support join multi entity query pass unit test

This commit is contained in:
xuejmnet 2021-08-22 16:43:26 +08:00
parent cb5b32c441
commit 2b4eaa6bd9
44 changed files with 739 additions and 492 deletions

2
.gitignore vendored
View File

@ -343,4 +343,4 @@ healthchecksdb
/src/Bd.ShopRent.Api/Properties/launchSettings.json
/src/Bd.ShopRent.DTO/__autoDTOConfig.json
/src/Bd.ShopRent.DTO/Bd.ShopRent.Dto.csproj
Configs/DbConfig.json
/test/ShardingCore.Test50/Configs/*

View File

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Sample.MySql.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions;
@ -21,6 +22,6 @@ namespace Sample.MySql.DbContexts
modelBuilder.ApplyConfiguration(new SysUserLogByMonthMap());
}
public string ModelChangeKey { get; set; }
public IRouteTail RouteTail { get; set; }
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Sample.SqlServer.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions;
@ -23,6 +24,6 @@ namespace Sample.SqlServer.DbContexts
modelBuilder.ApplyConfiguration(new SysTestMap());
}
public string ModelChangeKey { get; set; }
public IRouteTail RouteTail { get; set; }
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Sample.SqlServer3x.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions;
@ -25,6 +26,6 @@ namespace Sample.SqlServer3x
modelBuilder.ApplyConfiguration(new SysUserModMap());
}
public string ModelChangeKey { get; set; }
public IRouteTail RouteTail { get; set; }
}
}

View File

@ -10,10 +10,12 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage;
using ShardingCore;
using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
@ -21,9 +23,11 @@ namespace Samples.AbpSharding
{
public abstract class AbstractShardingAbpDbContext<T> : AbpDbContext, IShardingTableDbContext<T> where T : AbpDbContext, IShardingTableDbContext
{
private readonly string EMPTY_SHARDING_TAIL_ID = ShardingConstant.EMPTY_SHARDING_TAIL_ID + Guid.NewGuid().ToString("n");
private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>();
private readonly IVirtualTableManager _virtualTableManager;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IShardingDbContextFactory _shardingDbContextFactory;
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
private DbContextOptions<T> _dbContextOptions;
@ -34,6 +38,7 @@ namespace Samples.AbpSharding
{
_shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
_shardingDbContextOptionsBuilderConfig = ShardingContainer
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType);
@ -47,7 +52,7 @@ namespace Samples.AbpSharding
{
Type type = typeof(DbContextOptionsBuilder<>);
type = type.MakeGenericType(ActualDbContextType);
return (DbContextOptionsBuilder<T>)Activator.CreateInstance(type);
return (DbContextOptionsBuilder<T>) Activator.CreateInstance(type);
}
private DbContextOptions<T> CreateShareDbContextOptions()
@ -64,7 +69,7 @@ namespace Samples.AbpSharding
return dbContextOptionBuilder.Options;
}
private ShardingDbContextOptions GetShareShardingDbContextOptions(string tail)
private ShardingDbContextOptions GetShareShardingDbContextOptions(IRouteTail routeTail)
{
if (_dbContextOptions == null)
{
@ -77,30 +82,34 @@ namespace Samples.AbpSharding
}
}
return new ShardingDbContextOptions(_dbContextOptions, tail);
return new ShardingDbContextOptions(_dbContextOptions, routeTail);
}
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(string tail)
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(IRouteTail routeTail)
{
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), tail);
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), routeTail);
}
public DbContext GetDbContext(bool track, string tail)
public DbContext GetDbContext(bool track, IRouteTail routeTail)
{
if (track)
{
if (!_dbContextCaches.TryGetValue(tail, out var dbContext))
if (routeTail.IsMultiEntityQuery())
throw new ShardingCoreException("multi route not support track");
if(!(routeTail is ISingleQueryRouteTail singleQueryRouteTail))
throw new ShardingCoreException("multi route not support track");
var cacheKey = routeTail.GetRouteTailIdenty();
if (!_dbContextCaches.TryGetValue(cacheKey, out var dbContext))
{
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
_dbContextCaches.TryAdd(tail, dbContext);
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(routeTail));
_dbContextCaches.TryAdd(cacheKey, dbContext);
}
return dbContext;
}
else
{
var dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
return dbContext;
return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(routeTail));
}
}
@ -108,17 +117,15 @@ namespace Samples.AbpSharding
public DbContext CreateGenericDbContext<T>(T entity) where T : class
{
var tail = EMPTY_SHARDING_TAIL_ID;
var tail = string.Empty;
if (entity.IsShardingTable())
{
var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0];
tail = physicTable.Tail;
}
return GetDbContext(true, tail);
return GetDbContext(true, _routeTailFactory.Create(tail));
}
public override EntityEntry Add(object entity)
{
return CreateGenericDbContext(entity).Add(entity);

View File

@ -13,7 +13,6 @@ namespace ShardingCore.Core
*/
public class ShardingConstant
{
public const string EMPTY_SHARDING_TAIL_ID = "EMPTY_SHARDING_TAIL_ID";
public const string MULTI_ENTITIES_QUERY = "MULTI_ENTITIES_QUERY";
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:44:54
* @Email: 326308290@qq.com
*/
public interface IMultiQueryRouteTail:IRouteTail
{
/// <summary>
/// 获取对象类型的应该后缀
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
string GetEntityTail(Type entityType);
ISet<Type> GetEntityTypes();
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:39:19
* @Email: 326308290@qq.com
*/
public interface IRouteTail
{
string GetRouteTailIdenty();
bool IsMultiEntityQuery();
}
}

View File

@ -0,0 +1,17 @@
using System;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 14:58:19
* @Email: 326308290@qq.com
*/
public interface IRouteTailFactory
{
IRouteTail Create(string tail);
IRouteTail Create(RouteResult routeResult);
}
}

View File

@ -0,0 +1,19 @@
using System;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:44:22
* @Email: 326308290@qq.com
*/
public interface ISingleQueryRouteTail:IRouteTail
{
/// <summary>
/// 获取当前查询的后缀
/// </summary>
/// <returns></returns>
string GetTail();
}
}

View File

