From 4accc08567c1ac64664b6ddaeb01186d43f6d24f Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Fri, 20 Aug 2021 13:50:49 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E4=B8=AA=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nuget-publish.bat | 2 +- samples/Sample.SqlServer/DIExtension.cs | 49 +++---- .../DbContexts/DefaultShardingDbContext.cs | 1 + .../Sample.SqlServer/Sample.SqlServer.csproj | 8 ++ samples/Sample.SqlServer/Startup.cs | 37 +---- .../AbstractShardingCoreOptions.cs | 83 ----------- .../ShardingAccessors/IShardingAccessor.cs | 13 -- .../IShardingScopeFactory.cs | 20 --- .../ShardingAccessors/ShardingAccessor.cs | 26 ---- .../Core/ShardingAccessors/ShardingContext.cs | 71 --------- .../Core/ShardingAccessors/ShardingScope.cs | 36 ----- .../ShardingAccessors/ShardingScopeFactory.cs | 34 ----- .../RoutingRuleEngine/IRouteRuleEngine.cs | 6 +- .../IRoutingRuleEngineFactory.cs | 9 +- .../RoutingRuleEngine/QueryRouteRuleEngine.cs | 57 ++++---- .../RoutingRuleEngineFactory.cs | 38 +++-- .../VirtualTables/IVirtualTableManager.cs | 30 ++-- .../VirtualTables/OneDbVirtualTableManager.cs | 133 +++++++++++++---- src/ShardingCore/DIExtension.cs | 88 ++++++++---- .../DbContextCreateFilterManager.cs | 31 ---- .../Abstractions/IDbContextCreateFilter.cs | 24 ---- .../IDbContextCreateFilterManager.cs | 18 --- .../ShardingDbContextOptionBuilder.cs | 47 ------ .../DbContexts/IShardingDbContextFactory.cs | 4 +- .../IShardingParallelDbContextFactory.cs | 16 --- ...ShardingParallelDbContextFactoryManager.cs | 16 --- .../DbContexts/ShardingDbContextFactory.cs | 66 ++++----- .../Transactions/IShardingTransaction.cs | 26 ---- .../Transactions/ShardingTransaction.cs | 102 ------------- .../IDbContextOptionsProvider.cs | 23 --- .../DefaultShardingDbContextCreatorConfig.cs | 38 +++++ .../EFCores/ShardingModelCustomizer.cs | 5 +- .../Extensions/CommonExtension.cs | 32 ++++- .../Extensions/ShardingExtension.cs | 4 +- .../Helpers/ShardingCoreHelper.cs | 36 ++--- src/ShardingCore/IShardingBootstrapper.cs | 1 + src/ShardingCore/IShardingConfigOption.cs | 37 +++++ src/ShardingCore/IShardingCoreOptions.cs | 50 ------- .../IShardingDbContextCreatorConfig.cs | 26 ++++ .../IShardingDbContextOptionsBuilderConfig.cs | 21 +++ .../Sharding/AbstractShardingDbContext.cs | 70 ++++++--- .../Abstractions/IShardingDbContext.cs | 12 +- .../Abstractions/IShardingTableDbContext.cs | 1 + .../ShardingDbContextOptionsBuilderConfig.cs | 33 +++++ .../Sharding/StreamMergeContext.cs | 29 ++-- .../Sharding/StreamMergeContextFactory.cs | 13 +- .../AbstractInMemoryAsyncMergeEngine.cs | 1 + src/ShardingCore/ShardingBootstrapper.cs | 87 ++++++----- src/ShardingCore/ShardingConfig.cs | 26 ---- src/ShardingCore/ShardingConfigOption.cs | 83 +++++++++++ src/ShardingCore/ShardingContainer.cs | 4 + .../TableCreator/IShardingTableCreator.cs | 7 +- .../TableCreator/ShardingTableCreator.cs | 45 +++--- .../ShardingCore.Test50.csproj | 4 + .../ShardingDefaultDbContext.cs | 2 + test/ShardingCore.Test50/Startup.cs | 136 ++++++++---------- 56 files changed, 841 insertions(+), 1076 deletions(-) delete mode 100644 src/ShardingCore/AbstractShardingCoreOptions.cs delete mode 100644 src/ShardingCore/Core/ShardingAccessors/IShardingAccessor.cs delete mode 100644 src/ShardingCore/Core/ShardingAccessors/IShardingScopeFactory.cs delete mode 100644 src/ShardingCore/Core/ShardingAccessors/ShardingAccessor.cs delete mode 100644 src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs delete mode 100644 src/ShardingCore/Core/ShardingAccessors/ShardingScope.cs delete mode 100644 src/ShardingCore/Core/ShardingAccessors/ShardingScopeFactory.cs delete mode 100644 src/ShardingCore/DbContexts/Abstractions/DbContextCreateFilterManager.cs delete mode 100644 src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilter.cs delete mode 100644 src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilterManager.cs delete mode 100644 src/ShardingCore/DbContexts/Abstractions/ShardingDbContextOptionBuilder.cs delete mode 100644 src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs delete mode 100644 src/ShardingCore/DbContexts/IShardingParallelDbContextFactoryManager.cs delete mode 100644 src/ShardingCore/DbContexts/Transactions/IShardingTransaction.cs delete mode 100644 src/ShardingCore/DbContexts/Transactions/ShardingTransaction.cs delete mode 100644 src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs create mode 100644 src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs create mode 100644 src/ShardingCore/IShardingConfigOption.cs delete mode 100644 src/ShardingCore/IShardingCoreOptions.cs create mode 100644 src/ShardingCore/IShardingDbContextCreatorConfig.cs create mode 100644 src/ShardingCore/IShardingDbContextOptionsBuilderConfig.cs create mode 100644 src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs delete mode 100644 src/ShardingCore/ShardingConfig.cs create mode 100644 src/ShardingCore/ShardingConfigOption.cs diff --git a/nuget-publish.bat b/nuget-publish.bat index 88521d88..c76acb51 100644 --- a/nuget-publish.bat +++ b/nuget-publish.bat @@ -2,7 +2,7 @@ ::定义版本 set EFCORE2=2.1.0.21 set EFCORE3=3.1.0.21 -set EFCORE5=5.1.0.21 +set EFCORE5=5.2.0.02 ::删除所有bin与obj下的文件 @echo off diff --git a/samples/Sample.SqlServer/DIExtension.cs b/samples/Sample.SqlServer/DIExtension.cs index c7dbec63..dd1de354 100644 --- a/samples/Sample.SqlServer/DIExtension.cs +++ b/samples/Sample.SqlServer/DIExtension.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Builder; @@ -6,17 +5,15 @@ using Microsoft.Extensions.DependencyInjection; using Sample.SqlServer.DbContexts; using Sample.SqlServer.Domain.Entities; using ShardingCore; -using ShardingCore.DbContexts.VirtualDbContexts; -using ShardingCore.Extensions; namespace Sample.SqlServer { -/* -* @Author: xjm -* @Description: -* @Date: Tuesday, 26 January 2021 12:29:04 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Tuesday, 26 January 2021 12:29:04 + * @Email: 326308290@qq.com + */ public static class DIExtension { public static IApplicationBuilder UseShardingCore(this IApplicationBuilder app) @@ -30,24 +27,24 @@ namespace Sample.SqlServer { using (var scope=app.ApplicationServices.CreateScope()) { - var virtualDbContext =scope.ServiceProvider.GetService(); - //if (!virtualDbContext.Set().ShardingAny()) - //{ - // var ids = Enumerable.Range(1, 1000); - // var userMods = new List(); - // foreach (var id in ids) - // { - // userMods.Add(new SysUserMod() - // { - // Id = id.ToString(), - // Age = id, - // Name = $"name_{id}", - // }); - // } + var virtualDbContext =scope.ServiceProvider.GetService(); + if (!virtualDbContext.Set().Any()) + { + var ids = Enumerable.Range(1, 1000); + var userMods = new List(); + foreach (var id in ids) + { + userMods.Add(new SysUserMod() + { + Id = id.ToString(), + Age = id, + Name = $"name_{id}", + }); + } - // virtualDbContext.AddRange(userMods); - // virtualDbContext.SaveChanges(); - //} + virtualDbContext.AddRange(userMods); + virtualDbContext.SaveChanges(); + } } } } diff --git a/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs b/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs index 9d21ca77..35540c8a 100644 --- a/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs @@ -21,5 +21,6 @@ namespace Sample.SqlServer.DbContexts modelBuilder.ApplyConfiguration(new SysTestMap()); } + public override Type ShardingDbContextType => this.GetType(); } } diff --git a/samples/Sample.SqlServer/Sample.SqlServer.csproj b/samples/Sample.SqlServer/Sample.SqlServer.csproj index 14df3a81..62930223 100644 --- a/samples/Sample.SqlServer/Sample.SqlServer.csproj +++ b/samples/Sample.SqlServer/Sample.SqlServer.csproj @@ -5,4 +5,12 @@ 9.0 + + + + + + + + diff --git a/samples/Sample.SqlServer/Startup.cs b/samples/Sample.SqlServer/Startup.cs index 92c705e3..fa80beec 100644 --- a/samples/Sample.SqlServer/Startup.cs +++ b/samples/Sample.SqlServer/Startup.cs @@ -1,21 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Sample.SqlServer.DbContexts; using Sample.SqlServer.Shardings; using ShardingCore; -using ShardingCore.EFCores; -using ShardingCore.SqlServer; namespace Sample.SqlServer { @@ -30,31 +21,17 @@ namespace Sample.SqlServer public void ConfigureServices(IServiceCollection services) { services.AddControllers(); - services.AddShardingSqlServer(o => - { - o.EnsureCreatedWithOutShardingTable = false; - o.CreateShardingTableOnStart = false; - o.UseShardingDbContext( dbConfig => - { - dbConfig.AddShardingTableRoute(); - }); - //o.AddDataSourceVirtualRoute<>(); - - }); services.AddDbContext(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True")); - services.AddShardingDbContext(op => - { - op.UseShardingDbContextOptions((connection, builder) => + services.AddShardingDbContext(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx;Integrated Security=True;MultipleActiveResultSets=True;") + ,op => { - return builder.UseSqlServer(connection).UseLoggerFactory(efLogger) - .UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll) - .ReplaceService() - .ReplaceService().Options; + op.EnsureCreatedWithOutShardingTable = true; + op.CreateShardingTableOnStart = true; + op.UseShardingDbContextOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)); + op.AddShardingTableRoute(); }); - },o => - o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;MultipleActiveResultSets=True;").UseSharding()); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -70,7 +47,7 @@ namespace Sample.SqlServer app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); - //app.DbSeed(); + app.DbSeed(); } } } \ No newline at end of file diff --git a/src/ShardingCore/AbstractShardingCoreOptions.cs b/src/ShardingCore/AbstractShardingCoreOptions.cs deleted file mode 100644 index 7df2277d..00000000 --- a/src/ShardingCore/AbstractShardingCoreOptions.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using ShardingCore.DbContexts.Abstractions; -using ShardingCore.Helpers; -using ShardingCore.Sharding.Abstractions; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ShardingCore -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/3/5 17:30:10 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public abstract class AbstractShardingCoreOptions : IShardingCoreOptions - { - private ShardingConfigEntry _shardingConfigEntry; - - public void UseShardingDbContext(Action func) where TContext : DbContext,IShardingTableDbContext - { - if (_shardingConfigEntry!=null) - { - throw new ArgumentException($"same db context inited:[{typeof(TContext)}]"); - } - - ShardingCoreHelper.CheckContextConstructors(); - var creator = ShardingCoreHelper.CreateActivator(); - _shardingConfigEntry = new ShardingConfigEntry(creator, typeof(TContext), func); - } - - - private readonly Dictionary _virtualRoutes = new Dictionary(); - - - public ShardingConfigEntry GetShardingConfig() - { - return _shardingConfigEntry; - } - - public ISet GetVirtualRoutes() - { - return _virtualRoutes.Select(o => o.Value).ToHashSet(); - } - - public Type GetVirtualRoute(Type entityType) - { - if (!_virtualRoutes.ContainsKey(entityType)) - throw new ArgumentException("not found IDataSourceVirtualRoute"); - return _virtualRoutes[entityType]; - } - - /// - /// 如果数据库不存在就创建并且创建表除了分表的 - /// - public bool EnsureCreatedWithOutShardingTable { get; set; } - /// - /// 是否需要在启动时创建分表 - /// - public bool? CreateShardingTableOnStart { get; set; } - - public readonly List _filters = new List(); - /// - /// 添加filter过滤器 - /// - /// - public void AddDbContextCreateFilter() where TFilter : class, IDbContextCreateFilter - { - if (_filters.Contains(typeof(TFilter))) - throw new ArgumentException("请勿重复添加DbContextCreateFilter"); - _filters.Add(typeof(TFilter)); - } - - public List GetFilters() - { - return _filters; - } - - public bool? IgnoreCreateTableError { get; set; } - } -} diff --git a/src/ShardingCore/Core/ShardingAccessors/IShardingAccessor.cs b/src/ShardingCore/Core/ShardingAccessors/IShardingAccessor.cs deleted file mode 100644 index f2eefaa5..00000000 --- a/src/ShardingCore/Core/ShardingAccessors/IShardingAccessor.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ShardingCore.Core.ShardingAccessors -{ -/* -* @Author: xjm -* @Description: -* @Date: Tuesday, 22 December 2020 15:13:44 -* @Email: 326308290@qq.com -*/ - public interface IShardingAccessor - { - ShardingContext ShardingContext { get; set; } - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingAccessors/IShardingScopeFactory.cs b/src/ShardingCore/Core/ShardingAccessors/IShardingScopeFactory.cs deleted file mode 100644 index 2f45b8a8..00000000 --- a/src/ShardingCore/Core/ShardingAccessors/IShardingScopeFactory.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace ShardingCore.Core.ShardingAccessors -{ -/* -* @Author: xjm -* @Description: -* @Date: Wednesday, 23 December 2020 07:51:00 -* @Email: 326308290@qq.com -*/ - /// - /// 查询scope创建 - /// - public interface IShardingScopeFactory - { - /// - /// 创建查询scope - /// - /// - ShardingScope CreateScope(); - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingAccessors/ShardingAccessor.cs b/src/ShardingCore/Core/ShardingAccessors/ShardingAccessor.cs deleted file mode 100644 index e5953ffe..00000000 --- a/src/ShardingCore/Core/ShardingAccessors/ShardingAccessor.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Threading; -using ShardingCore.Core.VirtualTables; - -namespace ShardingCore.Core.ShardingAccessors -{ -/* -* @Author: xjm -* @Description: -* @Date: Tuesday, 22 December 2020 15:14:15 -* @Email: 326308290@qq.com -*/ - /// - /// 分表访问器 - /// - public class ShardingAccessor : IShardingAccessor - { - private static AsyncLocal _shardingContext = new AsyncLocal(); - - /// - public ShardingContext ShardingContext - { - get => _shardingContext.Value; - set => _shardingContext.Value = value; - } - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs b/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs deleted file mode 100644 index 31b1b3d5..00000000 --- a/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; -using ShardingCore.Core.VirtualTables; -using ShardingCore.Extensions; - -namespace ShardingCore.Core.ShardingAccessors -{ -/* -* @Author: xjm -* @Description: -* @Date: Tuesday, 22 December 2020 15:04:47 -* @Email: 326308290@qq.com -*/ - public class ShardingContext - { - private ShardingContext(RouteResult routeResult) - { - foreach (var physicTable in routeResult.ReplaceTables) - { - _shardingTables.Add(physicTable.VirtualTable, new List(1){physicTable.Tail}); - } - } - - /// - /// 分表操作上下文 key:物理表名 value:虚拟表和本次分表tails - /// - private readonly Dictionary> _shardingTables = new Dictionary>(); - - /// - /// 尝试添加本次操作表 - /// - /// - /// - /// - public void TryAddShardingTable(IVirtualTable virtualTable, List tails) - { - _shardingTables.Add(virtualTable, tails); - } - - /// - /// 创建一个分表上下文 - /// - /// - public static ShardingContext Create(RouteResult routeResult) - { - return new ShardingContext(routeResult); - } - - /// - /// 获取分表信息 - /// - /// - /// - public List GetContextQueryTails(IVirtualTable virtualTable) - { - if (_shardingTables.ContainsKey(virtualTable)) - return _shardingTables[virtualTable] ?? new List(0); - return new List(0); - } - - /// - /// 是否是空的 - /// - /// - public bool IsEmpty() - { - return _shardingTables.IsEmpty(); - } - } - -} \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingAccessors/ShardingScope.cs b/src/ShardingCore/Core/ShardingAccessors/ShardingScope.cs deleted file mode 100644 index 2952e92c..00000000 --- a/src/ShardingCore/Core/ShardingAccessors/ShardingScope.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -namespace ShardingCore.Core.ShardingAccessors -{ -/* -* @Author: xjm -* @Description: -* @Date: Wednesday, 23 December 2020 07:51:30 -* @Email: 326308290@qq.com -*/ - public class ShardingScope : IDisposable - { - - /// - /// 分表配置访问器 - /// - public IShardingAccessor ShardingAccessor { get; } - - /// - /// 构造函数 - /// - /// - public ShardingScope(IShardingAccessor shardingAccessor) - { - ShardingAccessor = shardingAccessor; - } - - /// - /// 回收 - /// - public void Dispose() - { - ShardingAccessor.ShardingContext = null; - } - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingAccessors/ShardingScopeFactory.cs b/src/ShardingCore/Core/ShardingAccessors/ShardingScopeFactory.cs deleted file mode 100644 index 3f1c38b1..00000000 --- a/src/ShardingCore/Core/ShardingAccessors/ShardingScopeFactory.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace ShardingCore.Core.ShardingAccessors -{ -/* -* @Author: xjm -* @Description: -* @Date: Wednesday, 23 December 2020 08:11:06 -* @Email: 326308290@qq.com -*/ - /// - /// 分表查询环境创建 - /// - public class ShardingScopeFactory : IShardingScopeFactory - { - private readonly IShardingAccessor _shardingAccessor; - - /// - /// 构造函数 - /// - /// - public ShardingScopeFactory(IShardingAccessor shardingAccessor) - { - _shardingAccessor = shardingAccessor; - } - /// - /// 创建scope - /// - /// - public ShardingScope CreateScope() - { - _shardingAccessor.ShardingContext = null; - return new ShardingScope(_shardingAccessor); - } - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRouteRuleEngine.cs index fbfc91ee..cf683763 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRouteRuleEngine.cs @@ -1,4 +1,7 @@ +using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine { @@ -10,6 +13,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine */ public interface IRouteRuleEngine { - IEnumerable Route(RouteRuleContext routeRuleContext); + IEnumerable Route(RouteRuleContext routeRuleContext) where TShardingDbContext:DbContext,IShardingDbContext; + IEnumerable Route(Type shardingDbContextType,RouteRuleContext routeRuleContext); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRoutingRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRoutingRuleEngineFactory.cs index c9f1c4eb..4cedf498 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRoutingRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/IRoutingRuleEngineFactory.cs @@ -1,5 +1,8 @@ +using System; using System.Collections.Generic; using System.Linq; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine { @@ -13,7 +16,9 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine { IRouteRuleEngine CreateEngine(); RouteRuleContext CreateContext(IQueryable queryable); - IEnumerable Route(IQueryable queryable); - IEnumerable Route(RouteRuleContext ruleContext); + IEnumerable Route(IQueryable queryable) where TShardingDbContext:DbContext,IShardingDbContext; + IEnumerable Route(RouteRuleContext ruleContext) where TShardingDbContext : DbContext, IShardingDbContext; + IEnumerable Route(Type shardingDbContextType,IQueryable queryable); + IEnumerable Route(Type shardingDbContextType,RouteRuleContext ruleContext); } } \ 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 7e6cde57..8687d3d2 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/QueryRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/QueryRouteRuleEngine.cs @@ -1,8 +1,12 @@ +using System; using System.Collections.Generic; using System.Linq; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualTables; using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; + #if !EFCORE5 using ShardingCore.Extensions; #endif @@ -24,30 +28,9 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine _virtualTableManager = virtualTableManager; } - public IEnumerable Route(RouteRuleContext routeRuleContext) + public IEnumerable Route(RouteRuleContext routeRuleContext) where TShardingDbContext : DbContext, IShardingDbContext { - Dictionary> routeMaps = new Dictionary>(); - var queryEntities = routeRuleContext.Queryable.ParseQueryableRoute(); - - - var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); - foreach (var shardingEntity in shardingEntities) - { - var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntity); - - var physicTables = virtualTable.RouteTo(new TableRouteConfig(routeRuleContext.Queryable)); - if (!routeMaps.ContainsKey(virtualTable)) - { - routeMaps.Add(virtualTable, physicTables.ToHashSet()); - } - else - { - foreach (var physicTable in physicTables) - { - routeMaps[virtualTable].Add(physicTable); - } - } - } + return Route(typeof(TShardingDbContext), routeRuleContext); ////先添加手动路由到当前上下文,之后将不再手动路由里面的自动路由添加到当前上下文 //foreach (var kv in routeRuleContext.ManualTails) //{ @@ -105,8 +88,34 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine // } // } //} + } - return routeMaps.Select(o => o.Value).Cartesian().Select(o=>new RouteResult(o)); + public IEnumerable Route(Type shardingDbContextType, RouteRuleContext routeRuleContext) + { + Dictionary> routeMaps = new Dictionary>(); + var queryEntities = routeRuleContext.Queryable.ParseQueryableRoute(); + + + var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); + foreach (var shardingEntity in shardingEntities) + { + var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntity); + + var physicTables = virtualTable.RouteTo(new TableRouteConfig(routeRuleContext.Queryable)); + if (!routeMaps.ContainsKey(virtualTable)) + { + routeMaps.Add(virtualTable, physicTables.ToHashSet()); + } + else + { + foreach (var physicTable in physicTables) + { + routeMaps[virtualTable].Add(physicTable); + } + } + } + + return routeMaps.Select(o => o.Value).Cartesian().Select(o => new RouteResult(o)); } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RoutingRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RoutingRuleEngineFactory.cs index fc761fe0..ebfb1aa3 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RoutingRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RoutingRuleEngineFactory.cs @@ -1,21 +1,24 @@ +using System; using System.Collections.Generic; using System.Linq; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualTables; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine { -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 28 January 2021 13:31:06 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Thursday, 28 January 2021 13:31:06 + * @Email: 326308290@qq.com + */ public class RoutingRuleEngineFactory : IRoutingRuleEngineFactory { private readonly IRouteRuleEngine _routeRuleEngine; private readonly IVirtualTableManager _virtualTableManager; - public RoutingRuleEngineFactory(IRouteRuleEngine routeRuleEngine,IVirtualTableManager virtualTableManager) + public RoutingRuleEngineFactory(IRouteRuleEngine routeRuleEngine, IVirtualTableManager virtualTableManager) { _routeRuleEngine = routeRuleEngine; _virtualTableManager = virtualTableManager; @@ -31,17 +34,30 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine return new RouteRuleContext(queryable, _virtualTableManager); } - public IEnumerable Route(IQueryable queryable) + public IEnumerable Route(IQueryable queryable) where TShardingDbContext : DbContext, IShardingDbContext { var engine = CreateEngine(); var ruleContext = CreateContext(queryable); - return engine.Route(ruleContext); + return engine.Route(ruleContext); } - public IEnumerable Route(RouteRuleContext ruleContext) + public IEnumerable Route(RouteRuleContext ruleContext) where TShardingDbContext : DbContext, IShardingDbContext { var engine = CreateEngine(); - return engine.Route(ruleContext); + return engine.Route(ruleContext); + } + + public IEnumerable Route(Type shardingDbContextType, IQueryable queryable) + { + var engine = CreateEngine(); + var ruleContext = CreateContext(queryable); + return engine.Route(shardingDbContextType,ruleContext); + } + + public IEnumerable Route(Type shardingDbContextType, RouteRuleContext ruleContext) + { + var engine = CreateEngine(); + return engine.Route(shardingDbContextType,ruleContext); } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs b/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs index 006172b4..36e18145 100644 --- a/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs +++ b/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.PhysicTables; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualTables { @@ -18,58 +20,70 @@ namespace ShardingCore.Core.VirtualTables /// /// 添加虚拟表应用启动时 add virtual table when app start /// + /// 分表的dbcontext类型 /// 虚拟表 - void AddVirtualTable(IVirtualTable virtualTable); + void AddVirtualTable(Type shardingDbContextType,IVirtualTable virtualTable); /// /// 获取虚拟表 get virtual table by sharding entity type /// + /// 分表的dbcontext类型 /// /// - IVirtualTable GetVirtualTable(Type shardingEntityType); + IVirtualTable GetVirtualTable(Type shardingDbContextType, Type shardingEntityType); /// /// 获取虚拟表 get virtual table by sharding entity type /// /// - IVirtualTable GetVirtualTable() where T : class, IShardingTable; + IVirtualTable GetVirtualTable() where T : class, IShardingTable where TDbContext : DbContext, IShardingDbContext; /// /// 获取虚拟表 get virtual table by original table name /// + /// 分表的dbcontext类型 /// /// - IVirtualTable GetVirtualTable(string originalTableName); + IVirtualTable GetVirtualTable(Type shardingDbContextType, string originalTableName); + IVirtualTable GetVirtualTable(string originalTableName) where TDbContext : DbContext, IShardingDbContext; /// /// 尝试获取虚拟表没有返回null /// + /// 分表的dbcontext类型 /// /// - IVirtualTable TryGetVirtualTable(string originalTableName); + IVirtualTable TryGetVirtualTable(Type shardingDbContextType, string originalTableName); + IVirtualTable TryGetVirtualTablee(string originalTableName) where TDbContext : DbContext, IShardingDbContext; /// /// 获取所有的虚拟表 get all virtual table /// + /// 分表的dbcontext类型 /// - List GetAllVirtualTables(); + List GetAllVirtualTables(Type shardingDbContextType); + List GetAllVirtualTables() where TDbContext : DbContext, IShardingDbContext; /// /// 添加物理表 add physic table /// + /// 分表的dbcontext类型 /// /// - void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable); + void AddPhysicTable(Type shardingDbContextType,IVirtualTable virtualTable, IPhysicTable physicTable); + void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable) where TDbContext : DbContext, IShardingDbContext; /// /// 添加物理表 add physic table /// + /// 分表的dbcontext类型 /// /// - void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable); + void AddPhysicTable(Type shardingDbContextType,Type shardingEntityType, IPhysicTable physicTable); + void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable) where TDbContext : DbContext, IShardingDbContext; ///// ///// 添加物理表 add physic table diff --git a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs index 2193f048..e95d8823 100644 --- a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs +++ b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs @@ -2,25 +2,29 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.PhysicTables; using ShardingCore.Exceptions; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualTables { -/* -* @Author: xjm -* @Description: -* @Date: Friday, 18 December 2020 14:52:42 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Friday, 18 December 2020 14:52:42 + * @Email: 326308290@qq.com + */ /// /// 同一个数据库下的虚拟表管理者 /// public class OneDbVirtualTableManager : IVirtualTableManager { private readonly IServiceProvider _serviceProvider; - private readonly ConcurrentDictionary _shardingVirtualTables = new ConcurrentDictionary(); - private readonly ConcurrentDictionary _shardingOriginalTaleVirtualTales = new ConcurrentDictionary(); + //{sharidngDbContextType:{entityType,virtualTableType}} + private readonly ConcurrentDictionary> _shardingVirtualTables = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _shardingOriginalTaleVirtualTales = new ConcurrentDictionary>(); public OneDbVirtualTableManager(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; @@ -38,62 +42,135 @@ namespace ShardingCore.Core.VirtualTables //} } - public void AddVirtualTable(IVirtualTable virtualTable) + private void CheckShardingDbContextType(Type shardingDbContextType) { - if (!_shardingVirtualTables.ContainsKey(virtualTable.EntityType)) + if (!shardingDbContextType.IsShardingDbContext()) + throw new ShardingCoreException( + $"{shardingDbContextType.FullName} must impl {nameof(IShardingDbContext)}"); + } + + private void CheckShardingTableEntityType(Type shardingEntityType) + { + if (!shardingEntityType.IsShardingTable()) + throw new ShardingCoreException( + $"{shardingEntityType.FullName} must impl {nameof(IShardingTable)}"); + } + private string CreateShardingEntityTypeKey(Type shardingDbContextType, Type entityType) + { + return $"{shardingDbContextType.FullName}{entityType.FullName}"; + } + private string CreateShardingTableNameKey(Type shardingDbContextType, string originalTableName) + { + return $"{shardingDbContextType.FullName}{originalTableName}"; + } + + public void AddVirtualTable(Type shardingDbContextType, IVirtualTable virtualTable) + { + CheckShardingDbContextType(shardingDbContextType); + + var innerShardingVirtualTables = _shardingVirtualTables.GetOrAdd(shardingDbContextType, + key => new ConcurrentDictionary()); + + if (!innerShardingVirtualTables.ContainsKey(virtualTable.EntityType)) { - _shardingVirtualTables.TryAdd(virtualTable.EntityType, virtualTable); + innerShardingVirtualTables.TryAdd(virtualTable.EntityType, virtualTable); } - if (!_shardingOriginalTaleVirtualTales.ContainsKey(virtualTable.GetOriginalTableName())) + var innerShardingOriginalTableVirtualTables = _shardingOriginalTaleVirtualTales.GetOrAdd(shardingDbContextType,type=>new ConcurrentDictionary()); + + if (!innerShardingOriginalTableVirtualTables.ContainsKey(virtualTable.GetOriginalTableName())) { - _shardingOriginalTaleVirtualTales.TryAdd(virtualTable.GetOriginalTableName(), virtualTable); + innerShardingOriginalTableVirtualTables.TryAdd(virtualTable.GetOriginalTableName(), virtualTable); } } - public IVirtualTable GetVirtualTable(Type shardingEntityType) + public IVirtualTable GetVirtualTable(Type shardingDbContextType, Type shardingEntityType) { - if (!_shardingVirtualTables.TryGetValue(shardingEntityType, out var virtualTable)) + CheckShardingDbContextType(shardingDbContextType); + CheckShardingTableEntityType(shardingEntityType); + + var shardingKey = CreateShardingEntityTypeKey(shardingDbContextType, shardingEntityType); + if(!_shardingVirtualTables.TryGetValue(shardingDbContextType,out var innerShardingVirtualTables) || innerShardingVirtualTables.IsEmpty()) + throw new ShardingVirtualTableNotFoundException(shardingDbContextType.FullName); + + if (!innerShardingVirtualTables.TryGetValue(shardingEntityType, out var virtualTable)||virtualTable==null) throw new ShardingVirtualTableNotFoundException(shardingEntityType.FullName); return virtualTable; } - public IVirtualTable GetVirtualTable() where T : class, IShardingTable + public IVirtualTable GetVirtualTable() where T : class, IShardingTable where TDbContext : DbContext, IShardingDbContext { - return (IVirtualTable)GetVirtualTable(typeof(T)); + return (IVirtualTable)GetVirtualTable(typeof(TDbContext), typeof(T)); } - public IVirtualTable GetVirtualTable(string originalTableName) + public IVirtualTable GetVirtualTable(Type shardingDbContextType, string originalTableName) { - if (!_shardingOriginalTaleVirtualTales.TryGetValue(originalTableName, out var virtualTable)||virtualTable==null) + CheckShardingDbContextType(shardingDbContextType); + if (!_shardingOriginalTaleVirtualTales.TryGetValue(shardingDbContextType, out var innerShardingOriginalTableVirtualTables) || innerShardingOriginalTableVirtualTables.IsEmpty()) + throw new ShardingVirtualTableNotFoundException(shardingDbContextType.FullName); + if(!innerShardingOriginalTableVirtualTables.TryGetValue(originalTableName,out var virtualTable)|| virtualTable==null) throw new ShardingVirtualTableNotFoundException(originalTableName); return virtualTable; } - public IVirtualTable TryGetVirtualTable(string originalTableName) + public IVirtualTable GetVirtualTable(string originalTableName) where TDbContext : DbContext, IShardingDbContext { - if (!_shardingOriginalTaleVirtualTales.TryGetValue(originalTableName, out var virtualTable)) + return GetVirtualTable(typeof(TDbContext), originalTableName); + } + + public IVirtualTable TryGetVirtualTable(Type shardingDbContextType, string originalTableName) + { + CheckShardingDbContextType(shardingDbContextType); + if (!_shardingOriginalTaleVirtualTales.TryGetValue(shardingDbContextType, + out var innerShardingOriginalTableVirtualTables) || innerShardingOriginalTableVirtualTables.IsEmpty()) + return null; + if (!innerShardingOriginalTableVirtualTables.TryGetValue(originalTableName, out var virtualTable) || virtualTable == null) return null; return virtualTable; } - public List GetAllVirtualTables() + public IVirtualTable TryGetVirtualTablee(string originalTableName) where TDbContext : DbContext, IShardingDbContext { - return _shardingVirtualTables.Values.ToList(); + return TryGetVirtualTable(typeof(TDbContext), originalTableName); } - public void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable) + public List GetAllVirtualTables(Type shardingDbContextType) { - AddPhysicTable(virtualTable.EntityType, physicTable); + if (!_shardingOriginalTaleVirtualTales.TryGetValue(shardingDbContextType, + out var innerShardingOriginalTableVirtualTables) || innerShardingOriginalTableVirtualTables.IsEmpty()) + return new List(); + var keyPrefix = shardingDbContextType.FullName; + return innerShardingOriginalTableVirtualTables.Values.ToList(); } - public void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable) + public List GetAllVirtualTables() where TDbContext : DbContext, IShardingDbContext { - var virtualTable = GetVirtualTable(shardingEntityType); + return GetAllVirtualTables(typeof(TDbContext)); + } + + public void AddPhysicTable(Type shardingDbContextType, IVirtualTable virtualTable, IPhysicTable physicTable) + { + AddPhysicTable(shardingDbContextType, virtualTable.EntityType, physicTable); + } + + public void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable) where TDbContext : DbContext, IShardingDbContext + { + AddPhysicTable(typeof(TDbContext), virtualTable.EntityType, physicTable); + } + + + public void AddPhysicTable(Type shardingDbContextType, Type shardingEntityType, IPhysicTable physicTable) + { + var virtualTable = GetVirtualTable(shardingDbContextType, shardingEntityType); virtualTable.AddPhysicTable(physicTable); } + public void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable) where TDbContext : DbContext, IShardingDbContext + { + var virtualTable = GetVirtualTable(typeof(TDbContext), shardingEntityType); + virtualTable.AddPhysicTable(physicTable); + } ///// ///// 是否是分表字段 @@ -103,7 +180,7 @@ namespace ShardingCore.Core.VirtualTables ///// //public bool IsShardingKey(Type shardingEntityType, string shardingField) //{ - // return _virtualTables.TryGetValue(shardingEntityType, out var virtualTable) && virtualTable.ShardingConfig.ShardingField == shardingField; + // return _virtualTables.TryGetValue(shardingEntityType, out var virtualTable) && virtualTable.ShardingConfigOption.ShardingField == shardingField; //} } } \ No newline at end of file diff --git a/src/ShardingCore/DIExtension.cs b/src/ShardingCore/DIExtension.cs index 1e89265f..a2e8f34e 100644 --- a/src/ShardingCore/DIExtension.cs +++ b/src/ShardingCore/DIExtension.cs @@ -1,17 +1,17 @@ -using System; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.DependencyInjection; -using ShardingCore.Core.Internal.StreamMerge; -using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Core.VirtualTables; using ShardingCore.DbContexts; -using ShardingCore.DbContexts.Abstractions; -using ShardingCore.DbContexts.ShardingDbContexts; +using ShardingCore.EFCores; +using ShardingCore.Helpers; using ShardingCore.Sharding; using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.Enumerators; using ShardingCore.TableCreator; +using System; namespace ShardingCore { @@ -24,9 +24,48 @@ namespace ShardingCore public static class DIExtension { - public static IServiceCollection AddShardingCore(this IServiceCollection services) + + public static IServiceCollection AddShardingDbContext(this IServiceCollection services, + Action optionsAction = null, + Action> configure=null, + ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + where TActualDbContext : DbContext, IShardingTableDbContext + where TShardingDbContext : DbContext, IShardingTableDbContext + { + if (configure == null) + throw new ArgumentNullException($"AddShardingDbContext params is null :{nameof(configure)}"); + + ShardingCoreHelper.CheckContextConstructors(); + var shardingConfigOptions = new ShardingConfigOption(); + configure?.Invoke(shardingConfigOptions); + services.AddSingleton>(sp=> shardingConfigOptions); + + + //添加创建TActualDbContext 的 创建者 + var config = new ShardingDbContextOptionsBuilderConfig(shardingConfigOptions.ShardingDbContextOptionsCreator); + services.AddSingleton>(sp=> config); + + //添加创建TActualDbContext创建者 + services.AddSingleton>(sp=> new DefaultShardingDbContextCreatorConfig(typeof(TActualDbContext))); + + + Action shardingOptionAction = option => + { + optionsAction?.Invoke(option); + option.UseSharding(); + }; + services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); + services.AddInternalShardingCore(); + + + + services.AddSingleton(); + return services; + } + + internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services) { - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -38,33 +77,20 @@ namespace ShardingCore //分表引擎 services.AddSingleton(); //services.AddSingleton(typeof(IVirtualTable<>), typeof(OneDbVirtualTable<>)); - services.AddSingleton(); - services.AddSingleton(); + //services.AddSingleton(); + //services.AddSingleton(); return services; } - - public static IServiceCollection AddShardingDbContext(this IServiceCollection services, - Action> configure, - Action optionsAction = null, - ServiceLifetime contextLifetime = ServiceLifetime.Scoped, - ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) - where TActualDbContext : DbContext, IShardingTableDbContext - where TShardingDbContext : DbContext + internal static DbContextOptionsBuilder UseSharding(this DbContextOptionsBuilder optionsBuilder) { - if (configure == null) - throw new ArgumentNullException($"AddScfSqlServerProvider 参数不能为空:{nameof(configure)}"); - var shardingConfig = new ShardingConfig(); - configure?.Invoke(shardingConfig); - services.AddSingleton(shardingConfig); - - services.AddDbContext(optionsAction, contextLifetime, optionsLifetime); - services.AddShardingCore(); - - - - services.AddSingleton(); - return services; + return optionsBuilder.ReplaceService() + .ReplaceService(); + } + internal static DbContextOptionsBuilder UseInnerDbContextSharding(this DbContextOptionsBuilder optionsBuilder) where TShardingDbContext:DbContext,IShardingDbContext + { + return optionsBuilder.ReplaceService() + .ReplaceService>(); } } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/Abstractions/DbContextCreateFilterManager.cs b/src/ShardingCore/DbContexts/Abstractions/DbContextCreateFilterManager.cs deleted file mode 100644 index dc69e588..00000000 --- a/src/ShardingCore/DbContexts/Abstractions/DbContextCreateFilterManager.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace ShardingCore.DbContexts.Abstractions -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/3/13 8:19:26 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class DbContextCreateFilterManager: IDbContextCreateFilterManager - { - private readonly List _filters = new List(); - public void RegisterFilter(IDbContextCreateFilter filter) - { - if (null == filter) - throw new ArgumentNullException(nameof(filter)); - if(!_filters.Contains(filter)) - _filters.Add(filter); - } - - public List GetFilters() - { - return _filters; - } - } -} diff --git a/src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilter.cs b/src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilter.cs deleted file mode 100644 index e284cdc3..00000000 --- a/src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.EntityFrameworkCore; - -namespace ShardingCore.DbContexts.Abstractions -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/3/13 8:17:41 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public interface IDbContextCreateFilter - { - /// - /// dbContext创建完成后 - /// - /// - /// - void CreateAfter(DbContext dbContext); - } -} diff --git a/src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilterManager.cs b/src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilterManager.cs deleted file mode 100644 index ed85ea58..00000000 --- a/src/ShardingCore/DbContexts/Abstractions/IDbContextCreateFilterManager.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace ShardingCore.DbContexts.Abstractions -{ -/* -* @Author: xjm -* @Description: -* @Date: Friday, 12 March 2021 22:25:10 -* @Email: 326308290@qq.com -*/ - public interface IDbContextCreateFilterManager - { - - void RegisterFilter(IDbContextCreateFilter filter); - List GetFilters(); - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/Abstractions/ShardingDbContextOptionBuilder.cs b/src/ShardingCore/DbContexts/Abstractions/ShardingDbContextOptionBuilder.cs deleted file mode 100644 index fec86216..00000000 --- a/src/ShardingCore/DbContexts/Abstractions/ShardingDbContextOptionBuilder.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.Extensions.Logging; -using ShardingCore.EFCores; - -namespace ShardingCore.DbContexts.Abstractions -{ -/* -* @Author: xjm -* @Description: -* @Date: Sunday, 07 February 2021 15:25:36 -* @Email: 326308290@qq.com -*/ - public class ShardingDbContextOptionBuilder - { - - private readonly DbContextOptionsBuilder _builder; - public ShardingDbContextOptionBuilder():this(new DbContextOptionsBuilder()) - { - - } - public ShardingDbContextOptionBuilder(DbContextOptionsBuilder optionsBuilder) - { - _builder = optionsBuilder - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - .ReplaceService() - .ReplaceService() - .ReplaceService(); - } - - public ShardingDbContextOptionBuilder UseLoggerFactory(ILoggerFactory loggerFactory) - { - _builder.UseLoggerFactory(loggerFactory); - return this; - } - - public DbContextOptionsBuilder GetOptionsBuilder() - { - return _builder; - } - } - public class ShardingDbContextOptionBuilder:ShardingDbContextOptionBuilder where T:DbContext - { - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs index a4a35c4a..d2b50f6a 100644 --- a/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs @@ -3,6 +3,7 @@ using System.Data.Common; using Microsoft.EntityFrameworkCore; using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.VirtualDbContexts; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.DbContexts { @@ -14,7 +15,8 @@ namespace ShardingCore.DbContexts */ public interface IShardingDbContextFactory { - DbContext Create(ShardingDbContextOptions shardingDbContextOptions); + DbContext Create(Type shardingDbContextType,ShardingDbContextOptions shardingDbContextOptions); + DbContext Create(ShardingDbContextOptions shardingDbContextOptions) where TShardingDbContext:DbContext,IShardingDbContext; //DbContext Create(DbConnection dbConnection,string tail); } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs b/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs deleted file mode 100644 index 75fd29d2..00000000 --- a/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; - -namespace ShardingCore.DbContexts -{ -/* -* @Author: xjm -* @Description: -* @Date: Tuesday, 29 December 2020 15:22:06 -* @Email: 326308290@qq.com -*/ - public interface IShardingParallelDbContextFactory - { - DbContext Create(string tail); - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/IShardingParallelDbContextFactoryManager.cs b/src/ShardingCore/DbContexts/IShardingParallelDbContextFactoryManager.cs deleted file mode 100644 index c5096a5b..00000000 --- a/src/ShardingCore/DbContexts/IShardingParallelDbContextFactoryManager.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; - -namespace ShardingCore.DbContexts -{ -/* -* @Author: xjm -* @Description: -* @Date: Saturday, 20 February 2021 15:04:25 -* @Email: 326308290@qq.com -*/ - public interface IShardingParallelDbContextFactoryManager - { - public DbContext CreateDbContext(string connectKey, string tail); - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs index f96eed5c..1e9fea0c 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs @@ -1,64 +1,54 @@ -using System; -using System.Data.Common; -using System.Linq; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using ShardingCore.Core.VirtualTables; -using ShardingCore.DbContexts.Abstractions; using ShardingCore.DbContexts.ShardingDbContexts; -using ShardingCore.DbContexts.VirtualDbContexts; +using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.Sharding.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; namespace ShardingCore.DbContexts { -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 24 December 2020 08:22:48 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Thursday, 24 December 2020 08:22:48 + * @Email: 326308290@qq.com + */ public class ShardingDbContextFactory:IShardingDbContextFactory { - private readonly IShardingCoreOptions _shardingCoreOptions; - private readonly IDbContextCreateFilterManager _dbContextCreateFilterManager; - private readonly IDbContextOptionsProvider _dbContextOptionsProvider; + private readonly IEnumerable _shardingDbContextCreatorConfigs; - public ShardingDbContextFactory(IShardingCoreOptions shardingCoreOptions, IDbContextCreateFilterManager dbContextCreateFilterManager,IDbContextOptionsProvider dbContextOptionsProvider) + public ShardingDbContextFactory(IEnumerable shardingDbContextCreatorConfigs) { - _shardingCoreOptions = shardingCoreOptions; - _dbContextCreateFilterManager = dbContextCreateFilterManager; - _dbContextOptionsProvider = dbContextOptionsProvider; + _shardingDbContextCreatorConfigs = shardingDbContextCreatorConfigs; } - public DbContext Create(ShardingDbContextOptions shardingDbContextOptions) + public DbContext Create(Type shardingDbContextType, ShardingDbContextOptions shardingDbContextOptions) { + if (!shardingDbContextType.IsShardingDbContext()) + throw new ShardingCoreException( + $"{shardingDbContextType.FullName} must impl {nameof(IShardingDbContext)}"); + var shardingDbContextCreatorConfig = _shardingDbContextCreatorConfigs.FirstOrDefault(o=>o.ShardingDbContextType==shardingDbContextType); + if (shardingDbContextCreatorConfig == null) + { + throw new ShardingCoreException( + $"{shardingDbContextType.FullName} cant found DefaultShardingDbContextCreatorConfig<{shardingDbContextType.Name}> should use {nameof(DIExtension.AddShardingDbContext)}"); + } var tail=shardingDbContextOptions.Tail; - var shardingConfigEntry = _shardingCoreOptions.GetShardingConfig(); - var dbContext = shardingConfigEntry.Creator(shardingDbContextOptions); + var dbContext = shardingDbContextCreatorConfig.Creator(shardingDbContextOptions); if (!string.IsNullOrWhiteSpace(tail) && dbContext is IShardingTableDbContext shardingTableDbContext) { shardingTableDbContext.SetShardingTableDbContextTail(tail); } - - var filters = _dbContextCreateFilterManager.GetFilters(); - if (filters.Any()) - { - foreach (var dbContextCreateFilter in filters) - { - dbContextCreateFilter.CreateAfter(dbContext); - } - } var dbContextModel = dbContext.Model; return dbContext; } - //public DbContext Create(DbConnection dbConnection,string tail) - //{ - // var shardingDbContextOptions = - // new ShardingDbContextOptions(_dbContextOptionsProvider.GetDbContextOptions(dbConnection), tail); - // return Create(shardingDbContextOptions); - //} + public DbContext Create(ShardingDbContextOptions shardingDbContextOptions) where TShardingDbContext : DbContext, IShardingDbContext + { + return Create(typeof(TShardingDbContext), shardingDbContextOptions); + } } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/Transactions/IShardingTransaction.cs b/src/ShardingCore/DbContexts/Transactions/IShardingTransaction.cs deleted file mode 100644 index 0679cafa..00000000 --- a/src/ShardingCore/DbContexts/Transactions/IShardingTransaction.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; - -namespace ShardingCore.DbContexts.Transactions -{ -/* -* @Author: xjm -* @Description: -* @Date: Saturday, 14 August 2021 04:19:53 -* @Email: 326308290@qq.com -*/ - public interface IShardingTransaction:IDisposable - { - bool IsOpened { get; } - bool IsUsed { get; } - void Use(DbContext dbContext); - void Open(); - void Rollback(); - Task RollbackAsync(); - void Commit(); - Task CommitAsync(); - IDbContextTransaction GetDbContextTransaction(); - } -} diff --git a/src/ShardingCore/DbContexts/Transactions/ShardingTransaction.cs b/src/ShardingCore/DbContexts/Transactions/ShardingTransaction.cs deleted file mode 100644 index c1abcc25..00000000 --- a/src/ShardingCore/DbContexts/Transactions/ShardingTransaction.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using ShardingCore.Exceptions; - -namespace ShardingCore.DbContexts.Transactions -{ -/* -* @Author: xjm -* @Description: -* @Date: Saturday, 14 August 2021 04:20:53 -* @Email: 326308290@qq.com -*/ - public class ShardingTransaction: IShardingTransaction - { - private IDbContextTransaction _dbTransaction; - private bool _isOpened; - public bool IsOpened => _isOpened; - public bool IsUsed => _dbTransaction != null; - private readonly ISet _dbContextUseTransactions = new HashSet(); - - public void Use(DbContext dbContext) - { - if (!_isOpened) - throw new ShardingTransactionException($"{nameof(ShardingTransaction)} is not open"); - if (!_dbContextUseTransactions.Contains(dbContext)) - { - if (!IsUsed) - _dbTransaction = dbContext.Database.BeginTransaction(); - else - dbContext.Database.UseTransaction(_dbTransaction.GetDbTransaction()); - _dbContextUseTransactions.Add(dbContext); - } - } - - public void Open() - { - _isOpened = true; - } - - private void Close() - { - _isOpened = false; - _dbContextUseTransactions.Clear(); - } - - public void Rollback() - { - _dbTransaction?.Rollback(); - } - -#if EFCORE2 - public Task RollbackAsync() - { - _dbTransaction?.Rollback(); - return Task.CompletedTask; - } -#endif - -#if !EFCORE2 - public async Task RollbackAsync() - { - if (_dbTransaction != null) - await _dbTransaction.RollbackAsync(); - } -#endif - - public void Commit() - { - _dbTransaction?.Commit(); - } - -#if EFCORE2 - public Task CommitAsync() - { - _dbTransaction?.Commit(); - return Task.CompletedTask; - } -#endif -#if !EFCORE2 - public async Task CommitAsync() - { - if (_dbTransaction != null) - await _dbTransaction.CommitAsync(); - } -#endif - - public IDbContextTransaction GetDbContextTransaction() - { - return _dbTransaction; - } - - public void Dispose() - { - Close(); - _dbTransaction?.Dispose(); - _dbTransaction = null; - } - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs b/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs deleted file mode 100644 index 11393b8b..00000000 --- a/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Data.Common; -using Microsoft.EntityFrameworkCore; - -namespace ShardingCore.DbContexts.VirtualDbContexts -{ -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 24 December 2020 10:32:07 -* @Email: 326308290@qq.com -*/ - public interface IDbContextOptionsProvider - { - /// - /// 创建数据库链接配置 - /// - /// - /// - DbContextOptions GetDbContextOptions(DbConnection dbConnection); - - } -} \ No newline at end of file diff --git a/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs b/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs new file mode 100644 index 00000000..9478f2fb --- /dev/null +++ b/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore; +using ShardingCore.DbContexts.Abstractions; +using ShardingCore.Helpers; +using ShardingCore.Sharding.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.DbContexts.ShardingDbContexts; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 17:30:10 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DefaultShardingDbContextCreatorConfig : IShardingDbContextCreatorConfig + where TShardingDbContext : DbContext, IShardingDbContext + where TActualDbContext : DbContext, IShardingTableDbContext + { + private readonly Func _creator; + public DefaultShardingDbContextCreatorConfig(Type actualDbContextType) + { + ActualDbContextType = actualDbContextType; + _creator = ShardingCoreHelper.CreateActivator(); + } + + public Type ShardingDbContextType => typeof(TShardingDbContext); + public Type ActualDbContextType { get; } + public DbContext Creator(ShardingDbContextOptions shardingDbContextOptions) + { + return _creator(shardingDbContextOptions); + } + } +} diff --git a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs index ecbe1ca9..2afb8188 100644 --- a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs +++ b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs @@ -20,8 +20,9 @@ namespace ShardingCore.EFCores * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class ShardingModelCustomizer: ModelCustomizer + public class ShardingModelCustomizer: ModelCustomizer where TShardingDbContext:DbContext,IShardingDbContext { + private Type _shardingDbContextType => typeof(TShardingDbContext); public ShardingModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies) { } @@ -36,7 +37,7 @@ namespace ShardingCore.EFCores if (!string.IsNullOrWhiteSpace(tail)) { var virtualTableManager = ShardingContainer.Services.GetService(); - var typeMap = virtualTableManager.GetAllVirtualTables().Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet(); + var typeMap = virtualTableManager.GetAllVirtualTables(_shardingDbContextType).Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet(); //设置分表 var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable() && typeMap.Contains(o.ClrType)); diff --git a/src/ShardingCore/Extensions/CommonExtension.cs b/src/ShardingCore/Extensions/CommonExtension.cs index 2f228f0c..7ef2cf30 100644 --- a/src/ShardingCore/Extensions/CommonExtension.cs +++ b/src/ShardingCore/Extensions/CommonExtension.cs @@ -21,6 +21,32 @@ namespace ShardingCore.Extensions */ public static class CommonExtension { + + /// + /// IShardingDbContext + /// + /// + /// + public static bool IsShardingDbContext(this DbContext dbContext) + { + if (dbContext == null) + throw new ArgumentNullException(nameof(dbContext)); + return dbContext is IShardingDbContext; + } + /// + /// IShardingDbContext + /// + /// + /// + public static bool IsShardingDbContext(this Type dbContextType) + { + if (dbContextType == null) + throw new ArgumentNullException(nameof(dbContextType)); + if (!typeof(DbContext).IsAssignableFrom(dbContextType)) + return false; + return typeof(IShardingDbContext).IsAssignableFrom(dbContextType); + } + /// /// IShardingTableDbContext /// @@ -41,6 +67,8 @@ namespace ShardingCore.Extensions { if (dbContextType == null) throw new ArgumentNullException(nameof(dbContextType)); + if (!typeof(DbContext).IsAssignableFrom(dbContextType)) + return false; return typeof(IShardingTableDbContext).IsAssignableFrom(dbContextType); } /// @@ -64,7 +92,7 @@ namespace ShardingCore.Extensions { if (entity == null) throw new ArgumentNullException(nameof(entity)); - return typeof(IShardingTable).IsAssignableFrom(entity.GetType()); + return entity is IShardingTable; } // /// // /// 虚拟表转换成对应的db配置 @@ -73,7 +101,7 @@ namespace ShardingCore.Extensions // /// // public static List GetVirtualTableDbContextConfigs(this List virtualTables) // { - // return virtualTables.Select(o => new VirtualTableDbContextConfig(o.EntityType, o.GetOriginalTableName(), o.ShardingConfig.TailPrefix)).ToList(); + // return virtualTables.Select(o => new VirtualTableDbContextConfig(o.EntityType, o.GetOriginalTableName(), o.ShardingConfigOption.TailPrefix)).ToList(); // } /// /// 是否是集合contains方法 diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs index 798056a2..234af5b5 100644 --- a/src/ShardingCore/Extensions/ShardingExtension.cs +++ b/src/ShardingCore/Extensions/ShardingExtension.cs @@ -26,9 +26,7 @@ namespace ShardingCore.Extensions /// public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext) { - if (string.IsNullOrWhiteSpace(dbContext.ModelChangeKey)) - throw new ShardingCoreException($"cant found ModelChangeKey in {dbContext.GetType().FullName}"); - return dbContext.ModelChangeKey.Replace(ShardingTableDbContextFormat, string.Empty); + return dbContext.ModelChangeKey?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty; } /// diff --git a/src/ShardingCore/Helpers/ShardingCoreHelper.cs b/src/ShardingCore/Helpers/ShardingCoreHelper.cs index 10b6177f..f6d4af14 100644 --- a/src/ShardingCore/Helpers/ShardingCoreHelper.cs +++ b/src/ShardingCore/Helpers/ShardingCoreHelper.cs @@ -6,23 +6,26 @@ using Microsoft.EntityFrameworkCore; using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.Exceptions; using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Helpers { -/* -* @Author: xjm -* @Description: -* @Date: Friday, 22 January 2021 13:32:08 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Friday, 22 January 2021 13:32:08 + * @Email: 326308290@qq.com + */ public class ShardingCoreHelper { - private ShardingCoreHelper(){} + private ShardingCoreHelper() { } public static int GetStringHashCode(string value) { int h = 0; // 默认值是0 - if (value.Length > 0) { - for (int i = 0; i < value.Length; i++) { + if (value.Length > 0) + { + for (int i = 0; i < value.Length; i++) + { h = 31 * h + value[i]; // val[0]*31^(n-1) + val[1]*31^(n-2) + ... + val[n-1] } } @@ -36,7 +39,7 @@ namespace ShardingCore.Helpers } public static long ConvertDateTimeToLong(DateTime time) { - return (long) (time.AddHours(-8) - UtcStartTime).TotalMilliseconds; + return (long)(time.AddHours(-8) - UtcStartTime).TotalMilliseconds; } /// @@ -61,7 +64,7 @@ namespace ShardingCore.Helpers public static DateTime GetCurrentMonday(DateTime time) { DateTime dateTime1 = new DateTime(time.Year, time.Month, time.Day); - int num = (int) (time.DayOfWeek - 1); + int num = (int)(time.DayOfWeek - 1); if (num == -1) num = 6; return dateTime1.AddDays(-num); @@ -88,7 +91,7 @@ namespace ShardingCore.Helpers } var paramType = declaredConstructors[0].GetParameters()[0].ParameterType; - if (paramType != typeof(ShardingDbContextOptions) && paramType != typeof(DbContextOptions) && paramType!= typeof(DbContextOptions)) + if (paramType != typeof(ShardingDbContextOptions) && paramType != typeof(DbContextOptions) && paramType != typeof(DbContextOptions)) { throw new ArgumentException($"dbcontext : {contextType} declared constructor parameters should use {typeof(ShardingDbContextOptions)} or {typeof(DbContextOptions)} or {typeof(DbContextOptions)} "); } @@ -103,8 +106,7 @@ namespace ShardingCore.Helpers //} } - - public static Func CreateActivator() where TContext : DbContext + public static Func CreateActivator() where TContext : DbContext, IShardingTableDbContext { var constructors = typeof(TContext).GetTypeInfo().DeclaredConstructors @@ -118,7 +120,7 @@ namespace ShardingCore.Helpers if (parameterType == typeof(ShardingDbContextOptions)) { - return CreateShardingDbContextOptionsActivator(constructors[0],parameterType); + return CreateShardingDbContextOptionsActivator(constructors[0], parameterType); } else if (typeof(DbContextOptions).IsAssignableFrom(parameterType)) { @@ -147,7 +149,7 @@ namespace ShardingCore.Helpers /// /// /// - private static Func CreateShardingDbContextOptionsActivator(ConstructorInfo constructor,Type paramType) where TContext : DbContext + private static Func CreateShardingDbContextOptionsActivator(ConstructorInfo constructor, Type paramType) where TContext : DbContext, IShardingTableDbContext { var po = Expression.Parameter(paramType, "o"); var newExpression = Expression.New(constructor, po); @@ -166,7 +168,7 @@ namespace ShardingCore.Helpers /// /// /// - private static Func CreateDbContextOptionsGenericActivator(ConstructorInfo constructor,Type paramType) where TContext : DbContext + private static Func CreateDbContextOptionsGenericActivator(ConstructorInfo constructor, Type paramType) where TContext : DbContext, IShardingTableDbContext { var parameterExpression = Expression.Parameter(typeof(ShardingDbContextOptions), "o"); //o.DbContextOptions diff --git a/src/ShardingCore/IShardingBootstrapper.cs b/src/ShardingCore/IShardingBootstrapper.cs index 4d05a0de..b0196738 100644 --- a/src/ShardingCore/IShardingBootstrapper.cs +++ b/src/ShardingCore/IShardingBootstrapper.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; namespace ShardingCore { diff --git a/src/ShardingCore/IShardingConfigOption.cs b/src/ShardingCore/IShardingConfigOption.cs new file mode 100644 index 00000000..db722c0a --- /dev/null +++ b/src/ShardingCore/IShardingConfigOption.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ShardingCore.Core.VirtualRoutes.TableRoutes; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/8/20 6:56:49 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public interface IShardingConfigOption + { + Type ShardingDbContextType { get;} + Type ActualDbContextType { get;} + + void AddShardingTableRoute() where TRoute : IVirtualTableRoute; + Type GetVirtualRouteType(Type entityType); + + + /// + /// 如果数据库不存在就创建并且创建表除了分表的 + /// + public bool EnsureCreatedWithOutShardingTable { get; set; } + /// + /// 是否需要在启动时创建分表 + /// + public bool? CreateShardingTableOnStart { get; set; } + /// + /// 忽略建表时的错误 + /// + public bool? IgnoreCreateTableError { get; set; } + } +} diff --git a/src/ShardingCore/IShardingCoreOptions.cs b/src/ShardingCore/IShardingCoreOptions.cs deleted file mode 100644 index 94b8d9ac..00000000 --- a/src/ShardingCore/IShardingCoreOptions.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using ShardingCore.DbContexts.Abstractions; -using System; -using System.Collections.Generic; -using ShardingCore.Sharding.Abstractions; - -namespace ShardingCore -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/3/4 13:11:16 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public interface IShardingCoreOptions - { - void UseShardingDbContext( - Action func) where T : DbContext, IShardingTableDbContext; - - - - - ShardingConfigEntry GetShardingConfig(); - ISet GetVirtualRoutes(); - Type GetVirtualRoute(Type entityType); - - - - /// - /// 如果数据库不存在就创建并且创建表除了分表的 - /// - bool EnsureCreatedWithOutShardingTable { get; set; } - /// - /// 是否需要在启动时创建分表 - /// - bool? CreateShardingTableOnStart { get; set; } - - /// - /// 添加filter过滤器 - /// - /// - public void AddDbContextCreateFilter() where TFilter : class, IDbContextCreateFilter; - - public List GetFilters(); - - bool? IgnoreCreateTableError { get; set; } - - } -} diff --git a/src/ShardingCore/IShardingDbContextCreatorConfig.cs b/src/ShardingCore/IShardingDbContextCreatorConfig.cs new file mode 100644 index 00000000..ff1ef9ba --- /dev/null +++ b/src/ShardingCore/IShardingDbContextCreatorConfig.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using ShardingCore.DbContexts.Abstractions; +using System; +using System.Collections.Generic; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.DbContexts.ShardingDbContexts; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/4 13:11:16 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public interface IShardingDbContextCreatorConfig + { + Type ShardingDbContextType { get; } + Type ActualDbContextType { get; } + + DbContext Creator(ShardingDbContextOptions shardingDbContextOptions); + + } +} diff --git a/src/ShardingCore/IShardingDbContextOptionsBuilderConfig.cs b/src/ShardingCore/IShardingDbContextOptionsBuilderConfig.cs new file mode 100644 index 00000000..85dc66e4 --- /dev/null +++ b/src/ShardingCore/IShardingDbContextOptionsBuilderConfig.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Text; +using Microsoft.EntityFrameworkCore; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/8/20 11:34:55 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public interface IShardingDbContextOptionsBuilderConfig + { + Type ShardingDbContextType { get; } + DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder); + } +} diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index d09a69b5..0bb39f55 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -30,13 +31,13 @@ namespace ShardingCore.Sharding /// 分表分库的dbcontext /// /// - public abstract class AbstractShardingDbContext : DbContext, IShardingDbContext where T : DbContext, IShardingTableDbContext + public abstract class AbstractShardingDbContext : DbContext, IShardingTableDbContext where T : DbContext, IShardingTableDbContext { private readonly string EMPTY_SHARDING_TAIL_ID = Guid.NewGuid().ToString("n"); private readonly ConcurrentDictionary _dbContextCaches = new ConcurrentDictionary(); private readonly IVirtualTableManager _virtualTableManager; private readonly IShardingDbContextFactory _shardingDbContextFactory; - private readonly ShardingConfig _shardingConfig; + private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig; private DbContextOptions _dbContextOptions; private readonly object CREATELOCK = new object(); @@ -45,10 +46,13 @@ namespace ShardingCore.Sharding { _shardingDbContextFactory = ShardingContainer.GetService(); _virtualTableManager = ShardingContainer.GetService(); - _shardingConfig = ShardingContainer.GetService>(); + _shardingDbContextOptionsBuilderConfig = ShardingContainer + .GetService>() + .FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType); } + public abstract Type ShardingDbContextType { get; } public Type ActualDbContextType => typeof(T); @@ -64,8 +68,8 @@ namespace ShardingCore.Sharding { var dbContextOptionBuilder = CreateDbContextOptionBuilder(); var dbConnection = Database.GetDbConnection(); - dbConnection.Open(); - return _shardingConfig.ShardingDbContextOptionsCreator(dbConnection, dbContextOptionBuilder); + _shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(dbConnection, dbContextOptionBuilder); + return dbContextOptionBuilder.Options; } private ShardingDbContextOptions CreateSameShardingDbContextOptions(string tail) @@ -87,7 +91,7 @@ namespace ShardingCore.Sharding { if (!_dbContextCaches.TryGetValue(tail, out var dbContext)) { - dbContext = _shardingDbContextFactory.Create(CreateSameShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail)); + dbContext = _shardingDbContextFactory.Create(ShardingDbContextType,CreateSameShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail)); _dbContextCaches.TryAdd(tail, dbContext); } @@ -101,13 +105,25 @@ namespace ShardingCore.Sharding var tail = EMPTY_SHARDING_TAIL_ID; if (entity.IsShardingTable()) { - var physicTable = _virtualTableManager.GetVirtualTable(entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0]; + var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType,entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0]; tail = physicTable.Tail; } return GetDbContext(true, tail); } + public bool TryOpen() + { + var dbConnection = Database.GetDbConnection(); + if (dbConnection.State != ConnectionState.Open) + { + dbConnection.Open(); + return true; + } + + return false; + } + public override EntityEntry Add(object entity) { return CreateGenericDbContext(entity).Add(entity); @@ -380,12 +396,14 @@ namespace ShardingCore.Sharding finally { if (!isBeginTransaction) - Database.CurrentTransaction?.Dispose(); - - foreach (var dbContextCache in _dbContextCaches) { - dbContextCache.Value.Database.UseTransaction(null); + Database.CurrentTransaction?.Dispose(); + foreach (var dbContextCache in _dbContextCaches) + { + dbContextCache.Value.Database.UseTransaction(null); + } } + } return i; } @@ -415,11 +433,12 @@ namespace ShardingCore.Sharding finally { if (!isBeginTransaction) - Database.CurrentTransaction?.Dispose(); - - foreach (var dbContextCache in _dbContextCaches) { - dbContextCache.Value.Database.UseTransaction(null); + Database.CurrentTransaction?.Dispose(); + foreach (var dbContextCache in _dbContextCaches) + { + dbContextCache.Value.Database.UseTransaction(null); + } } } return i; @@ -451,12 +470,14 @@ namespace ShardingCore.Sharding { if (!isBeginTransaction) { } if (Database.CurrentTransaction != null) - await Database.CurrentTransaction.DisposeAsync(); - - foreach (var dbContextCache in _dbContextCaches) { - await dbContextCache.Value.Database.UseTransactionAsync(null, cancellationToken: cancellationToken); + await Database.CurrentTransaction.DisposeAsync(); + foreach (var dbContextCache in _dbContextCaches) + { + await dbContextCache.Value.Database.UseTransactionAsync(null, cancellationToken: cancellationToken); + } } + } return i; } @@ -487,12 +508,15 @@ namespace ShardingCore.Sharding { if (!isBeginTransaction) if (Database.CurrentTransaction != null) + { await Database.CurrentTransaction.DisposeAsync(); - foreach (var dbContextCache in _dbContextCaches) - { - await dbContextCache.Value.Database.UseTransactionAsync(null, cancellationToken: cancellationToken); - } + foreach (var dbContextCache in _dbContextCaches) + { + await dbContextCache.Value.Database.UseTransactionAsync(null, cancellationToken: cancellationToken); + } + } + } return i; } diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs index 8cafeea1..1ccd641c 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs @@ -13,14 +13,15 @@ namespace ShardingCore.Sharding.Abstractions */ public interface IShardingDbContext { + Type ShardingDbContextType { get; } /// /// ʵDbContext /// - Type ActualDbContextType { get;} + Type ActualDbContextType { get;} /// /// DbContext /// - /// + /// trueʾdbcontextڵǰshardingdbcontextڣfalseҪֶͷţtrue not care dbcontext life, false need call dispose() /// /// DbContext GetDbContext(bool track,string tail); @@ -33,5 +34,12 @@ namespace ShardingCore.Sharding.Abstractions DbContext CreateGenericDbContext(T entity) where T : class; + bool TryOpen(); + + } + + public interface IShardingTableDbContext : IShardingDbContext where T : DbContext, IShardingTableDbContext + { + } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs index 147e46fc..feb81066 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingTableDbContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using Microsoft.EntityFrameworkCore; namespace ShardingCore.Sharding.Abstractions { diff --git a/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs b/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs new file mode 100644 index 00000000..403ec46f --- /dev/null +++ b/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Sharding +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/8/19 20:57:52 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingDbContextOptionsBuilderConfig : IShardingDbContextOptionsBuilderConfig where TShardingDbContext : DbContext, IShardingDbContext + { + public ShardingDbContextOptionsBuilderConfig(Action shardingDbContextOptionsCreator) + { + ShardingDbContextOptionsCreator = shardingDbContextOptionsCreator; + } + public Action ShardingDbContextOptionsCreator { get; } + public Type ShardingDbContextType => typeof(TShardingDbContext); + + public DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder) + { + ShardingDbContextOptionsCreator(dbConnection, dbContextOptionsBuilder); + dbContextOptionsBuilder.UseInnerDbContextSharding(); + return dbContextOptionsBuilder; + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index e64d2285..13d8fb5b 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -1,27 +1,24 @@ -using System.Collections.Generic; -using System.Linq; using Microsoft.EntityFrameworkCore; using ShardingCore.Core.Internal.StreamMerge.ReWrite; using ShardingCore.Core.Internal.Visitors; using ShardingCore.Core.Internal.Visitors.GroupBys; using ShardingCore.Core.Internal.Visitors.Selects; -using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; -using ShardingCore.DbContexts; using ShardingCore.Sharding.Abstractions; +using System.Collections.Generic; +using System.Linq; namespace ShardingCore.Sharding { -/* -* @Author: xjm -* @Description: -* @Date: Monday, 25 January 2021 11:38:27 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Monday, 25 January 2021 11:38:27 + * @Email: 326308290@qq.com + */ public class StreamMergeContext { - private readonly IShardingParallelDbContextFactory _shardingParallelDbContextFactory; //private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IQueryable _source; private readonly IShardingDbContext _shardingDbContext; @@ -37,10 +34,8 @@ namespace ShardingCore.Sharding public SelectContext SelectContext { get;} public GroupByContext GroupByContext { get; } - public StreamMergeContext(IQueryable source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, - IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory) + public StreamMergeContext(IQueryable source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory) { - _shardingParallelDbContextFactory = shardingParallelDbContextFactory; //_shardingScopeFactory = shardingScopeFactory; _source = source; _shardingDbContext = shardingDbContext; @@ -69,13 +64,17 @@ namespace ShardingCore.Sharding // _reWriteSource = reWriteResult.ReWriteQueryable; //} + public bool TryOpen() + { + return _shardingDbContext.TryOpen(); + } public DbContext CreateDbContext(string tail) { return _shardingDbContext.GetDbContext(true,tail); } public IEnumerable GetRouteResults() { - return _tableRoutingRuleEngineFactory.Route(_source); + return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source); } //public ShardingScope CreateScope() diff --git a/src/ShardingCore/Sharding/StreamMergeContextFactory.cs b/src/ShardingCore/Sharding/StreamMergeContextFactory.cs index e6c97ad4..a41b1ad3 100644 --- a/src/ShardingCore/Sharding/StreamMergeContextFactory.cs +++ b/src/ShardingCore/Sharding/StreamMergeContextFactory.cs @@ -1,8 +1,6 @@ -using System.Linq; -using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; -using ShardingCore.DbContexts; using ShardingCore.Sharding.Abstractions; +using System.Linq; namespace ShardingCore.Sharding { @@ -14,21 +12,16 @@ namespace ShardingCore.Sharding */ public class StreamMergeContextFactory:IStreamMergeContextFactory { - private readonly IShardingParallelDbContextFactory _shardingParallelDbContextFactory; - private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IRoutingRuleEngineFactory _routingRuleEngineFactory; - public StreamMergeContextFactory(IShardingParallelDbContextFactory shardingParallelDbContextFactory, - IShardingScopeFactory shardingScopeFactory, + public StreamMergeContextFactory( IRoutingRuleEngineFactory routingRuleEngineFactory) { - _shardingParallelDbContextFactory = shardingParallelDbContextFactory; - _shardingScopeFactory = shardingScopeFactory; _routingRuleEngineFactory = routingRuleEngineFactory; } public StreamMergeContext Create(IQueryable queryable,IShardingDbContext shardingDbContext) { - return new StreamMergeContext(queryable,shardingDbContext, _routingRuleEngineFactory, _shardingParallelDbContextFactory, _shardingScopeFactory); + return new StreamMergeContext(queryable,shardingDbContext, _routingRuleEngineFactory); } } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs index d636b0f7..d259d342 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs @@ -46,6 +46,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions } _mergeContext = ShardingContainer.GetService().Create(_queryable, shardingDbContext); + _mergeContext.TryOpen(); } protected abstract IQueryable ProcessSecondExpression(IQueryable queryable, Expression secondExpression); diff --git a/src/ShardingCore/ShardingBootstrapper.cs b/src/ShardingCore/ShardingBootstrapper.cs index d95f4a1d..bc2dbf91 100644 --- a/src/ShardingCore/ShardingBootstrapper.cs +++ b/src/ShardingCore/ShardingBootstrapper.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -12,6 +13,7 @@ using ShardingCore.Core.VirtualTables; using ShardingCore.DbContexts; using ShardingCore.DbContexts.Abstractions; using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; using ShardingCore.TableCreator; namespace ShardingCore @@ -25,66 +27,58 @@ namespace ShardingCore public class ShardingBootstrapper : IShardingBootstrapper { private readonly IServiceProvider _serviceProvider; - private readonly IShardingCoreOptions _shardingCoreOptions; + private readonly IEnumerable _shardingConfigOptions; private readonly IVirtualTableManager _virtualTableManager; private readonly IShardingTableCreator _tableCreator; private readonly ILogger _logger; private readonly IShardingDbContextFactory _shardingDbContextFactory; - private readonly IDbContextCreateFilterManager _dbContextCreateFilterManager; - public ShardingBootstrapper(IServiceProvider serviceProvider, IShardingCoreOptions shardingCoreOptions, + public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable shardingConfigOptions, IVirtualTableManager virtualTableManager , IShardingTableCreator tableCreator, ILogger logger, - IShardingDbContextFactory shardingDbContextFactory,IDbContextCreateFilterManager dbContextCreateFilterManager) + IShardingDbContextFactory shardingDbContextFactory) { ShardingContainer.SetServices(serviceProvider); _serviceProvider = serviceProvider; - _shardingCoreOptions = shardingCoreOptions; + _shardingConfigOptions = shardingConfigOptions; _virtualTableManager = virtualTableManager; _tableCreator = tableCreator; _logger = logger; _shardingDbContextFactory = shardingDbContextFactory; - _dbContextCreateFilterManager = dbContextCreateFilterManager; } public void Start() { - foreach (var filter in _shardingCoreOptions.GetFilters()) - { - _dbContextCreateFilterManager.RegisterFilter((IDbContextCreateFilter)Activator.CreateInstance(filter)); - } - - var shardingConfig= _shardingCoreOptions.GetShardingConfig(); - using var scope = _serviceProvider.CreateScope(); - using var context =(DbContext)scope.ServiceProvider.GetService(shardingConfig.DbContextType); - #if EFCORE5 - shardingConfig.ConnectionString = context.Database.GetConnectionString(); -#endif - #if !EFCORE5 - shardingConfig.ConnectionString = context.Database.GetDbConnection().ConnectionString; -#endif - - EnsureCreated(context); - foreach (var entity in context.Model.GetEntityTypes()) + using (var scope = _serviceProvider.CreateScope()) { - if (entity.ClrType.IsShardingTable()) + foreach (var shardingConfigOption in _shardingConfigOptions) { - var routeType = shardingConfig.DbConfigOptions.GetVirtualRoute(entity.ClrType); - var virtualRoute = CreateVirtualRoute(routeType); - var virtualTable = CreateVirtualTable(entity.ClrType, virtualRoute); + using var context = + (DbContext) scope.ServiceProvider.GetService(shardingConfigOption.ShardingDbContextType); + EnsureCreated(context); + foreach (var entity in context.Model.GetEntityTypes()) + { + if (entity.ClrType.IsShardingTable()) + { + var routeType = shardingConfigOption.GetVirtualRouteType(entity.ClrType); + var virtualRoute = CreateVirtualRoute(routeType); + var virtualTable = CreateVirtualTable(entity.ClrType, virtualRoute); - //获取ShardingEntity的实际表名 + //获取ShardingEntity的实际表名 #if !EFCORE2 - var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName(); + var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName(); #endif #if EFCORE2 var tableName = context.Model.FindEntityType(virtualTable.EntityType).Relational().TableName; #endif - virtualTable.SetOriginalTableName(tableName); - _virtualTableManager.AddVirtualTable(virtualTable); - CreateDataTable(virtualTable); + virtualTable.SetOriginalTableName(tableName); + _virtualTableManager.AddVirtualTable(shardingConfigOption.ShardingDbContextType,virtualTable); + CreateDataTable(shardingConfigOption.ShardingDbContextType,virtualTable, shardingConfigOption); + } + } + } } } @@ -124,50 +118,51 @@ namespace ShardingCore return (IVirtualTable) o; } - private void EnsureCreated(DbContext context) + private void EnsureCreated(DbContext context) { - if (_shardingCoreOptions.EnsureCreatedWithOutShardingTable) + if (context is IShardingDbContext shardingDbContext) { - var modelCacheSyncObject = context.GetModelCacheSyncObject(); + var dbContext = shardingDbContext.GetDbContext(true,string.Empty); + var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); lock (modelCacheSyncObject) { - context.RemoveDbContextRelationModelThatIsShardingTable(); - context.Database.EnsureCreated(); - context.RemoveModelCache(); + dbContext.RemoveDbContextRelationModelThatIsShardingTable(); + dbContext.Database.EnsureCreated(); + dbContext.RemoveModelCache(); } } } - private bool NeedCreateTable(ShardingTableConfig config) + private bool NeedCreateTable(ShardingTableConfig config, IShardingConfigOption shardingConfigOption) { if (config.AutoCreateTable.HasValue) { return config.AutoCreateTable.Value; } - return _shardingCoreOptions.CreateShardingTableOnStart.GetValueOrDefault(); + return shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault(); } - private void CreateDataTable(IVirtualTable virtualTable) + private void CreateDataTable(Type shardingDbContextType,IVirtualTable virtualTable,IShardingConfigOption shardingConfigOption) { var shardingConfig = virtualTable.ShardingConfig; foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails()) { - if (NeedCreateTable(shardingConfig)) + if (NeedCreateTable(shardingConfig, shardingConfigOption)) { try { //添加物理表 virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); - _tableCreator.CreateTable(virtualTable.EntityType, tail); + _tableCreator.CreateTable(shardingDbContextType,virtualTable.EntityType, tail); } - catch (Exception) + catch (Exception e) { - if (!_shardingCoreOptions.IgnoreCreateTableError.GetValueOrDefault()) + if (!shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) { _logger.LogWarning( - $"table :{virtualTable.GetOriginalTableName()}{shardingConfig.TailPrefix}{tail} will created"); + $"table :{virtualTable.GetOriginalTableName()}{shardingConfig.TailPrefix}{tail} will created.",e); } } } diff --git a/src/ShardingCore/ShardingConfig.cs b/src/ShardingCore/ShardingConfig.cs deleted file mode 100644 index 5df29fdc..00000000 --- a/src/ShardingCore/ShardingConfig.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.Text; -using Microsoft.EntityFrameworkCore; -using ShardingCore.Sharding.Abstractions; - -namespace ShardingCore -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/16 15:18:37 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class ShardingConfig where T:DbContext,IShardingTableDbContext - { - - public Func, DbContextOptions> ShardingDbContextOptionsCreator { get; private set; } - public void UseShardingDbContextOptions(Func, DbContextOptions> shardingDbContextOptions) - { - ShardingDbContextOptionsCreator = shardingDbContextOptions ?? throw new ArgumentNullException(nameof(shardingDbContextOptions)); - } - } -} diff --git a/src/ShardingCore/ShardingConfigOption.cs b/src/ShardingCore/ShardingConfigOption.cs new file mode 100644 index 00000000..9ad2a9d4 --- /dev/null +++ b/src/ShardingCore/ShardingConfigOption.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; +using System.Text; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.EFCores; +using ShardingCore.Sharding; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/8/16 15:18:37 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingConfigOption : IShardingConfigOption + where TActualDbContext : DbContext, IShardingTableDbContext + where TShardingDbContext : DbContext, IShardingTableDbContext + { + private readonly Dictionary _virtualRoutes = new Dictionary(); + + public Action ShardingDbContextOptionsCreator { get; set; } + public void UseShardingDbContextOptions(Action shardingDbContextOptionsCreator) + { + ShardingDbContextOptionsCreator = shardingDbContextOptionsCreator ?? throw new ArgumentNullException(nameof(shardingDbContextOptionsCreator)); + } + + + public Type ShardingDbContextType => typeof(TShardingDbContext); + public Type ActualDbContextType => typeof(TActualDbContext); + + /// + /// 添加分表路由 + /// + /// + public void AddShardingTableRoute() where TRoute : IVirtualTableRoute + { + var routeType = typeof(TRoute); + //获取类型 + var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualTableRoute<>) + && it.GetGenericArguments().Any()); + if (genericVirtualRoute == null) + throw new ArgumentException("add sharding route type error not assignable from IVirtualTableRoute<>."); + + var shardingEntityType = genericVirtualRoute.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IVirtualTableRoute<>"); + if (!_virtualRoutes.ContainsKey(shardingEntityType)) + { + _virtualRoutes.Add(shardingEntityType, routeType); + } + } + + public Type GetVirtualRouteType(Type entityType) + { + if (!_virtualRoutes.ContainsKey(entityType)) + throw new ArgumentException($"{entityType} not found IVirtualTableRoute"); + return _virtualRoutes[entityType]; + } + + + /// + /// 如果数据库不存在就创建并且创建表除了分表的 + /// + public bool EnsureCreatedWithOutShardingTable { get; set; } + /// + /// 是否需要在启动时创建分表 + /// + public bool? CreateShardingTableOnStart { get; set; } + /// + /// 忽略建表时的错误 + /// + public bool? IgnoreCreateTableError { get; set; } + } + +} + diff --git a/src/ShardingCore/ShardingContainer.cs b/src/ShardingCore/ShardingContainer.cs index 3cbcfff9..5750aff8 100644 --- a/src/ShardingCore/ShardingContainer.cs +++ b/src/ShardingCore/ShardingContainer.cs @@ -29,5 +29,9 @@ namespace ShardingCore { return Services.GetService(); } + public static object GetService(Type serviceType) + { + return Services.GetService(serviceType); + } } } \ No newline at end of file diff --git a/src/ShardingCore/TableCreator/IShardingTableCreator.cs b/src/ShardingCore/TableCreator/IShardingTableCreator.cs index 6958778c..d7941bef 100644 --- a/src/ShardingCore/TableCreator/IShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/IShardingTableCreator.cs @@ -1,6 +1,8 @@ using System; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core; using ShardingCore.Exceptions; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.TableCreator { @@ -20,13 +22,14 @@ namespace ShardingCore.TableCreator /// /// /// - void CreateTable(string tail) where T : class, IShardingTable; + void CreateTable(string tail) where T : class, IShardingTable where TShardingDbContext:DbContext,IShardingDbContext; /// /// 创建表 /// + /// /// /// /// - void CreateTable(Type shardingEntityType,string tail); + void CreateTable(Type shardingDbContextType,Type shardingEntityType,string tail); } } \ No newline at end of file diff --git a/src/ShardingCore/TableCreator/ShardingTableCreator.cs b/src/ShardingCore/TableCreator/ShardingTableCreator.cs index 1a446b95..d4a0cd8a 100644 --- a/src/ShardingCore/TableCreator/ShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/ShardingTableCreator.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; @@ -7,10 +9,12 @@ using Microsoft.Extensions.Logging; using ShardingCore.Core; using ShardingCore.Core.VirtualTables; using ShardingCore.DbContexts; +using ShardingCore.DbContexts.Abstractions; using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.VirtualDbContexts; using ShardingCore.Exceptions; using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.TableCreator { @@ -26,50 +30,60 @@ namespace ShardingCore.TableCreator private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IVirtualTableManager _virtualTableManager; private readonly IServiceProvider _serviceProvider; - private readonly IShardingCoreOptions _shardingCoreOptions; + private readonly IEnumerable _shardingConfigOptions; public ShardingTableCreator(ILogger logger, IShardingDbContextFactory shardingDbContextFactory, - IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider,IShardingCoreOptions shardingCoreOptions) + IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable shardingConfigOptions) { _logger = logger; _shardingDbContextFactory = shardingDbContextFactory; _virtualTableManager = virtualTableManager; _serviceProvider = serviceProvider; - _shardingCoreOptions = shardingCoreOptions; + _shardingConfigOptions = shardingConfigOptions; } - public void CreateTable(string tail) where T : class, IShardingTable + public void CreateTable(string tail) where TShardingDbContext : DbContext, IShardingDbContext where T : class, IShardingTable { - CreateTable(typeof(T), tail); + CreateTable(typeof(TShardingDbContext),typeof(T), tail); } + /// /// /// + /// /// /// /// - public void CreateTable(Type shardingEntityType, string tail) + public void CreateTable(Type shardingDbContextType,Type shardingEntityType, string tail) { + if (!shardingDbContextType.IsShardingDbContext()) + throw new ShardingCoreException( + $"{shardingDbContextType.FullName} must impl {nameof(IShardingDbContext)}"); + + var shardingConfigOptions = _shardingConfigOptions.FirstOrDefault(o => o.ShardingDbContextType == shardingDbContextType); + if (shardingConfigOptions == null) + throw new ShardingCoreException( + "not found sharding config options db context is {shardingDbContextType.FullName}"); using (var serviceScope = _serviceProvider.CreateScope()) { - var dbContextOptionsProvider = serviceScope.ServiceProvider.GetService(); - var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType); + var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntityType); + var dbContext = (DbContext)serviceScope.ServiceProvider.GetService(shardingDbContextType); + var shardingDbContext = (IShardingDbContext)dbContext; + var context = shardingDbContext.GetDbContext(true,tail); - using (var dbContext = _shardingDbContextFactory.Create(new ShardingDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(null), tail))) - { - var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); + var modelCacheSyncObject = context.GetModelCacheSyncObject(); lock (modelCacheSyncObject) { - dbContext.RemoveDbContextRelationModelSaveOnlyThatIsNamedType(shardingEntityType); - var databaseCreator = dbContext.Database.GetService() as RelationalDatabaseCreator; + context.RemoveDbContextRelationModelSaveOnlyThatIsNamedType(shardingEntityType); + var databaseCreator = context.Database.GetService() as RelationalDatabaseCreator; try { databaseCreator.CreateTables(); } catch (Exception ex) { - if (!_shardingCoreOptions.IgnoreCreateTableError.GetValueOrDefault()) + if (!shardingConfigOptions.IgnoreCreateTableError.GetValueOrDefault()) { _logger.LogWarning( $"create table error maybe table:[{virtualTable.GetOriginalTableName()}{virtualTable.ShardingConfig.TailPrefix}{tail}]"); @@ -78,11 +92,10 @@ namespace ShardingCore.TableCreator } finally { - dbContext.RemoveModelCache(); + context.RemoveModelCache(); } } - } } } } diff --git a/test/ShardingCore.Test50/ShardingCore.Test50.csproj b/test/ShardingCore.Test50/ShardingCore.Test50.csproj index b4de1a90..102b40c8 100644 --- a/test/ShardingCore.Test50/ShardingCore.Test50.csproj +++ b/test/ShardingCore.Test50/ShardingCore.Test50.csproj @@ -7,6 +7,7 @@ + @@ -22,5 +23,8 @@ PreserveNewest + + + diff --git a/test/ShardingCore.Test50/ShardingDefaultDbContext.cs b/test/ShardingCore.Test50/ShardingDefaultDbContext.cs index 14fe4cd2..79cd7c3a 100644 --- a/test/ShardingCore.Test50/ShardingDefaultDbContext.cs +++ b/test/ShardingCore.Test50/ShardingDefaultDbContext.cs @@ -28,5 +28,7 @@ namespace ShardingCore.Test50 modelBuilder.ApplyConfiguration(new SysUserModMap()); modelBuilder.ApplyConfiguration(new SysUserSalaryMap()); } + + public override Type ShardingDbContextType => this.GetType(); } } diff --git a/test/ShardingCore.Test50/Startup.cs b/test/ShardingCore.Test50/Startup.cs index 3bf6e641..b2760a46 100644 --- a/test/ShardingCore.Test50/Startup.cs +++ b/test/ShardingCore.Test50/Startup.cs @@ -1,17 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using ShardingCore.DbContexts.VirtualDbContexts; -using ShardingCore.Extensions; -using ShardingCore.Sharding; -using ShardingCore.SqlServer; using ShardingCore.Test50.Domain.Entities; using ShardingCore.Test50.Shardings; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; #if EFCORE5SQLSERVER using ShardingCore.SqlServer; @@ -22,14 +19,18 @@ using ShardingCore.MySql; namespace ShardingCore.Test50 { -/* -* @Author: xjm -* @Description: -* @Date: Friday, 15 January 2021 15:37:46 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Friday, 15 January 2021 15:37:46 + * @Email: 326308290@qq.com + */ public class Startup { + public static readonly ILoggerFactory efLogger = LoggerFactory.Create(builder => + { + builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole(); + }); // // 自定义 host 构建 public void ConfigureHost(IHostBuilder hostBuilder) { @@ -47,33 +48,18 @@ namespace ShardingCore.Test50 public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) { - services.AddShardingSqlServer(o => - { - o.EnsureCreatedWithOutShardingTable = false; - o.CreateShardingTableOnStart = false; - o.UseShardingDbContext( dbConfig => - { - dbConfig.AddShardingTableRoute(); - dbConfig.AddShardingTableRoute(); - }); - //o.AddDataSourceVirtualRoute<>(); - - }); - //services.AddShardingSqlServer(o => - //{ - // o.ConnectionString = hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]; - // o.AddSharding(); - // o.AddSharding(); - // o.UseShardingCoreConfig((provider, config) => - // { - // config.EnsureCreated = true; - // config.CreateShardingTableOnStart = true; - // }); - //}); - services.AddDbContext(o=> + services.AddDbContext(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])); - services.AddDbContext(o=> - o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]).UseSharding()); + services.AddShardingDbContext(o => + o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]), op => + { + + op.EnsureCreatedWithOutShardingTable = true; + op.CreateShardingTableOnStart = true; + op.UseShardingDbContextOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)); + op.AddShardingTableRoute(); + op.AddShardingTableRoute(); + }); } // 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法 @@ -90,50 +76,50 @@ namespace ShardingCore.Test50 /// /// /// - private async Task InitData(IServiceProvider serviceProvider) + private async Task InitData(IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { var virtualDbContext = scope.ServiceProvider.GetService(); - var ids = Enumerable.Range(1, 1000); - var userMods = new List(); - var userSalaries = new List(); - var beginTime = new DateTime(2020, 1, 1); - var endTime = new DateTime(2021, 12, 1); - foreach (var id in ids) + var ids = Enumerable.Range(1, 1000); + var userMods = new List(); + var userSalaries = new List(); + var beginTime = new DateTime(2020, 1, 1); + var endTime = new DateTime(2021, 12, 1); + foreach (var id in ids) + { + userMods.Add(new SysUserMod() { - userMods.Add(new SysUserMod() + Id = id.ToString(), + Age = id, + Name = $"name_{id}", + AgeGroup = Math.Abs(id % 10) + }); + var tempTime = beginTime; + var i = 0; + while (tempTime <= endTime) + { + var dateOfMonth = $@"{tempTime:yyyyMM}"; + userSalaries.Add(new SysUserSalary() { - Id = id.ToString(), - Age = id, - Name = $"name_{id}", - AgeGroup=Math.Abs(id%10) + Id = $@"{id}{dateOfMonth}", + UserId = id.ToString(), + DateOfMonth = int.Parse(dateOfMonth), + Salary = 700000 + id * 100 * i, + SalaryLong = 700000 + id * 100 * i, + SalaryDecimal = (700000 + id * 100 * i) / 100m, + SalaryDouble = (700000 + id * 100 * i) / 100d, + SalaryFloat = (700000 + id * 100 * i) / 100f }); - var tempTime = beginTime; - var i = 0; - while (tempTime<=endTime) - { - var dateOfMonth = $@"{tempTime:yyyyMM}"; - userSalaries.Add(new SysUserSalary() - { - Id = $@"{id}{dateOfMonth}", - UserId = id.ToString(), - DateOfMonth = int.Parse(dateOfMonth), - Salary = 700000+id*100*i, - SalaryLong = 700000+id*100*i, - SalaryDecimal = (700000+id*100*i)/100m, - SalaryDouble = (700000+id*100*i)/100d, - SalaryFloat = (700000+id*100*i)/100f - }); - tempTime=tempTime.AddMonths(1); - i++; - } + tempTime = tempTime.AddMonths(1); + i++; } + } - await virtualDbContext.AddRangeAsync(userMods); - await virtualDbContext.AddRangeAsync(userSalaries); - - await virtualDbContext.SaveChangesAsync(); + await virtualDbContext.AddRangeAsync(userMods); + await virtualDbContext.AddRangeAsync(userSalaries); + + await virtualDbContext.SaveChangesAsync(); } } }