From 2b4eaa6bd94c00c570144de6565fbf145120e5a0 Mon Sep 17 00:00:00 2001 From: xuejmnet <326308290@qq.com> Date: Sun, 22 Aug 2021 16:43:26 +0800 Subject: [PATCH] support join multi entity query pass unit test --- .gitignore | 2 +- .../DbContexts/DefaultTableDbContext.cs | 3 +- .../DbContexts/DefaultTableDbContext.cs | 3 +- .../Sample.SqlServer3x/DefaultDbContext.cs | 3 +- .../AbstractShardingAbpDbContext.cs | 39 +- src/ShardingCore/Core/ShardingConstant.cs | 1 - .../Abstractions/IMultiQueryRouteTail.cs | 23 + .../VirtualRoutes/Abstractions/IRouteTail.cs | 16 + .../Abstractions/IRouteTailFactory.cs | 17 + .../Abstractions/ISingleQueryRouteTail.cs | 19 + .../Core/VirtualRoutes/RouteTailFactory.cs | 32 + .../RouteTails/MultiQueryRouteTail.cs | 50 ++ .../RouteTails/SingleQueryRouteTail.cs | 49 ++ .../RoutingRuleEngine/QueryRouteRuleEngine.cs | 6 - .../RoutingRuleEngine/RouteResult.cs | 1 + src/ShardingCore/DIExtension.cs | 3 + .../DbContexts/ShardingDbContextFactory.cs | 6 +- .../ShardingDbContextOptions.cs | 8 +- .../EFCores/ShardingModelCacheKeyFactory.cs | 4 +- .../EFCores/ShardingModelCustomizer.cs | 51 +- .../EFCores/ShardingQueryCompiler.cs | 41 +- .../Extensions/ShardingComplierExtension.cs | 19 +- .../Extensions/ShardingExtension.cs | 42 +- .../Sharding/AbstractShardingDbContext.cs | 34 +- .../Abstractions/IShardingDbContext.cs | 8 +- .../Abstractions/IShardingTableDbContext.cs | 3 +- .../MultiOrderStreamMergeAsyncEnumerator.cs | 3 +- .../Sharding/StreamMergeContext.cs | 17 +- .../Sharding/StreamMergeContextFactory.cs | 9 +- ...hodCallSelectorInMemoryAsyncMergeEngine.cs | 4 +- ...hodCallSelectorInMemoryAsyncMergeEngine.cs | 4 +- .../AbstractInMemoryAsyncMergeEngine.cs | 77 +-- .../AverageAsyncInMemoryMergeEngine.cs | 2 +- .../MaxAsyncInMemoryMergeEngine.cs | 2 +- .../MinAsyncInMemoryMergeEngine.cs | 2 +- .../SumAsyncInMemoryMergeEngine.cs | 2 +- .../AsyncEnumerableStreamMergeEngine.cs | 49 +- src/ShardingCore/ShardingBootstrapper.cs | 7 +- .../TableCreator/ShardingTableCreator.cs | 7 +- .../DefaultDbContext.cs | 3 +- test/ShardingCore.Test50/DefaultDbContext.cs | 3 +- .../ShardingCore.Test50.csproj | 2 + test/ShardingCore.Test50/ShardingTest.cs | 550 +++++++++--------- test/ShardingCore.Test50/Startup.cs | 5 +- 44 files changed, 739 insertions(+), 492 deletions(-) create mode 100644 src/ShardingCore/Core/VirtualRoutes/Abstractions/IMultiQueryRouteTail.cs create mode 100644 src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTail.cs create mode 100644 src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTailFactory.cs create mode 100644 src/ShardingCore/Core/VirtualRoutes/Abstractions/ISingleQueryRouteTail.cs create mode 100644 src/ShardingCore/Core/VirtualRoutes/RouteTailFactory.cs create mode 100644 src/ShardingCore/Core/VirtualRoutes/RouteTails/MultiQueryRouteTail.cs create mode 100644 src/ShardingCore/Core/VirtualRoutes/RouteTails/SingleQueryRouteTail.cs diff --git a/.gitignore b/.gitignore index 675445f0..c1338bd1 100644 --- a/.gitignore +++ b/.gitignore @@ -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/* diff --git a/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs b/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs index 25a62f37..7e081195 100644 --- a/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs +++ b/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs @@ -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; } } } diff --git a/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs b/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs index 66a936f2..e93843ac 100644 --- a/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs +++ b/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs @@ -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; } } } diff --git a/samples/Sample.SqlServer3x/DefaultDbContext.cs b/samples/Sample.SqlServer3x/DefaultDbContext.cs index d9a12cf6..f5c0e549 100644 --- a/samples/Sample.SqlServer3x/DefaultDbContext.cs +++ b/samples/Sample.SqlServer3x/DefaultDbContext.cs @@ -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; } } } diff --git a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs index 8d7575ee..c18e262f 100644 --- a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs +++ b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs @@ -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 : AbpDbContext, IShardingTableDbContext where T : AbpDbContext, IShardingTableDbContext { - private readonly string EMPTY_SHARDING_TAIL_ID = ShardingConstant.EMPTY_SHARDING_TAIL_ID + Guid.NewGuid().ToString("n"); + + private readonly ConcurrentDictionary _dbContextCaches = new ConcurrentDictionary(); private readonly IVirtualTableManager _virtualTableManager; + private readonly IRouteTailFactory _routeTailFactory; private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig; private DbContextOptions _dbContextOptions; @@ -34,6 +38,7 @@ namespace Samples.AbpSharding { _shardingDbContextFactory = ShardingContainer.GetService(); _virtualTableManager = ShardingContainer.GetService(); + _routeTailFactory = ShardingContainer.GetService(); _shardingDbContextOptionsBuilderConfig = ShardingContainer .GetService>() .FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType); @@ -47,7 +52,7 @@ namespace Samples.AbpSharding { Type type = typeof(DbContextOptionsBuilder<>); type = type.MakeGenericType(ActualDbContextType); - return (DbContextOptionsBuilder)Activator.CreateInstance(type); + return (DbContextOptionsBuilder) Activator.CreateInstance(type); } private DbContextOptions 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 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); diff --git a/src/ShardingCore/Core/ShardingConstant.cs b/src/ShardingCore/Core/ShardingConstant.cs index 7cc89672..c40516f7 100644 --- a/src/ShardingCore/Core/ShardingConstant.cs +++ b/src/ShardingCore/Core/ShardingConstant.cs @@ -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"; } } diff --git a/src/ShardingCore/Core/VirtualRoutes/Abstractions/IMultiQueryRouteTail.cs b/src/ShardingCore/Core/VirtualRoutes/Abstractions/IMultiQueryRouteTail.cs new file mode 100644 index 00000000..16cdf76f --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/Abstractions/IMultiQueryRouteTail.cs @@ -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 + { + /// + /// 获取对象类型的应该后缀 + /// + /// + /// + string GetEntityTail(Type entityType); + + ISet GetEntityTypes(); + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTail.cs b/src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTail.cs new file mode 100644 index 00000000..ad5a5510 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTail.cs @@ -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(); + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTailFactory.cs b/src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTailFactory.cs new file mode 100644 index 00000000..2780980e --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/Abstractions/IRouteTailFactory.cs @@ -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); + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/Abstractions/ISingleQueryRouteTail.cs b/src/ShardingCore/Core/VirtualRoutes/Abstractions/ISingleQueryRouteTail.cs new file mode 100644 index 00000000..87a4c9fb --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/Abstractions/ISingleQueryRouteTail.cs @@ -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 + { + /// + /// 获取当前查询的后缀 + /// + /// + string GetTail(); + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/RouteTailFactory.cs b/src/ShardingCore/Core/VirtualRoutes/RouteTailFactory.cs new file mode 100644 index 00000000..dae9a529 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/RouteTailFactory.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/RouteTails/MultiQueryRouteTail.cs b/src/ShardingCore/Core/VirtualRoutes/RouteTails/MultiQueryRouteTail.cs new file mode 100644 index 00000000..0641bc40 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/RouteTails/MultiQueryRouteTail.cs @@ -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 _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 GetEntityTypes() + { + return _entityTypes; + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/RouteTails/SingleQueryRouteTail.cs b/src/ShardingCore/Core/VirtualRoutes/RouteTails/SingleQueryRouteTail.cs new file mode 100644 index 00000000..14c02b8d --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/RouteTails/SingleQueryRouteTail.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/QueryRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/QueryRouteRuleEngine.cs index 70c99be4..d0843413 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/QueryRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/QueryRouteRuleEngine.cs @@ -91,8 +91,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine //} } - private bool EnableMultiEntityQuery = false; - public IEnumerable Route(Type shardingDbContextType, RouteRuleContext routeRuleContext) { Dictionary> routeMaps = new Dictionary>(); @@ -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); diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs index 4c1896bf..c1f56282 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs @@ -22,5 +22,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine } public ISet ReplaceTables { get; } + } } \ No newline at end of file diff --git a/src/ShardingCore/DIExtension.cs b/src/ShardingCore/DIExtension.cs index 3ce5bf8a..f0ece5a1 100644 --- a/src/ShardingCore/DIExtension.cs +++ b/src/ShardingCore/DIExtension.cs @@ -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(); services.AddSingleton(); + services.AddSingleton(); return services; } diff --git a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs index f1054344..e34eef0c 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs @@ -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; diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs index d05343db..94fd98c4 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs @@ -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; } } } \ No newline at end of file diff --git a/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs b/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs index e14cdd99..358b5cd8 100644 --- a/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs +++ b/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs @@ -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 { diff --git a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs index 00c74a1b..fdc6b448 100644 --- a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs +++ b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs @@ -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: ModelCustomizer where TShardingDbContext:DbContext,IShardingDbContext + public class ShardingModelCustomizer : 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(); 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(); - // 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}"); } } -} +} \ No newline at end of file diff --git a/src/ShardingCore/EFCores/ShardingQueryCompiler.cs b/src/ShardingCore/EFCores/ShardingQueryCompiler.cs index 1b087648..ee911a8a 100644 --- a/src/ShardingCore/EFCores/ShardingQueryCompiler.cs +++ b/src/ShardingCore/EFCores/ShardingQueryCompiler.cs @@ -104,9 +104,9 @@ namespace ShardingCore.EFCores case nameof(Enumerable.All): return EnsureMergeExecute(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); case nameof(Enumerable.Max): - return GenericMergeExecute(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); + return GenericMergeExecute2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); case nameof(Enumerable.Min): - return EnsureMergeExecute(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); + return GenericMergeExecute2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); case nameof(Enumerable.Sum): return EnsureMergeExecute2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); case nameof(Enumerable.Average): @@ -177,9 +177,9 @@ namespace ShardingCore.EFCores case nameof(Enumerable.All): return EnsureMergeExecute(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Max): - return GenericMergeExecute(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + return GenericMergeExecute2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Min): - return EnsureMergeExecute(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + return GenericMergeExecute2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Sum): return EnsureMergeExecute2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Average): @@ -224,13 +224,27 @@ namespace ShardingCore.EFCores private TResult GenericMergeExecute(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(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)streamEngineMethod.Invoke(streamEngine, @params); } + private Task GenericMergeExecuteAsync2(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)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params); + } + private Task EnsureMergeExecuteAsync2(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, CancellationToken cancellationToken) { @@ -392,9 +419,9 @@ namespace ShardingCore.EFCores case nameof(Enumerable.All): return EnsureMergeExecuteAsync(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Max): - return GenericMergeExecuteAsync(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + return GenericMergeExecuteAsync2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Min): - return EnsureMergeExecuteAsync(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + return GenericMergeExecuteAsync2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); case nameof(Enumerable.Sum): return EnsureMergeExecuteAsync2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken); case nameof(Enumerable.Average): diff --git a/src/ShardingCore/Extensions/ShardingComplierExtension.cs b/src/ShardingCore/Extensions/ShardingComplierExtension.cs index 483f800f..1c9d5dc7 100644 --- a/src/ShardingCore/Extensions/ShardingComplierExtension.cs +++ b/src/ShardingCore/Extensions/ShardingComplierExtension.cs @@ -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"); } } -} +} \ No newline at end of file diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs index 234af5b5..e73e68c6 100644 --- a/src/ShardingCore/Extensions/ShardingExtension.cs +++ b/src/ShardingCore/Extensions/ShardingExtension.cs @@ -19,26 +19,32 @@ namespace ShardingCore.Extensions public static class ShardingExtension { private static readonly string ShardingTableDbContextFormat = $"sharding_{Guid.NewGuid():n}_"; - /// - /// 获取分表的tail - /// - /// - /// - public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext) - { - return dbContext.ModelChangeKey?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty; + // /// + // /// 获取分表的tail + // /// + // /// + // /// + // public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext) + // { + // return dbContext.RouteTail?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty; + // + // } + // /// + // /// 设置分表的tail + // /// + // /// + // /// + // 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(); + // } - } - /// - /// 设置分表的tail - /// - /// - /// - 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}"; + ; } } } diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index 654a6c20..3fab56be 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -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 /// public abstract class AbstractShardingDbContext : DbContext, IShardingTableDbContext where T : DbContext, IShardingTableDbContext { - private readonly string EMPTY_SHARDING_TAIL_ID = ShardingConstant.EMPTY_SHARDING_TAIL_ID+ Guid.NewGuid().ToString("n"); private readonly ConcurrentDictionary _dbContextCaches = new ConcurrentDictionary(); private readonly IVirtualTableManager _virtualTableManager; + private readonly IRouteTailFactory _routeTailFactory; private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig; private DbContextOptions _dbContextOptions; @@ -46,6 +50,7 @@ namespace ShardingCore.Sharding { _shardingDbContextFactory = ShardingContainer.GetService(); _virtualTableManager = ShardingContainer.GetService(); + _routeTailFactory = ShardingContainer.GetService(); _shardingDbContextOptionsBuilderConfig = ShardingContainer .GetService>() .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 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)); } diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs index 6085f56d..556e2426 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs @@ -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 /// Type ActualDbContextType { get;} /// - /// ����DbContext + /// create DbContext /// /// true not care dbcontext life, false need call dispose() - /// + /// /// - DbContext GetDbContext(bool track,string tail); + DbContext GetDbContext(bool track,IRouteTail routeTail); /// /// ����ʵ�崴��db context /// diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs index feb81066..a4c4e965 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs @@ -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; } } } diff --git a/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/MultiOrderStreamMergeAsyncEnumerator.cs b/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/MultiOrderStreamMergeAsyncEnumerator.cs index b30118bb..7b1b3185 100644 --- a/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/MultiOrderStreamMergeAsyncEnumerator.cs +++ b/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/MultiOrderStreamMergeAsyncEnumerator.cs @@ -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 diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index f79ec327..5b1a4dac 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -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 _source; private readonly IShardingDbContext _shardingDbContext; private readonly IRoutingRuleEngineFactory _tableRoutingRuleEngineFactory; - private readonly IShardingScopeFactory _shardingScopeFactory; + private readonly IRouteTailFactory _routeTailFactory; private readonly IQueryable _reWriteSource; //public IEnumerable RouteResults { get; } @@ -36,13 +38,13 @@ namespace ShardingCore.Sharding public SelectContext SelectContext { get;} public GroupByContext GroupByContext { get; } - public StreamMergeContext(IQueryable source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IShardingScopeFactory shardingScopeFactory) + public StreamMergeContext(IQueryable source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IRouteTailFactory routeTailFactory) { //_shardingScopeFactory = shardingScopeFactory; _source = source; _shardingDbContext = shardingDbContext; _tableRoutingRuleEngineFactory = tableRoutingRuleEngineFactory; - _shardingScopeFactory = shardingScopeFactory; + _routeTailFactory = routeTailFactory; var reWriteResult = new ReWriteEngine(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 GetRouteResults() { return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source); } - public ShardingScope CreateScope() + public IRouteTail Create(RouteResult routeResult) { - return _shardingScopeFactory.CreateScope(); + return _routeTailFactory.Create(routeResult); } public IQueryable GetReWriteQueryable() diff --git a/src/ShardingCore/Sharding/StreamMergeContextFactory.cs b/src/ShardingCore/Sharding/StreamMergeContextFactory.cs index 7b8a9289..303d2304 100644 --- a/src/ShardingCore/Sharding/StreamMergeContextFactory.cs +++ b/src/ShardingCore/Sharding/StreamMergeContextFactory.cs @@ -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 Create(IQueryable queryable,IShardingDbContext shardingDbContext) { - return new StreamMergeContext(queryable,shardingDbContext, _routingRuleEngineFactory, _shardingScopeFactory); + return new StreamMergeContext(queryable,shardingDbContext, _routingRuleEngineFactory, _routeTailFactory); } } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs index 1f6eb49e..c7aa7ca0 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs @@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx * @Ver: 1.0 * @Email: 326308290@qq.com */ - public abstract class AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine: AbstractEnsureMethodCallInMemoryAsyncMergeEngine + public abstract class AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine: AbstractEnsureMethodCallInMemoryAsyncMergeEngine { 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> selector) + if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression> selector) { return queryable.Select(selector); } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs index abe854f7..703e1e80 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs @@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE * @Ver: 1.0 * @Email: 326308290@qq.com */ - public abstract class AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine:AbstractGenericMethodCallInMemoryAsyncMergeEngine + public abstract class AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine:AbstractGenericMethodCallInMemoryAsyncMergeEngine { 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> selector) + if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression> selector) { return queryable.Select(selector); } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs index a980f6dc..60208e88 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs @@ -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 ProcessSecondExpression(IQueryable queryable, Expression secondExpression); + private IQueryable CreateAsyncExecuteQueryable(RouteResult routeResult) + { + var shardingDbContext = _mergeContext.CreateDbContext(routeResult); + _parllelDbbContexts.Add(shardingDbContext); + var newQueryable = (IQueryable) GetStreamMergeContext().GetReWriteQueryable() + .ReplaceDbContextQueryable(shardingDbContext); + var newFilterQueryable = EFQueryAfterFilter(newQueryable); + return newFilterQueryable; + } + public async Task> ExecuteAsync(Func> 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)GetStreamMergeContext().GetReWriteQueryable() - .ReplaceDbContextQueryable(shardingDbContext); - var newFilterQueryable = EFQueryAfterFilter(newQueryable); - return await efQuery(newFilterQueryable); + var asyncExecuteQueryable = CreateAsyncExecuteQueryable(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 Execute(Func 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)GetStreamMergeContext().GetReWriteQueryable() - .ReplaceDbContextQueryable(shardingDbContext); - var newFilterQueryable = EFQueryAfterFilter(newQueryable); - var query = efQuery(newFilterQueryable); - return query; - //} - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - }); + { + try + { + var asyncExecuteQueryable = CreateAsyncExecuteQueryable(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 GetQueryable() { return _queryable; @@ -165,6 +145,5 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions { return _secondExpression; } - } -} +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs index 28c8cebf..07b3b6c5 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs @@ -23,7 +23,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines * @Email: 326308290@qq.com */ public class AverageAsyncInMemoryMergeEngine : - AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine + AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine { public AverageAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs index 5acd1230..78777db3 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs @@ -19,7 +19,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class MaxAsyncInMemoryMergeEngine: AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine + public class MaxAsyncInMemoryMergeEngine: AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine { public MaxAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs index 647139ee..c89cf849 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs @@ -20,7 +20,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class MinAsyncInMemoryMergeEngine : AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine + public class MinAsyncInMemoryMergeEngine : AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine { public MinAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs index ba820b47..596ad279 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs @@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class SumAsyncInMemoryMergeEngine : AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine + public class SumAsyncInMemoryMergeEngine : AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine { public SumAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs index 4a124bcd..c64ffa1e 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs @@ -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 : IAsyncEnumerable, IEnumerable, IDisposable { - private readonly StreamMergeContext _mergeContext; private readonly ICollection _parllelDbbContexts; @@ -47,7 +46,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines } #endif #if EFCORE2 - private async Task> GetAsyncEnumerator(IQueryable newQueryable) { var enumator = newQueryable.AsAsyncEnumerable().GetEnumerator(); @@ -64,38 +62,34 @@ namespace ShardingCore.Sharding.StreamMergeEngines #endif #if EFCORE2 - IAsyncEnumerator IAsyncEnumerable.GetEnumerator() { return GetShardingEnumerator(); } #endif + private IQueryable CreateAsyncExecuteQueryable(RouteResult routeResult) + { + var shardingDbContext = _mergeContext.CreateDbContext(routeResult); + _parllelDbbContexts.Add(shardingDbContext); + var newQueryable = (IQueryable) _mergeContext.GetReWriteQueryable() + .ReplaceDbContextQueryable(shardingDbContext); + return newQueryable; + } + private IAsyncEnumerator 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)_mergeContext.GetReWriteQueryable() - .ReplaceDbContextQueryable(shardingDbContext); + var newQueryable = CreateAsyncExecuteQueryable(routeResult); var asyncEnumerator = await GetAsyncEnumerator(newQueryable); return new StreamMergeAsyncEnumerator(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)_mergeContext.GetReWriteQueryable() - .ReplaceDbContextQueryable(shardingDbContext); - - var enumerator = GetEnumerator(newQueryable); - return new StreamMergeEnumerator(enumerator); - //} + var enumerator = GetEnumerator(newQueryable); + return new StreamMergeEnumerator(enumerator); } catch (Exception e) { @@ -187,4 +168,4 @@ namespace ShardingCore.Sharding.StreamMergeEngines } } } -} +} \ No newline at end of file diff --git a/src/ShardingCore/ShardingBootstrapper.cs b/src/ShardingCore/ShardingBootstrapper.cs index ea3a3a93..5bc5b7d2 100644 --- a/src/ShardingCore/ShardingBootstrapper.cs +++ b/src/ShardingCore/ShardingBootstrapper.cs @@ -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 _logger; + private readonly IRouteTailFactory _routeTailFactory; private readonly IShardingDbContextFactory _shardingDbContextFactory; public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable shardingConfigOptions, IVirtualTableManager virtualTableManager , IShardingTableCreator tableCreator, ILogger 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) diff --git a/src/ShardingCore/TableCreator/ShardingTableCreator.cs b/src/ShardingCore/TableCreator/ShardingTableCreator.cs index 58132f35..ef575bc5 100644 --- a/src/ShardingCore/TableCreator/ShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/ShardingTableCreator.cs @@ -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 _shardingConfigOptions; + private readonly IRouteTailFactory _routeTailFactory; public ShardingTableCreator(ILogger logger, IShardingDbContextFactory shardingDbContextFactory, - IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable shardingConfigOptions) + IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable shardingConfigOptions,IRouteTailFactory routeTailFactory) { _logger = logger; _shardingDbContextFactory = shardingDbContextFactory; _virtualTableManager = virtualTableManager; _serviceProvider = serviceProvider; _shardingConfigOptions = shardingConfigOptions; + _routeTailFactory = routeTailFactory; } public void CreateTable(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(); diff --git a/test/ShardingCore.Test50.MySql/DefaultDbContext.cs b/test/ShardingCore.Test50.MySql/DefaultDbContext.cs index 5e904a11..3482fa94 100644 --- a/test/ShardingCore.Test50.MySql/DefaultDbContext.cs +++ b/test/ShardingCore.Test50.MySql/DefaultDbContext.cs @@ -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; } } } diff --git a/test/ShardingCore.Test50/DefaultDbContext.cs b/test/ShardingCore.Test50/DefaultDbContext.cs index b057b3ff..3e48a8a4 100644 --- a/test/ShardingCore.Test50/DefaultDbContext.cs +++ b/test/ShardingCore.Test50/DefaultDbContext.cs @@ -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; } } } diff --git a/test/ShardingCore.Test50/ShardingCore.Test50.csproj b/test/ShardingCore.Test50/ShardingCore.Test50.csproj index 102b40c8..066bda53 100644 --- a/test/ShardingCore.Test50/ShardingCore.Test50.csproj +++ b/test/ShardingCore.Test50/ShardingCore.Test50.csproj @@ -22,6 +22,8 @@ PreserveNewest PreserveNewest + + diff --git a/test/ShardingCore.Test50/ShardingTest.cs b/test/ShardingCore.Test50/ShardingTest.cs index 651b06e2..fe06a9b1 100644 --- a/test/ShardingCore.Test50/ShardingTest.cs +++ b/test/ShardingCore.Test50/ShardingTest.cs @@ -67,307 +67,307 @@ namespace ShardingCore.Test50 } } - //[Fact] - //public async Task ToList_Join_Test() - //{ - // var list = await (from u in _virtualDbContext.Set().Where(o=>o.Id=="1" || o.Id=="1000") - // join salary in _virtualDbContext.Set() - // 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() + join salary in _virtualDbContext.Set() + 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().Where(o => o.Id == "300") - // join salary in _virtualDbContext.Set() - // 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().Where(o => o.Id == "300") + join salary in _virtualDbContext.Set() + 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().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().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().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().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().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().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().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().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().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().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().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().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().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().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().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().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().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().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().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().Where(o => o.Name == "name_1001").ToListAsync(); + Assert.Empty(mods); + } - //[Fact] - //public async Task FirstOrDefault_Order_By_Id_Test() - //{ - // var sysUserModAge = await _virtualDbContext.Set().OrderBy(o => o.Age).ShardingFirstOrDefaultAsync(); - // Assert.True(sysUserModAge != null && sysUserModAge.Id == "1"); - // var sysUserModAgeDesc = await _virtualDbContext.Set().OrderByDescending(o => o.Age).ShardingFirstOrDefaultAsync(); - // Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000"); - // var sysUserMod = await _virtualDbContext.Set().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().OrderBy(o => o.Age).FirstOrDefaultAsync(); + Assert.True(sysUserModAge != null && sysUserModAge.Id == "1"); + var sysUserModAgeDesc = await _virtualDbContext.Set().OrderByDescending(o => o.Age).FirstOrDefaultAsync(); + Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000"); + var sysUserMod = await _virtualDbContext.Set().OrderBy(o => o.Id).FirstOrDefaultAsync(); + Assert.True(sysUserMod != null && sysUserMod.Id == "1"); - // var sysUserModDesc = await _virtualDbContext.Set().OrderByDescending(o => o.Id).ShardingFirstOrDefaultAsync(); - // Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999"); - //} + var sysUserModDesc = await _virtualDbContext.Set().OrderByDescending(o => o.Id).FirstOrDefaultAsync(); + Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999"); + } - //[Fact] - //public async Task FirstOrDefault2() - //{ - // var sysUserMod = await _virtualDbContext.Set().Where(o => o.Id == "1").ShardingFirstOrDefaultAsync(); - // Assert.NotNull(sysUserMod); - // Assert.True(sysUserMod.Id == "1"); - //} + [Fact] + public async Task FirstOrDefault2() + { + var sysUserMod = await _virtualDbContext.Set().Where(o => o.Id == "1").FirstOrDefaultAsync(); + Assert.NotNull(sysUserMod); + Assert.True(sysUserMod.Id == "1"); + } - //[Fact] - //public async Task FirstOrDefault3() - //{ - // var sysUserMod = await _virtualDbContext.Set().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().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().Where(o => o.Id != "1").ShardingFirstOrDefaultAsync(); - // Assert.NotNull(sysUserMod); - // Assert.True(sysUserMod.Id != "1"); - //} + [Fact] + public async Task FirstOrDefault4() + { + var sysUserMod = await _virtualDbContext.Set().Where(o => o.Id != "1").FirstOrDefaultAsync(); + Assert.NotNull(sysUserMod); + Assert.True(sysUserMod.Id != "1"); + } - //[Fact] - //public async Task FirstOrDefault5() - //{ - // var sysUserMod = await _virtualDbContext.Set().Where(o => o.Name == "name_1001").ShardingFirstOrDefaultAsync(); - // Assert.Null(sysUserMod); - //} + [Fact] + public async Task FirstOrDefault5() + { + var sysUserMod = await _virtualDbContext.Set().Where(o => o.Name == "name_1001").FirstOrDefaultAsync(); + Assert.Null(sysUserMod); + } - //[Fact] - //public async Task Count_Test() - //{ - // var a = await _virtualDbContext.Set().Where(o => o.Name == "name_1000").ShardingCountAsync(); - // Assert.Equal(1, a); - // var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1000").ShardingCountAsync(); - // Assert.Equal(999, b); - //} + [Fact] + public async Task Count_Test() + { + var a = await _virtualDbContext.Set().Where(o => o.Name == "name_1000").CountAsync(); + Assert.Equal(1, a); + var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1000").CountAsync(); + Assert.Equal(999, b); + } - //[Fact] - //public async Task Sum_Test() - //{ - // var a = await _virtualDbContext.Set().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().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().Where(o => o.Name != "name_1000").ShardingSumAsync(o => o.Age); - // Assert.Equal(expected - 1000, b); - //} + Assert.Equal(expected, a); + var b = await _virtualDbContext.Set().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().ShardingMaxAsync(o => o.Age); - // Assert.Equal(1000, a); - // var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1000").ShardingMaxAsync(o => o.Age); - // Assert.Equal(999, b); - // var c = await _virtualDbContext.Set().Where(o => o.Age < 500).ShardingMaxAsync(o => o.Age); - // Assert.Equal(499, c); - // var e = await _virtualDbContext.Set().Where(o => o.Age <= 500).ShardingMaxAsync(o => o.Age); - // Assert.Equal(500, e); - //} + [Fact] + public async Task Max_Test() + { + var a = await _virtualDbContext.Set().MaxAsync(o => o.Age); + Assert.Equal(1000, a); + var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1000").MaxAsync(o => o.Age); + Assert.Equal(999, b); + var c = await _virtualDbContext.Set().Where(o => o.Age < 500).MaxAsync(o => o.Age); + Assert.Equal(499, c); + var e = await _virtualDbContext.Set().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().Where(o => o.Id == "300") - // join salary in _virtualDbContext.Set() - // 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().Where(o => o.Id == "300") + join salary in _virtualDbContext.Set() + 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().ShardingMinAsync(o => o.Age); - // Assert.Equal(1, a); - // var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1").ShardingMinAsync(o => o.Age); - // Assert.Equal(2, b); - // var c = await _virtualDbContext.Set().Where(o => o.Age > 500).ShardingMinAsync(o => o.Age); - // Assert.Equal(501, c); - // var e = await _virtualDbContext.Set().Where(o => o.Age >= 500).ShardingMinAsync(o => o.Age); - // Assert.Equal(500, e); - //} + [Fact] + public async Task Min_Test() + { + var a = await _virtualDbContext.Set().MinAsync(o => o.Age); + Assert.Equal(1, a); + var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1").MinAsync(o => o.Age); + Assert.Equal(2, b); + var c = await _virtualDbContext.Set().Where(o => o.Age > 500).MinAsync(o => o.Age); + Assert.Equal(501, c); + var e = await _virtualDbContext.Set().Where(o => o.Age >= 500).MinAsync(o => o.Age); + Assert.Equal(500, e); + } - //[Fact] - //public async Task Any_Test() - //{ - // var a = await _virtualDbContext.Set().ShardingAnyAsync(o => o.Age == 100); - // Assert.True(a); - // var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1").ShardingAnyAsync(o => o.Age == 1); - // Assert.False(b); - // var c = await _virtualDbContext.Set().Where(o => o.Age > 500).ShardingAnyAsync(o => o.Age <= 500); - // Assert.False(c); - // var e = await _virtualDbContext.Set().Where(o => o.Age >= 500).ShardingAnyAsync(o => o.Age <= 500); - // Assert.True(e); - //} + [Fact] + public async Task Any_Test() + { + var a = await _virtualDbContext.Set().AnyAsync(o => o.Age == 100); + Assert.True(a); + var b = await _virtualDbContext.Set().Where(o => o.Name != "name_1").AnyAsync(o => o.Age == 1); + Assert.False(b); + var c = await _virtualDbContext.Set().Where(o => o.Age > 500).AnyAsync(o => o.Age <= 500); + Assert.False(c); + var e = await _virtualDbContext.Set().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() - // .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() - // .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() + .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() + // .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); + // } } } \ No newline at end of file diff --git a/test/ShardingCore.Test50/Startup.cs b/test/ShardingCore.Test50/Startup.cs index c3a9c4d9..4a60a92c 100644 --- a/test/ShardingCore.Test50/Startup.cs +++ b/test/ShardingCore.Test50/Startup.cs @@ -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(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]) + services.AddShardingDbContext(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(); op.AddShardingTableRoute(); });