@ -0,0 +1,32 @@
using System;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.RouteTails;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 14:58:58
* @Email: 326308290@qq.com
*/
public class RouteTailFactory:IRouteTailFactory
{
public IRouteTail Create(string tail)
{
return new SingleQueryRouteTail(tail);
}
public IRouteTail Create(RouteResult routeResult)
{
if (routeResult == null || routeResult.ReplaceTables.IsEmpty())
throw new ShardingCoreException("route result null or empty");
if (routeResult.ReplaceTables.Count == 1)
return new SingleQueryRouteTail(routeResult);
return new MultiQueryRouteTail(routeResult);
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes.RouteTails
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:59:22
* @Email: 326308290@qq.com
*/
public class MultiQueryRouteTail:IMultiQueryRouteTail
{
private const string RANDOM_MODEL_CACHE_KEY = "RANDOM_MODEL_CACHE_KEY";
private readonly RouteResult _routeResult;
private readonly string _modelCacheKey;
private readonly ISet<Type> _entityTypes;
public MultiQueryRouteTail(RouteResult routeResult)
{
if (routeResult.ReplaceTables.IsEmpty() || routeResult.ReplaceTables.Count <= 1) throw new ArgumentException("route result replace tables must greater than 1");
_routeResult = routeResult;
_modelCacheKey = RANDOM_MODEL_CACHE_KEY+Guid.NewGuid().ToString("n");
_entityTypes = routeResult.ReplaceTables.Select(o=>o.EntityType).ToHashSet();
}
public string GetRouteTailIdenty()
{
return _modelCacheKey;
}
public bool IsMultiEntityQuery()
{
return true;
}
public string GetEntityTail(Type entityType)
{
return _routeResult.ReplaceTables.Single(o => o.EntityType == entityType).Tail;
}
public ISet<Type> GetEntityTypes()
{
return _entityTypes;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Linq;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes.RouteTails
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:46:07
* @Email: 326308290@qq.com
*/
public class SingleQueryRouteTail:ISingleQueryRouteTail
{
private readonly RouteResult _routeResult;
private readonly string _tail;
private readonly string _modelCacheKey;
public SingleQueryRouteTail(RouteResult routeResult)
{
if (routeResult.ReplaceTables.IsEmpty() || routeResult.ReplaceTables.Count > 1) throw new ArgumentException("route result replace tables must 1");
_routeResult = routeResult;
_tail= _routeResult.ReplaceTables.First().Tail;
_modelCacheKey = _tail.FormatRouteTail2ModelCacheKey();
}
public SingleQueryRouteTail(string tail)
{
_tail= tail;
_modelCacheKey = _tail.FormatRouteTail2ModelCacheKey();
}
public virtual string GetRouteTailIdenty()
{
return _modelCacheKey;
}
public virtual bool IsMultiEntityQuery()
{
return false;
}
public virtual string GetTail()
{
return _tail;
}
}
}

View File

@ -91,8 +91,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
//}
}
private bool EnableMultiEntityQuery = false;
public IEnumerable<RouteResult> Route<T>(Type shardingDbContextType, RouteRuleContext<T> routeRuleContext)
{
Dictionary<IVirtualTable, ISet<IPhysicTable>> routeMaps = new Dictionary<IVirtualTable, ISet<IPhysicTable>>();
@ -100,10 +98,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
var shardingEntities = queryEntities.Where(o => o.IsShardingTable());
if (shardingEntities.Count() > 1&& !EnableMultiEntityQuery)
{
throw new ShardingCoreException("not support multi entity query");
}
foreach (var shardingEntity in shardingEntities)
{
var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntity);

View File

@ -22,5 +22,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
}
public ISet<IPhysicTable> ReplaceTables { get; }
}
}

View File

@ -14,6 +14,8 @@ using ShardingCore.TableCreator;
using System;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.ShardingAccessors.Abstractions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore
{
@ -81,6 +83,7 @@ namespace ShardingCore
//services.AddSingleton(typeof(IVirtualTable<>), typeof(OneDbVirtualTable<>));
services.AddSingleton<IShardingAccessor, ShardingAccessor>();
services.AddSingleton<IShardingScopeFactory, ShardingScopeFactory>();
services.AddSingleton<IRouteTailFactory, RouteTailFactory>();
return services;
}

View File

@ -34,12 +34,12 @@ namespace ShardingCore.DbContexts
throw new ShardingCoreException(
$"{shardingDbContextType.FullName} cant found DefaultShardingDbContextCreatorConfig<{shardingDbContextType.Name}> should use {nameof(DIExtension.AddShardingDbContext)}");
}
var tail=shardingDbContextOptions.Tail;
var routeTail=shardingDbContextOptions.RouteTail;
var dbContext = shardingDbContextCreatorConfig.Creator(shardingDbContextOptions);
if (!string.IsNullOrWhiteSpace(tail) && dbContext is IShardingTableDbContext shardingTableDbContext)
if (dbContext is IShardingTableDbContext shardingTableDbContext)
{
shardingTableDbContext.SetShardingTableDbContextTail(tail);
shardingTableDbContext.RouteTail = routeTail;
}
var dbContextModel = dbContext.Model;
return dbContext;

View File

@ -1,5 +1,7 @@
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.DbContexts.ShardingDbContexts
{
@ -12,13 +14,13 @@ namespace ShardingCore.DbContexts.ShardingDbContexts
public class ShardingDbContextOptions
{
public ShardingDbContextOptions(DbContextOptions dbContextOptions, string tail)
public ShardingDbContextOptions(DbContextOptions dbContextOptions, IRouteTail routeTail)
{
RouteTail = routeTail;
DbContextOptions = dbContextOptions;
Tail = tail;
}
public IRouteTail RouteTail{ get; }
public DbContextOptions DbContextOptions { get; }
public string Tail { get; }
}
}

View File

@ -17,10 +17,10 @@ namespace ShardingCore.EFCores
{
public object Create(DbContext context)
{
if (context is IShardingTableDbContext shardingTableDbContext&&!string.IsNullOrWhiteSpace(shardingTableDbContext.ModelChangeKey))
if (context is IShardingTableDbContext shardingTableDbContext&&!string.IsNullOrWhiteSpace(shardingTableDbContext.RouteTail.GetRouteTailIdenty()))
{
return $"{context.GetType()}_{shardingTableDbContext.ModelChangeKey}";
return $"{context.GetType()}_{shardingTableDbContext.RouteTail.GetRouteTailIdenty()}";
}
else
{

View File

@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core.ShardingAccessors.Abstractions;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Extensions;
@ -21,9 +22,10 @@ namespace ShardingCore.EFCores
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingModelCustomizer<TShardingDbContext>: ModelCustomizer where TShardingDbContext:DbContext,IShardingDbContext
public class ShardingModelCustomizer<TShardingDbContext> : ModelCustomizer where TShardingDbContext : DbContext, IShardingDbContext
{
private Type _shardingDbContextType => typeof(TShardingDbContext);
private Type _shardingDbContextType => typeof(TShardingDbContext);
public ShardingModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies)
{
}
@ -33,12 +35,11 @@ namespace ShardingCore.EFCores
base.Customize(modelBuilder, context);
if (context is IShardingTableDbContext shardingTableDbContext)
{
var tail = shardingTableDbContext.GetShardingTableDbContextTail();
//if (tail.StartsWith("EMPTY_SHARDING_TAIL_ID"))
// tail = null;
if (!string.IsNullOrWhiteSpace(tail))
var isMultiEntityQuery = shardingTableDbContext.RouteTail.IsMultiEntityQuery();
if (!isMultiEntityQuery)
{
var singleQueryRouteTail = (ISingleQueryRouteTail) shardingTableDbContext.RouteTail;
var tail = singleQueryRouteTail.GetTail();
var virtualTableManager = ShardingContainer.Services.GetService<IVirtualTableManager>();
var typeMap = virtualTableManager.GetAllVirtualTables(_shardingDbContextType).Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet();
@ -49,26 +50,24 @@ namespace ShardingCore.EFCores
MappingToTable(entityType.ClrType, modelBuilder, tail);
}
}
//else
//{
// var shardingAccessor = ShardingContainer.Services.GetService<IShardingAccessor>();
// if (shardingAccessor?.ShardingContext != null)
// {
// var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable()).ToArray();
// foreach (var entityType in mutableEntityTypes)
// {
// var queryTail = shardingAccessor.ShardingContext.GetContextQueryTail(entityType.ClrType);
// if (queryTail != null)
// {
// MappingToTable(entityType.ClrType,modelBuilder, queryTail);
// }
// }
// }
//}
else
{
var multiQueryRouteTail = (IMultiQueryRouteTail) shardingTableDbContext.RouteTail;
var entityTypes = multiQueryRouteTail.GetEntityTypes();
var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable() && entityTypes.Contains(o.ClrType)).ToArray();
foreach (var entityType in mutableEntityTypes)
{
var queryTail = multiQueryRouteTail.GetEntityTail(entityType.ClrType);
if (queryTail != null)
{
MappingToTable(entityType.ClrType, modelBuilder, queryTail);
}
}
}
}
}
private void MappingToTable(Type clrType,ModelBuilder modelBuilder,string tail)
private void MappingToTable(Type clrType, ModelBuilder modelBuilder, string tail)
{
var shardingEntityConfig = ShardingKeyUtil.Parse(clrType);
var shardingEntity = shardingEntityConfig.ShardingEntityType;
@ -83,4 +82,4 @@ namespace ShardingCore.EFCores
entity.ToTable($"{tableName}{tailPrefix}{tail}");
}
}
}
}

View File

@ -104,9 +104,9 @@ namespace ShardingCore.EFCores
case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Max):
return GenericMergeExecute<TResult>(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Min):
return EnsureMergeExecute<TResult>(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Average):
@ -177,9 +177,9 @@ namespace ShardingCore.EFCores
case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max):
return GenericMergeExecute<TResult>(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min):
return EnsureMergeExecute<TResult>(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Average):
@ -224,13 +224,27 @@ namespace ShardingCore.EFCores
private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultEntityType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params);
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultEntityType }).Invoke(streamEngine, @params);
}
private TResult GenericMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType,resultType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
//typeof(TResult)==?resultType
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
}
@ -323,6 +337,19 @@ namespace ShardingCore.EFCores
var @params = async ? new object[] { cancellationToken } : new object[0];
return (Task<TResult>)streamEngineMethod.Invoke(streamEngine, @params);
}
private Task<TResult> GenericMergeExecuteAsync2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType,resultType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (Task<TResult>)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
}
private Task<TResult> EnsureMergeExecuteAsync2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, CancellationToken cancellationToken)
{
@ -392,9 +419,9 @@ namespace ShardingCore.EFCores
case nameof(Enumerable.All):
return EnsureMergeExecuteAsync<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max):
return GenericMergeExecuteAsync<TResult>(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
return GenericMergeExecuteAsync2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min):
return EnsureMergeExecuteAsync<TResult>(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
return GenericMergeExecuteAsync2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum):
return EnsureMergeExecuteAsync2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken);
case nameof(Enumerable.Average):

View File

@ -18,11 +18,24 @@ namespace ShardingCore.Extensions
{
public static Type GetQueryEntityType(this MethodCallExpression expression)
{
var rootQuery = expression.Arguments.FirstOrDefault(o => typeof(IQueryable).IsAssignableFrom(o.Type));
if (rootQuery == null)
throw new ShardingCoreException("expression error");
return rootQuery.Type.GetSequenceType();
return rootQuery.Type.GetSequenceType();
}
public static Type GetResultType(this MethodCallExpression expression)
{
if (expression.Arguments.Count == 1)
return expression.GetQueryEntityType();
var otherExpression = expression.Arguments.FirstOrDefault(o => !typeof(IQueryable).IsAssignableFrom(o.Type));
if (otherExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression)
{
return lambdaExpression.ReturnType;
}
throw new ShardingCoreException("expression error");
}
}
}
}

View File

@ -19,26 +19,32 @@ namespace ShardingCore.Extensions
public static class ShardingExtension
{
private static readonly string ShardingTableDbContextFormat = $"sharding_{Guid.NewGuid():n}_";
/// <summary>
/// 获取分表的tail
/// </summary>
/// <param name="dbContext"></param>
/// <returns></returns>
public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext)
{
return dbContext.ModelChangeKey?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty;
// /// <summary>
// /// 获取分表的tail
// /// </summary>
// /// <param name="dbContext"></param>
// /// <returns></returns>
// public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext)
// {
// return dbContext.RouteTail?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty;
//
// }
// /// <summary>
// /// 设置分表的tail
// /// </summary>
// /// <param name="dbContext"></param>
// /// <param name="tail"></param>
// public static void SetShardingTableDbContextTail(this IShardingTableDbContext dbContext, string tail)
// {
// if (!string.IsNullOrWhiteSpace(dbContext.ModelChangeKey))
// throw new ShardingCoreException($"repeat set ModelChangeKey in {dbContext.GetType().FullName}");
// dbContext.ModelChangeKey = tail.FormatRouteTail();
// }
}
/// <summary>
/// 设置分表的tail
/// </summary>
/// <param name="dbContext"></param>
/// <param name="tail"></param>
public static void SetShardingTableDbContextTail(this IShardingTableDbContext dbContext, string tail)
public static string FormatRouteTail2ModelCacheKey(this string originalTail)
{
if (!string.IsNullOrWhiteSpace(dbContext.ModelChangeKey))
throw new ShardingCoreException($"repeat set ModelChangeKey in {dbContext.GetType().FullName}");
dbContext.ModelChangeKey = $"{ShardingTableDbContextFormat}{tail}";
return $"{ShardingTableDbContextFormat}{originalTail}";
;
}
}
}

View File

@ -11,11 +11,15 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.RouteTails;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.EFCores;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
@ -33,9 +37,9 @@ namespace ShardingCore.Sharding
/// <typeparam name="T"></typeparam>
public abstract class AbstractShardingDbContext<T> : DbContext, IShardingTableDbContext<T> where T : DbContext, IShardingTableDbContext
{
private readonly string EMPTY_SHARDING_TAIL_ID = ShardingConstant.EMPTY_SHARDING_TAIL_ID+ Guid.NewGuid().ToString("n");
private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>();
private readonly IVirtualTableManager _virtualTableManager;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IShardingDbContextFactory _shardingDbContextFactory;
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
private DbContextOptions<T> _dbContextOptions;
@ -46,6 +50,7 @@ namespace ShardingCore.Sharding
{
_shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
_shardingDbContextOptionsBuilderConfig = ShardingContainer
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType);
@ -76,7 +81,7 @@ namespace ShardingCore.Sharding
return dbContextOptionBuilder.Options;
}
private ShardingDbContextOptions GetShareShardingDbContextOptions(string tail)
private ShardingDbContextOptions GetShareShardingDbContextOptions(IRouteTail routeTail)
{
if (_dbContextOptions == null)
{
@ -89,29 +94,34 @@ namespace ShardingCore.Sharding
}
}
return new ShardingDbContextOptions(_dbContextOptions, tail);
return new ShardingDbContextOptions(_dbContextOptions, routeTail);
}
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(string tail)
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(IRouteTail routeTail)
{
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), tail);
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), routeTail);
}
public DbContext GetDbContext(bool track, string tail)
public DbContext GetDbContext(bool track, IRouteTail routeTail)
{
if (track)
{
if (!_dbContextCaches.TryGetValue(tail, out var dbContext))
if (routeTail.IsMultiEntityQuery())
throw new ShardingCoreException("multi route not support track");
if(!(routeTail is ISingleQueryRouteTail singleQueryRouteTail))
throw new ShardingCoreException("multi route not support track");
var cacheKey = routeTail.GetRouteTailIdenty();
if (!_dbContextCaches.TryGetValue(cacheKey, out var dbContext))
{
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
_dbContextCaches.TryAdd(tail, dbContext);
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(routeTail));
_dbContextCaches.TryAdd(cacheKey, dbContext);
}
return dbContext;
}
else
{
return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(routeTail));
}
}
@ -119,14 +129,14 @@ namespace ShardingCore.Sharding
public DbContext CreateGenericDbContext<T>(T entity) where T : class
{
var tail = EMPTY_SHARDING_TAIL_ID;
var tail = string.Empty;
if (entity.IsShardingTable())
{
var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0];
tail = physicTable.Tail;
}
return GetDbContext(true, tail);
return GetDbContext(true, _routeTailFactory.Create(tail));
}

View File

@ -2,6 +2,8 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding.Abstractions
{
@ -19,12 +21,12 @@ namespace ShardingCore.Sharding.Abstractions
/// </summary>
Type ActualDbContextType { get;}
/// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>DbContext
/// create DbContext
/// </summary>
/// <param name="track">true not care dbcontext life, false need call dispose()</param>
/// <param name="tail"></param>
/// <param name="routeTail"></param>
/// <returns></returns>
DbContext GetDbContext(bool track,string tail);
DbContext GetDbContext(bool track,IRouteTail routeTail);
/// <summary>
/// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><E5B4B4>db context
/// </summary>

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding.Abstractions
{
@ -14,6 +15,6 @@ namespace ShardingCore.Sharding.Abstractions
*/
public interface IShardingTableDbContext
{
string ModelChangeKey { get; set; }
IRouteTail RouteTail { get; set; }
}
}

View File

@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ShardingCore.Core.Internal.PriorityQueues;
namespace ShardingCore.Sharding.Enumerators
namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
{
/*
* @Author: xjm

View File

@ -8,6 +8,8 @@ using ShardingCore.Sharding.Abstractions;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding
@ -24,7 +26,7 @@ namespace ShardingCore.Sharding
private readonly IQueryable<T> _source;
private readonly IShardingDbContext _shardingDbContext;
private readonly IRoutingRuleEngineFactory _tableRoutingRuleEngineFactory;
private readonly IShardingScopeFactory _shardingScopeFactory;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IQueryable<T> _reWriteSource;
//public IEnumerable<RouteResult> RouteResults { get; }
@ -36,13 +38,13 @@ namespace ShardingCore.Sharding
public SelectContext SelectContext { get;}
public GroupByContext GroupByContext { get; }
public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IShardingScopeFactory shardingScopeFactory)
public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IRouteTailFactory routeTailFactory)
{
//_shardingScopeFactory = shardingScopeFactory;
_source = source;
_shardingDbContext = shardingDbContext;
_tableRoutingRuleEngineFactory = tableRoutingRuleEngineFactory;
_shardingScopeFactory = shardingScopeFactory;
_routeTailFactory = routeTailFactory;
var reWriteResult = new ReWriteEngine<T>(source).ReWrite();
Skip = reWriteResult.Skip;
Take = reWriteResult.Take;
@ -67,18 +69,19 @@ namespace ShardingCore.Sharding
// _reWriteSource = reWriteResult.ReWriteQueryable;
//}
public DbContext CreateDbContext(string tail)
public DbContext CreateDbContext(RouteResult routeResult)
{
return _shardingDbContext.GetDbContext(false, tail);
var routeTail = _routeTailFactory.Create(routeResult);
return _shardingDbContext.GetDbContext(false, routeTail);
}
public IEnumerable<RouteResult> GetRouteResults()
{
return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source);
}
public ShardingScope CreateScope()
public IRouteTail Create(RouteResult routeResult)
{
return _shardingScopeFactory.CreateScope();
return _routeTailFactory.Create(routeResult);
}
public IQueryable<T> GetReWriteQueryable()

View File

@ -2,6 +2,7 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Sharding.Abstractions;
using System.Linq;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding
{
@ -14,17 +15,17 @@ namespace ShardingCore.Sharding
public class StreamMergeContextFactory:IStreamMergeContextFactory
{
private readonly IRoutingRuleEngineFactory _routingRuleEngineFactory;
private readonly IShardingScopeFactory _shardingScopeFactory;
private readonly IRouteTailFactory _routeTailFactory;
public StreamMergeContextFactory(
IRoutingRuleEngineFactory routingRuleEngineFactory,IShardingScopeFactory shardingScopeFactory)
IRoutingRuleEngineFactory routingRuleEngineFactory,IRouteTailFactory routeTailFactory)
{
_routingRuleEngineFactory = routingRuleEngineFactory;
_shardingScopeFactory = shardingScopeFactory;
_routeTailFactory = routeTailFactory;
}
public StreamMergeContext<T> Create<T>(IQueryable<T> queryable,IShardingDbContext shardingDbContext)
{
return new StreamMergeContext<T>(queryable,shardingDbContext, _routingRuleEngineFactory, _shardingScopeFactory);
return new StreamMergeContext<T>(queryable,shardingDbContext, _routingRuleEngineFactory, _routeTailFactory);
}
}
}

View File

@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public abstract class AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TResult>: AbstractEnsureMethodCallInMemoryAsyncMergeEngine<TEntity, TResult>
public abstract class AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TResult,TSelect>: AbstractEnsureMethodCallInMemoryAsyncMergeEngine<TEntity, TResult>
{
protected AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
@ -26,7 +26,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
var secondExpression = GetSecondExpression();
if (secondExpression != null)
{
if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TResult>> selector)
if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TSelect>> selector)
{
return queryable.Select(selector);
}

View File

@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public abstract class AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity>:AbstractGenericMethodCallInMemoryAsyncMergeEngine<TEntity>
public abstract class AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TSelect>:AbstractGenericMethodCallInMemoryAsyncMergeEngine<TEntity>
{
public AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{
@ -25,7 +25,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
var secondExpression = GetSecondExpression();
if (secondExpression != null)
{
if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TResult>> selector)
if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TSelect>> selector)
{
return queryable.Select(selector);
}

View File

@ -6,13 +6,9 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{
@ -52,7 +48,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{
if (methodCallExpression.Arguments.Count == 2)
{
#if !EFCORE2
throw new InvalidOperationException(methodCallExpression.Print());
#endif
@ -68,30 +63,27 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
protected abstract IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression);
private IQueryable CreateAsyncExecuteQueryable<TResult>(RouteResult routeResult)
{
var shardingDbContext = _mergeContext.CreateDbContext(routeResult);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<TEntity>) GetStreamMergeContext().GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
return newFilterQueryable;
}
public async Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken())
{
var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult =>
{
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(async () =>
{
try
{
//using (var scope = _mergeContext.CreateScope())
//{
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<TEntity>)GetStreamMergeContext().GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
return await efQuery(newFilterQueryable);
var asyncExecuteQueryable = CreateAsyncExecuteQueryable<TResult>(routeResult);
return await efQuery(asyncExecuteQueryable);
//}
}
catch (Exception e)
@ -104,39 +96,26 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
return (await Task.WhenAll(enumeratorTasks)).ToList();
}
public List<TResult> Execute<TResult>(Func<IQueryable, TResult> efQuery, CancellationToken cancellationToken = new CancellationToken())
{
var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult =>
{
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(() =>
{
try
{
//using (var scope = _mergeContext.CreateScope())
//{
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<TEntity>)GetStreamMergeContext().GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
var query = efQuery(newFilterQueryable);
return query;
//}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
{
try
{
var asyncExecuteQueryable = CreateAsyncExecuteQueryable<TResult>(routeResult);
var query = efQuery(asyncExecuteQueryable);
return query;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
return Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult().ToList();
}
@ -151,6 +130,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{
return _mergeContext;
}
public IQueryable<TEntity> GetQueryable()
{
return _queryable;
@ -165,6 +145,5 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{
return _secondExpression;
}
}
}
}

View File

@ -23,7 +23,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Email: 326308290@qq.com
*/
public class AverageAsyncInMemoryMergeEngine<TEntity, TEnsureResult> :
AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult>
AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult,TEnsureResult>
{
public AverageAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression,
IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)

View File

@ -19,7 +19,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class MaxAsyncInMemoryMergeEngine<TEntity>: AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity>
public class MaxAsyncInMemoryMergeEngine<TEntity,TSelect>: AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TSelect>
{
public MaxAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{

View File

@ -20,7 +20,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class MinAsyncInMemoryMergeEngine<TEntity> : AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity>
public class MinAsyncInMemoryMergeEngine<TEntity,TSelect> : AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TSelect>
{
public MinAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{

View File

@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class SumAsyncInMemoryMergeEngine<TEntity, TEnsureResult> : AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult>
public class SumAsyncInMemoryMergeEngine<TEntity, TEnsureResult> : AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult,TEnsureResult>
{
public SumAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
@ -26,7 +26,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines
*/
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>, IDisposable
{
private readonly StreamMergeContext<T> _mergeContext;
private readonly ICollection<DbContext> _parllelDbbContexts;
@ -47,7 +46,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines
}
#endif
#if EFCORE2
private async Task<IAsyncEnumerator<T>> GetAsyncEnumerator(IQueryable<T> newQueryable)
{
var enumator = newQueryable.AsAsyncEnumerable().GetEnumerator();
@ -64,38 +62,34 @@ namespace ShardingCore.Sharding.StreamMergeEngines
#endif
#if EFCORE2
IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator()
{
return GetShardingEnumerator();
}
#endif
private IQueryable<T> CreateAsyncExecuteQueryable(RouteResult routeResult)
{
var shardingDbContext = _mergeContext.CreateDbContext(routeResult);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<T>) _mergeContext.GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
private IAsyncEnumerator<T> GetShardingEnumerator()
{
var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult =>
{
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(async () =>
{
try
{
//using (var scope = _mergeContext.CreateScope())
//{
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<T>)_mergeContext.GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newQueryable = CreateAsyncExecuteQueryable(routeResult);
var asyncEnumerator = await GetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<T>(asyncEnumerator);
//}
}
catch (Exception e)
{
@ -126,27 +120,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult =>
{
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(() =>
{
try
{
//using (var scope = _mergeContext.CreateScope())
//{
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = CreateAsyncExecuteQueryable(routeResult);
var newQueryable = (IQueryable<T>)_mergeContext.GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var enumerator = GetEnumerator(newQueryable);
return new StreamMergeEnumerator<T>(enumerator);
//}
var enumerator = GetEnumerator(newQueryable);
return new StreamMergeEnumerator<T>(enumerator);
}
catch (Exception e)
{
@ -187,4 +168,4 @@ namespace ShardingCore.Sharding.StreamMergeEngines
}
}
}
}
}

View File

@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts;
@ -31,12 +32,13 @@ namespace ShardingCore
private readonly IVirtualTableManager _virtualTableManager;
private readonly IShardingTableCreator _tableCreator;
private readonly ILogger<ShardingBootstrapper> _logger;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IShardingDbContextFactory _shardingDbContextFactory;
public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions,
IVirtualTableManager virtualTableManager
, IShardingTableCreator tableCreator, ILogger<ShardingBootstrapper> logger,
IShardingDbContextFactory shardingDbContextFactory)
IShardingDbContextFactory shardingDbContextFactory,IRouteTailFactory routeTailFactory)
{
ShardingContainer.SetServices(serviceProvider);
_serviceProvider = serviceProvider;
@ -44,6 +46,7 @@ namespace ShardingCore
_virtualTableManager = virtualTableManager;
_tableCreator = tableCreator;
_logger = logger;
_routeTailFactory = routeTailFactory;
_shardingDbContextFactory = shardingDbContextFactory;
}
@ -122,7 +125,7 @@ namespace ShardingCore
{
if (context is IShardingDbContext shardingDbContext)
{
var dbContext = shardingDbContext.GetDbContext(false,string.Empty);
var dbContext = shardingDbContext.GetDbContext(false,_routeTailFactory.Create(string.Empty));
var modelCacheSyncObject = dbContext.GetModelCacheSyncObject();
lock (modelCacheSyncObject)

View File

@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts;
using ShardingCore.DbContexts.Abstractions;
@ -31,15 +32,17 @@ namespace ShardingCore.TableCreator
private readonly IVirtualTableManager _virtualTableManager;
private readonly IServiceProvider _serviceProvider;
private readonly IEnumerable<IShardingConfigOption> _shardingConfigOptions;
private readonly IRouteTailFactory _routeTailFactory;
public ShardingTableCreator(ILogger<ShardingTableCreator> logger, IShardingDbContextFactory shardingDbContextFactory,
IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions)
IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions,IRouteTailFactory routeTailFactory)
{
_logger = logger;
_shardingDbContextFactory = shardingDbContextFactory;
_virtualTableManager = virtualTableManager;
_serviceProvider = serviceProvider;
_shardingConfigOptions = shardingConfigOptions;
_routeTailFactory = routeTailFactory;
}
public void CreateTable<TShardingDbContext, T>(string tail) where TShardingDbContext : DbContext, IShardingDbContext where T : class, IShardingTable
@ -69,7 +72,7 @@ namespace ShardingCore.TableCreator
var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntityType);
var dbContext = (DbContext)serviceScope.ServiceProvider.GetService(shardingDbContextType);
var shardingDbContext = (IShardingDbContext)dbContext;
var context = shardingDbContext.GetDbContext(false,tail);
var context = shardingDbContext.GetDbContext(false,_routeTailFactory.Create(tail));
var modelCacheSyncObject = context.GetModelCacheSyncObject();

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50.MySql.Domain.Maps;
@ -26,6 +27,6 @@ namespace ShardingCore.Test50.MySql
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
}
public string ModelChangeKey { get; set; }
public IRouteTail RouteTail { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50.Domain.Maps;
@ -26,6 +27,6 @@ namespace ShardingCore.Test50
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
}
public string ModelChangeKey { get; set; }
public IRouteTail RouteTail { get; set; }
}
}

View File

@ -22,6 +22,8 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<None Remove="Configs\MacDbConfig.json" />
<Content Include="Configs\MacDbConfig.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ShardingCore\ShardingCore.csproj" />

View File

@ -67,307 +67,307 @@ namespace ShardingCore.Test50
}
}
//[Fact]
//public async Task ToList_Join_Test()
//{
// var list = await (from u in _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="1" || o.Id=="1000")
// join salary in _virtualDbContext.Set<SysUserSalary>()
// on u.Id equals salary.UserId
// select new
// {
// u.Id,
// u.Age,
// Salary = salary.Salary,
// DateOfMonth = salary.DateOfMonth,
// Name = u.Name
// }).ToListAsync();
// var list2 = list.OrderBy(o=>o.Age).ToList();
// Assert.Equal(24000, list.Count());
// Assert.Equal(24, list.Count(o => o.Name == "name_200"));
[Fact]
public async Task ToList_Join_Test()
{
var list = await (from u in _virtualDbContext.Set<SysUserMod>()
join salary in _virtualDbContext.Set<SysUserSalary>()
on u.Id equals salary.UserId
select new
{
u.Id,
u.Age,
Salary = salary.Salary,
DateOfMonth = salary.DateOfMonth,
Name = u.Name
}).ToListAsync();
var list2 = list.OrderBy(o=>o.Age).Select(o=>o.Age).Distinct().ToList();
Assert.Equal(24000, list.Count());
Assert.Equal(24, list.Count(o => o.Name == "name_200"));
// var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
// join salary in _virtualDbContext.Set<SysUserSalary>()
// on u.Id equals salary.UserId
// select new
// {
// Salary = salary.Salary,
// DateOfMonth = salary.DateOfMonth,
// Name = u.Name
// });
// var list1 = await queryable.ToListAsync();
// Assert.Equal(24, list1.Count());
// Assert.DoesNotContain(list1, o => o.Name != "name_300");
//}
var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
join salary in _virtualDbContext.Set<SysUserSalary>()
on u.Id equals salary.UserId
select new
{
Salary = salary.Salary,
DateOfMonth = salary.DateOfMonth,
Name = u.Name
});
var list1 = await queryable.ToListAsync();
Assert.Equal(24, list1.Count());
Assert.DoesNotContain(list1, o => o.Name != "name_300");
}
//[Fact]
//public async Task ToList_OrderBy_Asc_Desc_Test()
//{
// var modascs = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToShardingListAsync();
// Assert.Equal(1000, modascs.Count);
// var i = 1;
// foreach (var age in modascs)
// {
// Assert.Equal(i, age.Age);
// i++;
// }
[Fact]
public async Task ToList_OrderBy_Asc_Desc_Test()
{
var modascs = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToListAsync();
Assert.Equal(1000, modascs.Count);
var i = 1;
foreach (var age in modascs)
{
Assert.Equal(i, age.Age);
i++;
}
// var moddescs = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToShardingListAsync();
// Assert.Equal(1000, moddescs.Count);
// var j = 1000;
// foreach (var age in moddescs)
// {
// Assert.Equal(j, age.Age);
// j--;
// }
//}
var moddescs = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToListAsync();
Assert.Equal(1000, moddescs.Count);
var j = 1000;
foreach (var age in moddescs)
{
Assert.Equal(j, age.Age);
j--;
}
}
//[Fact]
//public async Task ToList_Id_In_Test()
//{
// var ids = new[] {"1", "2", "3", "4"};
// var sysUserMods = await _virtualDbContext.Set<SysUserMod>().Where(o => ids.Contains(o.Id)).ToShardingListAsync();
// foreach (var id in ids)
// {
// Assert.Contains(sysUserMods, o => o.Id == id);
// }
[Fact]
public async Task ToList_Id_In_Test()
{
var ids = new[] {"1", "2", "3", "4"};
var sysUserMods = await _virtualDbContext.Set<SysUserMod>().Where(o => ids.Contains(o.Id)).ToListAsync();
foreach (var id in ids)
{
Assert.Contains(sysUserMods, o => o.Id == id);
}
// Assert.DoesNotContain(sysUserMods, o => o.Age > 4);
//}
Assert.DoesNotContain(sysUserMods, o => o.Age > 4);
}
//[Fact]
//public async Task ToList_Id_Eq_Test()
//{
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "3").ToShardingListAsync();
// Assert.Single(mods);
// Assert.Equal("3", mods[0].Id);
//}
[Fact]
public async Task ToList_Id_Eq_Test()
{
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "3").ToListAsync();
Assert.Single(mods);
Assert.Equal("3", mods[0].Id);
}
//[Fact]
//public async Task ToList_Id_Not_Eq_Test()
//{
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").ToShardingListAsync();
// Assert.Equal(999, mods.Count);
// Assert.DoesNotContain(mods, o => o.Id == "3");
//}
[Fact]
public async Task ToList_Id_Not_Eq_Test()
{
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").ToListAsync();
Assert.Equal(999, mods.Count);
Assert.DoesNotContain(mods, o => o.Id == "3");
}
//[Fact]
//public async Task ToList_Id_Not_Eq_Skip_Test()
//{
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderBy(o => o.Age).Skip(2).ToShardingListAsync();
// Assert.Equal(997, mods.Count);
// Assert.DoesNotContain(mods, o => o.Id == "3");
// Assert.Equal(4, mods[0].Age);
// Assert.Equal(5, mods[1].Age);
[Fact]
public async Task ToList_Id_Not_Eq_Skip_Test()
{
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderBy(o => o.Age).Skip(2).ToListAsync();
Assert.Equal(997, mods.Count);
Assert.DoesNotContain(mods, o => o.Id == "3");
Assert.Equal(4, mods[0].Age);
Assert.Equal(5, mods[1].Age);
// var modsDesc = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderByDescending(o => o.Age).Skip(13).ToShardingListAsync();
// Assert.Equal(986, modsDesc.Count);
// Assert.DoesNotContain(mods, o => o.Id == "3");
// Assert.Equal(987, modsDesc[0].Age);
// Assert.Equal(986, modsDesc[1].Age);
//}
var modsDesc = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderByDescending(o => o.Age).Skip(13).ToListAsync();
Assert.Equal(986, modsDesc.Count);
Assert.DoesNotContain(mods, o => o.Id == "3");
Assert.Equal(987, modsDesc[0].Age);
Assert.Equal(986, modsDesc[1].Age);
}
//[Fact]
//public async Task ToList_Name_Eq_Test()
//{
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_3").ToShardingListAsync();
// Assert.Single(mods);
// Assert.Equal("3", mods[0].Id);
//}
[Fact]
public async Task ToList_Name_Eq_Test()
{
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_3").ToListAsync();
Assert.Single(mods);
Assert.Equal("3", mods[0].Id);
}
//[Fact]
//public async Task ToList_Id_Eq_Not_In_Db_Test()
//{
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1001").ToShardingListAsync();
// Assert.Empty(mods);
//}
[Fact]
public async Task ToList_Id_Eq_Not_In_Db_Test()
{
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1001").ToListAsync();
Assert.Empty(mods);
}
//[Fact]
//public async Task ToList_Name_Eq_Not_In_Db_Test()
//{
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ToShardingListAsync();
// Assert.Empty(mods);
//}
[Fact]
public async Task ToList_Name_Eq_Not_In_Db_Test()
{
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ToListAsync();
Assert.Empty(mods);
}
//[Fact]
//public async Task FirstOrDefault_Order_By_Id_Test()
//{
// var sysUserModAge = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ShardingFirstOrDefaultAsync();
// Assert.True(sysUserModAge != null && sysUserModAge.Id == "1");
// var sysUserModAgeDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ShardingFirstOrDefaultAsync();
// Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000");
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Id).ShardingFirstOrDefaultAsync();
// Assert.True(sysUserMod != null && sysUserMod.Id == "1");
[Fact]
public async Task FirstOrDefault_Order_By_Id_Test()
{
var sysUserModAge = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).FirstOrDefaultAsync();
Assert.True(sysUserModAge != null && sysUserModAge.Id == "1");
var sysUserModAgeDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).FirstOrDefaultAsync();
Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000");
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Id).FirstOrDefaultAsync();
Assert.True(sysUserMod != null && sysUserMod.Id == "1");
// var sysUserModDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Id).ShardingFirstOrDefaultAsync();
// Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999");
//}
var sysUserModDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Id).FirstOrDefaultAsync();
Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999");
}
//[Fact]
//public async Task FirstOrDefault2()
//{
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1").ShardingFirstOrDefaultAsync();
// Assert.NotNull(sysUserMod);
// Assert.True(sysUserMod.Id == "1");
//}
[Fact]
public async Task FirstOrDefault2()
{
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1").FirstOrDefaultAsync();
Assert.NotNull(sysUserMod);
Assert.True(sysUserMod.Id == "1");
}
//[Fact]
//public async Task FirstOrDefault3()
//{
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2").ShardingFirstOrDefaultAsync();
// Assert.NotNull(sysUserMod);
// Assert.Equal("2", sysUserMod.Id);
//}
[Fact]
public async Task FirstOrDefault3()
{
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2").FirstOrDefaultAsync();
Assert.NotNull(sysUserMod);
Assert.Equal("2", sysUserMod.Id);
}
//[Fact]
//public async Task FirstOrDefault4()
//{
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "1").ShardingFirstOrDefaultAsync();
// Assert.NotNull(sysUserMod);
// Assert.True(sysUserMod.Id != "1");
//}
[Fact]
public async Task FirstOrDefault4()
{
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "1").FirstOrDefaultAsync();
Assert.NotNull(sysUserMod);
Assert.True(sysUserMod.Id != "1");
}
//[Fact]
//public async Task FirstOrDefault5()
//{
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ShardingFirstOrDefaultAsync();
// Assert.Null(sysUserMod);
//}
[Fact]
public async Task FirstOrDefault5()
{
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").FirstOrDefaultAsync();
Assert.Null(sysUserMod);
}
//[Fact]
//public async Task Count_Test()
//{
// var a = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1000").ShardingCountAsync();
// Assert.Equal(1, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").ShardingCountAsync();
// Assert.Equal(999, b);
//}
[Fact]
public async Task Count_Test()
{
var a = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1000").CountAsync();
Assert.Equal(1, a);
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").CountAsync();
Assert.Equal(999, b);
}
//[Fact]
//public async Task Sum_Test()
//{
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingSumAsync(o => o.Age);
// var expected = 0;
// for (int i = 1; i <= 1000; i++)
// {
// expected += i;
// }
[Fact]
public async Task Sum_Test()
{
var a = await _virtualDbContext.Set<SysUserMod>().SumAsync(o => o.Age);
var expected = 0;
for (int i = 1; i <= 1000; i++)
{
expected += i;
}
// Assert.Equal(expected, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").ShardingSumAsync(o => o.Age);
// Assert.Equal(expected - 1000, b);
//}
Assert.Equal(expected, a);
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").SumAsync(o => o.Age);
Assert.Equal(expected - 1000, b);
}
//[Fact]
//public async Task Max_Test()
//{
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingMaxAsync(o => o.Age);
// Assert.Equal(1000, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").ShardingMaxAsync(o => o.Age);
// Assert.Equal(999, b);
// var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age < 500).ShardingMaxAsync(o => o.Age);
// Assert.Equal(499, c);
// var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age <= 500).ShardingMaxAsync(o => o.Age);
// Assert.Equal(500, e);
//}
[Fact]
public async Task Max_Test()
{
var a = await _virtualDbContext.Set<SysUserMod>().MaxAsync(o => o.Age);
Assert.Equal(1000, a);
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").MaxAsync(o => o.Age);
Assert.Equal(999, b);
var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age < 500).MaxAsync(o => o.Age);
Assert.Equal(499, c);
var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age <= 500).MaxAsync(o => o.Age);
Assert.Equal(500, e);
}
//[Fact]
//public async Task Max_Join_Test()
//{
// var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
// join salary in _virtualDbContext.Set<SysUserSalary>()
// on u.Id equals salary.UserId
// select new
// {
// Salary = salary.Salary,
// DateOfMonth = salary.DateOfMonth,
// Name = u.Name
// });
// var maxSalary = await queryable.ShardingMaxAsync(o => o.Salary);
// Assert.Equal(1390000, maxSalary);
//}
[Fact]
public async Task Max_Join_Test()
{
var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
join salary in _virtualDbContext.Set<SysUserSalary>()
on u.Id equals salary.UserId
select new
{
Salary = salary.Salary,
DateOfMonth = salary.DateOfMonth,
Name = u.Name
});
var maxSalary = await queryable.MaxAsync(o => o.Salary);
Assert.Equal(1390000, maxSalary);
}
//[Fact]
//public async Task Min_Test()
//{
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingMinAsync(o => o.Age);
// Assert.Equal(1, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").ShardingMinAsync(o => o.Age);
// Assert.Equal(2, b);
// var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).ShardingMinAsync(o => o.Age);
// Assert.Equal(501, c);
// var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).ShardingMinAsync(o => o.Age);
// Assert.Equal(500, e);
//}
[Fact]
public async Task Min_Test()
{
var a = await _virtualDbContext.Set<SysUserMod>().MinAsync(o => o.Age);
Assert.Equal(1, a);
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").MinAsync(o => o.Age);
Assert.Equal(2, b);
var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).MinAsync(o => o.Age);
Assert.Equal(501, c);
var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).MinAsync(o => o.Age);
Assert.Equal(500, e);
}
//[Fact]
//public async Task Any_Test()
//{
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingAnyAsync(o => o.Age == 100);
// Assert.True(a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").ShardingAnyAsync(o => o.Age == 1);
// Assert.False(b);
// var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).ShardingAnyAsync(o => o.Age <= 500);
// Assert.False(c);
// var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).ShardingAnyAsync(o => o.Age <= 500);
// Assert.True(e);
//}
[Fact]
public async Task Any_Test()
{
var a = await _virtualDbContext.Set<SysUserMod>().AnyAsync(o => o.Age == 100);
Assert.True(a);
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").AnyAsync(o => o.Age == 1);
Assert.False(b);
var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).AnyAsync(o => o.Age <= 500);
Assert.False(c);
var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).AnyAsync(o => o.Age <= 500);
Assert.True(e);
}
//[Fact]
//public async Task Group_Test()
//{
// var ids = new[] {"200", "300"};
// var dateOfMonths = new[] {202111, 202110};
// var group = await (from u in _virtualDbContext.Set<SysUserSalary>()
// .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
// group u by new
// {
// UId = u.UserId
// }
// into g
// select new
// {
// GroupUserId = g.Key.UId,
// Count = g.Count(),
// TotalSalary = g.Sum(o => o.Salary),
// AvgSalary = g.Average(o => o.Salary),
// AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
// MinSalary = g.Min(o => o.Salary),
// MaxSalary = g.Max(o => o.Salary)
// }).ToShardingListAsync();
// Assert.Equal(2, group.Count);
// Assert.Equal(2, group[0].Count);
// Assert.Equal(2260000, group[0].TotalSalary);
// Assert.Equal(1130000, group[0].AvgSalary);
// Assert.Equal(11300, group[0].AvgSalaryDecimal);
// Assert.Equal(1120000, group[0].MinSalary);
// Assert.Equal(1140000, group[0].MaxSalary);
//}
//[Fact]
//public async Task Group_API_Test()
//{
// var ids = new[] {"200", "300"};
// var dateOfMonths = new[] {202111, 202110};
// var group = await _virtualDbContext.Set<SysUserSalary>()
// .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
// .ShardingGroupByAsync(g => new {UId = g.UserId}, g => new
// {
// GroupUserId = g.Key.UId,
// Count = g.Count(),
// TotalSalary = g.Sum(o => o.Salary),
// AvgSalary = g.Average(o => o.Salary),
// AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
// MinSalary = g.Min(o => o.Salary),
// MaxSalary = g.Max(o => o.Salary)
// });
// Assert.Equal(2, group.Count);
// Assert.Equal(2, group[0].Count);
// Assert.Equal(2260000, group[0].TotalSalary);
// Assert.Equal(1130000, group[0].AvgSalary);
// Assert.Equal(11300, group[0].AvgSalaryDecimal);
// Assert.Equal(1120000, group[0].MinSalary);
// Assert.Equal(1140000, group[0].MaxSalary);
//}
[Fact]
public async Task Group_Test()
{
var ids = new[] {"200", "300"};
var dateOfMonths = new[] {202111, 202110};
var group = await (from u in _virtualDbContext.Set<SysUserSalary>()
.Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
group u by new
{
UId = u.UserId
}
into g
select new
{
GroupUserId = g.Key.UId,
Count = g.Count(),
TotalSalary = g.Sum(o => o.Salary),
AvgSalary = g.Average(o => o.Salary),
AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
MinSalary = g.Min(o => o.Salary),
MaxSalary = g.Max(o => o.Salary)
}).ToListAsync();
Assert.Equal(2, group.Count);
Assert.Equal(2, group[0].Count);
Assert.Equal(2260000, group[0].TotalSalary);
Assert.Equal(1130000, group[0].AvgSalary);
Assert.Equal(11300, group[0].AvgSalaryDecimal);
Assert.Equal(1120000, group[0].MinSalary);
Assert.Equal(1140000, group[0].MaxSalary);
}
// [Fact]
// public async Task Group_API_Test()
// {
// var ids = new[] {"200", "300"};
// var dateOfMonths = new[] {202111, 202110};
// var group = await _virtualDbContext.Set<SysUserSalary>()
// .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
// .ShardingGroupByAsync(g => new {UId = g.UserId}, g => new
// {
//
// GroupUserId = g.Key.UId,
// Count = g.Count(),
// TotalSalary = g.Sum(o => o.Salary),
// AvgSalary = g.Average(o => o.Salary),
// AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
// MinSalary = g.Min(o => o.Salary),
// MaxSalary = g.Max(o => o.Salary)
// });
// Assert.Equal(2, group.Count);
// Assert.Equal(2, group[0].Count);
// Assert.Equal(2260000, group[0].TotalSalary);
// Assert.Equal(1130000, group[0].AvgSalary);
// Assert.Equal(11300, group[0].AvgSalaryDecimal);
// Assert.Equal(1120000, group[0].MinSalary);
// Assert.Equal(1140000, group[0].MaxSalary);
// }
}
}

View File

@ -38,6 +38,7 @@ namespace ShardingCore.Test50
.ConfigureAppConfiguration(builder =>
{
builder.AddJsonFile("Configs/DbConfig.json");
builder.AddJsonFile("Configs/MacDbConfig.json");
});
}
@ -47,13 +48,13 @@ namespace ShardingCore.Test50
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
{
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServerMac")["ConnectionString"])
,op =>
{
op.EnsureCreatedWithOutShardingTable = false;
op.CreateShardingTableOnStart = false;
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),
builder=> builder.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]).UseLoggerFactory(efLogger));
builder=> builder.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServerMac")["ConnectionString"]).UseLoggerFactory(efLogger));
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
});