From 18cdbfea0e0db79945a13cee259e236e596222ed Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Mon, 20 Sep 2021 22:26:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E5=88=86=E8=A1=A8?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81=E9=99=A4=E4=BA=86=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=A4=84=E7=90=86=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DbContexts/MyShardingDbContext.cs | 1 - samples/Sample.BulkConsole/Program.cs | 17 +- .../DbContexts/DefaultShardingDbContext.cs | 1 - .../DbContexts/DefaultTableDbContext.cs | 2 +- .../Controllers/ValuesController.cs | 74 ++-- .../DbContexts/DefaultShardingDbContext.cs | 3 +- samples/Sample.SqlServer/Startup.cs | 53 ++- .../VirtualDataSources/IVirtualDataSource.cs | 9 +- .../IVirtualDataSourceManager.cs | 60 ++-- .../VirtualDataSources/VirtualDataSource.cs | 31 +- .../VirtualDataSourceManager.cs | 128 +++---- ...TableManager.cs => VirtualTableManager.cs} | 4 +- .../IVirtualDataSourceRoute.cs | 1 + .../DataSourceRouteRuleEngine.cs | 23 +- .../DataSourceRouteRuleEngineFactory.cs | 18 +- .../IDataSourceRouteRuleEngine.cs | 9 +- .../IDataSourceRouteRuleEngineFactory.cs | 10 +- .../ITableRouteRuleEngine.cs | 7 +- .../ITableRouteRuleEngineFactory.cs | 7 +- .../TableRouteRuleContext.cs | 4 +- .../RoutingRuleEngine/TableRouteRuleEngine.cs | 72 +--- .../TableRouteRuleEngineFactory.cs | 18 +- src/ShardingCore/DIExtension.cs | 227 +++++++----- .../DIExtensions/ShardingCoreConfigBuilder.cs | 58 +++ .../ShardingCoreConfigEndBuilder.cs | 112 ++++++ .../ShardingDataBaseOrTableBuilder.cs | 55 +++ .../ShardingDatabaseOrTableOptions.cs | 55 +++ .../ShardingDefaultDataSourceBuilder.cs | 35 ++ .../DIExtensions/ShardingQueryBuilder.cs | 33 ++ .../ShardingReadWriteSeparationBuilder.cs | 39 ++ .../DIExtensions/ShardingTableBuilder.cs | 40 +++ .../ShardingTransactionBuilder.cs | 33 ++ .../DbContexts/IShardingDbContextFactory.cs | 5 +- .../DbContexts/ShardingDbContextFactory.cs | 28 +- .../DefaultShardingDbContextCreatorConfig.cs | 2 +- .../ShardingRelationalTransaction.cs | 114 +++--- .../EFCores/ShardingModelCustomizer.cs | 4 +- .../EFCores/ShardingRelationalConnection.cs | 334 +++++++++--------- .../ShardingRelationalTransactionFactory.cs | 64 ++-- .../Extensions/ShardingExtension.cs | 80 ++++- .../Extensions/StreamMergeContextExtension.cs | 11 +- .../Extensions/VirtualDataBaseExtension.cs | 15 +- ...nsion.cs => VirtualDataSourceExtension.cs} | 9 +- .../Helpers/ShardingCoreHelper.cs | 6 +- src/ShardingCore/IShardingConfigOption.cs | 18 +- .../IShardingDbContextCreatorConfig.cs | 1 - .../Sharding/AbstractShardingDbContext.cs | 4 +- .../Abstractions/IConnectionStringManager.cs | 5 +- .../Abstractions/IShardingDbContext.cs | 4 - .../IStreamMergeContextFactory.cs | 19 +- .../Sharding/ActualConnectionStringManager.cs | 6 +- .../DefaultConnectionStringManager.cs | 6 +- .../RandomShardingConnectionStringResolver.cs | 29 +- .../ReadWriteRandomConnector.cs | 35 ++ .../ShardingReadWriteManager.cs | 12 +- .../Sharding/ShardingDbContextExecutor.cs | 32 +- .../ShardingDbContextOptionsBuilderConfig.cs | 2 +- .../DefaultShardingQueryExecutor.cs | 14 +- .../EnumeratorShardingQueryExecutor.cs | 6 +- .../Sharding/StreamMergeContext.cs | 17 +- .../Sharding/StreamMergeContextFactory.cs | 15 +- .../AbstractInMemoryAsyncMergeEngine.cs | 2 +- .../CountAsyncInMemoryMergeEngine.cs | 2 +- .../Base/SequencePaginationList.cs | 2 +- ...hardingEnumeratorAsyncStreamMergeEngine.cs | 7 +- ...hardingEnumeratorAsyncStreamMergeEngine.cs | 7 +- ...leQueryEnumeratorAsyncStreamMergeEngine.cs | 6 +- .../StreamMergeEngines/RouteQueryResult.cs | 6 +- src/ShardingCore/ShardingBootstrapper.cs | 136 +------ src/ShardingCore/ShardingConfigOption.cs | 125 +++++-- src/ShardingCore/ShardingContainer.cs | 17 +- src/ShardingCore/ShardingCore.csproj | 2 +- .../ShardingDbContextBootstrapper.cs | 218 ++++++++++++ .../TableCreator/IShardingTableCreator.cs | 25 +- .../TableCreator/ShardingTableCreator.cs | 41 +-- .../ShardingDefaultDbContext.cs | 1 - test/ShardingCore.Test50/Startup.cs | 15 +- 77 files changed, 1735 insertions(+), 1013 deletions(-) rename src/ShardingCore/Core/VirtualDatabase/VirtualTables/{DefaultVirtualTableManager.cs => VirtualTableManager.cs} (98%) create mode 100644 src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingDatabaseOrTableOptions.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingDefaultDataSourceBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingQueryBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingTableBuilder.cs create mode 100644 src/ShardingCore/DIExtensions/ShardingTransactionBuilder.cs rename src/ShardingCore/Extensions/{VirtualDataSourceManagerExtension.cs => VirtualDataSourceExtension.cs} (66%) create mode 100644 src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteRandomConnector.cs create mode 100644 src/ShardingCore/ShardingDbContextBootstrapper.cs diff --git a/samples/Sample.BulkConsole/DbContexts/MyShardingDbContext.cs b/samples/Sample.BulkConsole/DbContexts/MyShardingDbContext.cs index 8862bcda..b68e6f44 100644 --- a/samples/Sample.BulkConsole/DbContexts/MyShardingDbContext.cs +++ b/samples/Sample.BulkConsole/DbContexts/MyShardingDbContext.cs @@ -29,6 +29,5 @@ namespace Sample.BulkConsole.DbContexts entity.ToTable(nameof(Order)); }); } - public override Type ShardingDbContextType => this.GetType(); } } diff --git a/samples/Sample.BulkConsole/Program.cs b/samples/Sample.BulkConsole/Program.cs index f541218d..20f0e353 100644 --- a/samples/Sample.BulkConsole/Program.cs +++ b/samples/Sample.BulkConsole/Program.cs @@ -24,17 +24,14 @@ namespace Sample.BulkConsole var services = new ServiceCollection(); services.AddLogging(); services.AddShardingDbContext( - o => o.UseSqlServer("Data Source=localhost;Initial Catalog=MyOrderSharding;Integrated Security=True;") - , op => - { - op.EnsureCreatedWithOutShardingTable = true; - op.CreateShardingTableOnStart = true; - op.UseShardingOptionsBuilder( - (connection, builder) => builder.UseSqlServer(connection),//使用dbconnection创建dbcontext支持事务 - (conStr, builder) => builder.UseSqlServer(conStr).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - ); + o => o.UseSqlServer("Data Source=localhost;Initial Catalog=MyOrderSharding;Integrated Security=True;")) + .Begin(true) + .AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)) + .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection)) + .AddDefaultDataSource("ds0", "Data Source=localhost;Initial Catalog=MyOrderSharding;Integrated Security=True;") + .AddShardingTable(op=> { op.AddShardingTableRoute(); - }); + }).End(); var serviceProvider = services.BuildServiceProvider(); serviceProvider.GetService().Start(); using (var serviceScope = serviceProvider.CreateScope()) diff --git a/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs b/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs index 1b658806..c5023abc 100644 --- a/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs @@ -19,6 +19,5 @@ namespace Sample.MySql.DbContexts modelBuilder.ApplyConfiguration(new SysUserLogByMonthMap()); } - public override Type ShardingDbContextType => this.GetType(); } } diff --git a/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs b/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs index 20ac9196..1b25a8d8 100644 --- a/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs +++ b/samples/Sample.MySql/DbContexts/DefaultTableDbContext.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; using Sample.MySql.Domain.Maps; -using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Sharding.Abstractions; namespace Sample.MySql.DbContexts diff --git a/samples/Sample.SqlServer/Controllers/ValuesController.cs b/samples/Sample.SqlServer/Controllers/ValuesController.cs index e5136034..d67083c7 100644 --- a/samples/Sample.SqlServer/Controllers/ValuesController.cs +++ b/samples/Sample.SqlServer/Controllers/ValuesController.cs @@ -116,47 +116,47 @@ namespace Sample.SqlServer.Controllers shardingPageResultAsync }); } - [HttpGet] - public IActionResult Get3() - { + //[HttpGet] + //public IActionResult Get3() + //{ - var dbContext2s = _defaultTableDbContext.BulkShardingExpression(o => o.Age > 100); - using (var tran = _defaultTableDbContext.Database.BeginTransaction()) - { - dbContext2s.ForEach(dbContext => - { - dbContext.Set().Where(o => o.Age > 100).Update(o => new SysUserMod() - { - AgeGroup = 1000 - }); - }); - _defaultTableDbContext.SaveChanges(); - tran.Commit(); - } - var list = new List(); - var dbContexts = _defaultTableDbContext.BulkShardingEnumerable(list); + // var dbContext2s = _defaultTableDbContext.BulkShardingExpression(o => o.Age > 100); + // using (var tran = _defaultTableDbContext.Database.BeginTransaction()) + // { + // dbContext2s.ForEach(dbContext => + // { + // dbContext.Set().Where(o => o.Age > 100).Update(o => new SysUserMod() + // { + // AgeGroup = 1000 + // }); + // }); + // _defaultTableDbContext.SaveChanges(); + // tran.Commit(); + // } + // var list = new List(); + // var dbContexts = _defaultTableDbContext.BulkShardingEnumerable(list); - using (var tran = _defaultTableDbContext.Database.BeginTransaction()) - { - dbContexts.ForEach(kv => - { - kv.Key.BulkInsert(kv.Value); - }); - dbContexts.ForEach(kv => - { - kv.Key.BulkDelete(kv.Value); - }); - dbContexts.ForEach(kv => - { - kv.Key.BulkUpdate(kv.Value); - }); - _defaultTableDbContext.SaveChanges(); - tran.Commit(); - } + // using (var tran = _defaultTableDbContext.Database.BeginTransaction()) + // { + // dbContexts.ForEach(kv => + // { + // kv.Key.BulkInsert(kv.Value); + // }); + // dbContexts.ForEach(kv => + // { + // kv.Key.BulkDelete(kv.Value); + // }); + // dbContexts.ForEach(kv => + // { + // kv.Key.BulkUpdate(kv.Value); + // }); + // _defaultTableDbContext.SaveChanges(); + // tran.Commit(); + // } - return Ok(); - } + // return Ok(); + //} } } diff --git a/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs b/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs index 6d71a66f..a43857e5 100644 --- a/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs @@ -22,7 +22,6 @@ namespace Sample.SqlServer.DbContexts modelBuilder.ApplyConfiguration(new SysTestMap()); modelBuilder.ApplyConfiguration(new SysUserSalaryMap()); } - - public override Type ShardingDbContextType => this.GetType(); + } } diff --git a/samples/Sample.SqlServer/Startup.cs b/samples/Sample.SqlServer/Startup.cs index c3039a8e..dd8c31a6 100644 --- a/samples/Sample.SqlServer/Startup.cs +++ b/samples/Sample.SqlServer/Startup.cs @@ -29,26 +29,41 @@ namespace Sample.SqlServer services.AddControllers(); //services.AddDbContext(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx3;Integrated Security=True")); - services.AddShardingDbContext( - o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;") - , op => - { - op.EnsureCreatedWithOutShardingTable = true; - op.CreateShardingTableOnStart = true; - op.UseShardingOptionsBuilder( - (connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection创建dbcontext支持事务 - (conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - //.ReplaceService()//支持sqlserver2008r2 - );//使用链接字符串创建dbcontext - //op.UseReadWriteConfiguration(sp => new List() - //{ - // "Data Source=localhost;Initial Catalog=ShardingCoreDB1;Integrated Security=True;", - // "Data Source=localhost;Initial Catalog=ShardingCoreDB2;Integrated Security=True;" - //}, ReadStrategyEnum.Random); - op.AddShardingTableRoute(); - op.AddShardingTableRoute(); - }); + o => o.UseSqlServer( + "Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;") + ).Begin(true) + .AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger) + .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)) + .AddShardingTransaction((connection, builder) => + builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) + .AddDefaultDataSource("ds0", + "Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;") + .AddShardingTable(o => + { + o.AddShardingTableRoute(); + o.AddShardingTableRoute(); + }).End(); + + //services.AddShardingDbContext( + // o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;") + // , op => + // { + // op.EnsureCreatedWithOutShardingTable = true; + // op.CreateShardingTableOnStart = true; + // op.UseShardingOptionsBuilder( + // (connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection创建dbcontext支持事务 + // (conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) + // //.ReplaceService()//支持sqlserver2008r2 + // );//使用链接字符串创建dbcontext + // //op.UseReadWriteConfiguration(sp => new List() + // //{ + // // "Data Source=localhost;Initial Catalog=ShardingCoreDB1;Integrated Security=True;", + // // "Data Source=localhost;Initial Catalog=ShardingCoreDB2;Integrated Security=True;" + // //}, ReadStrategyEnum.Random); + // op.AddShardingTableRoute(); + // op.AddShardingTableRoute(); + // }); } diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs index 9cf8a454..869a384c 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; using ShardingCore.Core.VirtualTables; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources { @@ -16,16 +18,16 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources /// /// 虚拟数据源 连接所有的实际数据源 /// - public interface IVirtualDataSource + public interface IVirtualDataSource + where TShardingDbContext : DbContext, IShardingDbContext { - Type ShardingDbContextType{get; } string DefaultDataSourceName { get; } /// /// 路由到具体的物理数据源 /// /// data source names - List RouteTo(Type entityType,ShardingDataSourceRouteConfig routeRouteConfig); + List RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig); /// /// 获取当前数据源的路由 @@ -49,5 +51,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources /// 是否添加成功 bool AddPhysicDataSource(IPhysicDataSource physicDataSource); + bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs index c4a3bedb..4680baea 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; -using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Sharding.Abstractions; +//using System; +//using System.Collections.Generic; +//using Microsoft.EntityFrameworkCore; +//using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; +//using ShardingCore.Core.VirtualRoutes; +//using ShardingCore.Sharding.Abstractions; -namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 06 February 2021 14:24:01 - * @Email: 326308290@qq.com - */ - public interface IVirtualDataSourceManager - { - /// - /// 添加链接 - /// - /// - bool AddPhysicDataSource(IPhysicDataSource physicDataSource); - IVirtualDataSource GetVirtualDataSource(); - IPhysicDataSource GetDefaultDataSource(); - string GetDefaultDataSourceName(); - IPhysicDataSource GetPhysicDataSource(string dataSourceName); - } - public interface IVirtualDataSourceManager : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext - { +//namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: Saturday, 06 February 2021 14:24:01 +// * @Email: 326308290@qq.com +// */ +// public interface IVirtualDataSourceManager +// { +// /// +// /// 添加链接 +// /// +// /// +// bool AddPhysicDataSource(IPhysicDataSource physicDataSource); +// IVirtualDataSource GetVirtualDataSource(); +// IPhysicDataSource GetDefaultDataSource(); +// string GetDefaultDataSourceName(); +// IPhysicDataSource GetPhysicDataSource(string dataSourceName); +// } +// public interface IVirtualDataSourceManager : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext +// { - } -} \ No newline at end of file +// } +//} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs index 54187dda..939eb902 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs @@ -3,11 +3,13 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; using ShardingCore.Core.VirtualTables; using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; using ShardingCore.Utils; namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources @@ -18,21 +20,15 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources * @Date: Friday, 05 February 2021 15:21:04 * @Email: 326308290@qq.com */ - public class VirtualDataSource : IVirtualDataSource + public class VirtualDataSource : IVirtualDataSource where TShardingDbContext : DbContext, IShardingDbContext { private readonly ConcurrentDictionary _dataSourceVirtualRoutes = new ConcurrentDictionary(); private readonly ConcurrentDictionary _physicDataSources = new ConcurrentDictionary(); - public string DefaultDataSourceName { get; } - public Type ShardingDbContextType { get; } + public string DefaultDataSourceName { get; private set; } - public VirtualDataSource(Type shardingDbContextType,string defaultDataSourceName) - { - ShardingDbContextType = shardingDbContextType; - DefaultDataSourceName = defaultDataSourceName??throw new ArgumentNullException(nameof(defaultDataSourceName)); - } @@ -93,9 +89,24 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources public bool AddPhysicDataSource(IPhysicDataSource physicDataSource) { - if (physicDataSource.IsDefault && physicDataSource.DataSourceName != DefaultDataSourceName) - throw new InvalidOperationException($"default data source name:[{DefaultDataSourceName}],add physic default data source name:[{physicDataSource.DataSourceName}]"); + if (physicDataSource.IsDefault) + { + if (!string.IsNullOrWhiteSpace(DefaultDataSourceName)) + { + throw new InvalidOperationException($"default data source name:[{DefaultDataSourceName}],add physic default data source name:[{physicDataSource.DataSourceName}]"); + } + + DefaultDataSourceName = physicDataSource.DataSourceName; + } return _physicDataSources.TryAdd(physicDataSource.DataSourceName, physicDataSource); } + + public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute) + { + if (!virtualDataSourceRoute.EntityType.IsShardingDataSource()) + throw new InvalidOperationException($"{virtualDataSourceRoute.EntityType.FullName} should impl {nameof(IShardingDataSource)}"); + + return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.EntityType, virtualDataSourceRoute); + } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs index 2b3de7eb..43163012 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs @@ -1,72 +1,74 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; -using ShardingCore.Core.VirtualRoutes; +//using System; +//using System.Collections.Concurrent; +//using System.Collections.Generic; +//using System.Linq; +//using Microsoft.EntityFrameworkCore; +//using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; +//using ShardingCore.Core.VirtualRoutes; +//using ShardingCore.Sharding.Abstractions; -namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 06 February 2021 15:24:08 - * @Email: 326308290@qq.com - */ - public class VirtualDataSourceManager : IVirtualDataSourceManager - { - private readonly IServiceProvider _serviceProvider; - /// - /// {sharding db context type :{entity type:virtual data source}} - /// - private readonly ConcurrentDictionary _virtualDataSources = new ConcurrentDictionary(); +//namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: Saturday, 06 February 2021 15:24:08 +// * @Email: 326308290@qq.com +// */ +// public class VirtualDataSourceManager : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext +// { +// private readonly IServiceProvider _serviceProvider; +// /// +// /// {sharding db context type :{entity type:virtual data source}} +// /// +// private readonly ConcurrentDictionary _virtualDataSources = new ConcurrentDictionary(); - public VirtualDataSourceManager(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - //var shardingEntities = AssemblyHelper.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes()) - // .Where(type => !String.IsNullOrEmpty(type.Namespace)) - // .Where(type => !type.IsAbstract&&type.GetInterfaces() - // .Any(it => it.IsInterface &&typeof(IShardingDataSource)==it) - // ); - //foreach (var shardingEntity in shardingEntities) - //{ - // Type genericType = typeof(IVirtualDataSource<>); - // Type interfaceType = genericType.MakeGenericType(shardingEntity); - // var virtualDataSource = (IVirtualDataSource)serviceProvider.GetService(interfaceType); - // _virtualDataSources.TryAdd(virtualDataSource.EntityType, virtualDataSource); - //} - } +// public VirtualDataSourceManager(IServiceProvider serviceProvider) +// { +// _serviceProvider = serviceProvider; +// //var shardingEntities = AssemblyHelper.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes()) +// // .Where(type => !String.IsNullOrEmpty(type.Namespace)) +// // .Where(type => !type.IsAbstract&&type.GetInterfaces() +// // .Any(it => it.IsInterface &&typeof(IShardingDataSource)==it) +// // ); +// //foreach (var shardingEntity in shardingEntities) +// //{ +// // Type genericType = typeof(IVirtualDataSource<>); +// // Type interfaceType = genericType.MakeGenericType(shardingEntity); +// // var virtualDataSource = (IVirtualDataSource)serviceProvider.GetService(interfaceType); +// // _virtualDataSources.TryAdd(virtualDataSource.EntityType, virtualDataSource); +// //} +// } - public bool AddPhysicDataSource(Type shardingDbContextType, IPhysicDataSource physicDataSource) - { - throw new NotImplementedException(); - } +// public bool AddPhysicDataSource(IPhysicDataSource physicDataSource) +// { +// throw new NotImplementedException(); +// } - public IVirtualDataSource GetVirtualDataSource(Type shardingDbContextType) - { - if (!_virtualDataSources.TryGetValue(shardingDbContextType, out var virtualDataSource)) - throw new InvalidOperationException($"not found virtual data source sharding db context type:[{shardingDbContextType.FullName}]"); - return virtualDataSource; - } +// public IVirtualDataSource GetVirtualDataSource() +// { +// if (!_virtualDataSources.TryGetValue(shardingDbContextType, out var virtualDataSource)) +// throw new InvalidOperationException($"not found virtual data source sharding db context type:[{shardingDbContextType.FullName}]"); +// return virtualDataSource; +// } - public IPhysicDataSource GetDefaultDataSource(Type shardingDbContextType) - { - var virtualDataSource = GetVirtualDataSource(shardingDbContextType); - return virtualDataSource.GetDefaultDataSource(); - } +// public IPhysicDataSource GetDefaultDataSource() +// { +// var virtualDataSource = GetVirtualDataSource(shardingDbContextType); +// return virtualDataSource.GetDefaultDataSource(); +// } - public string GetDefaultDataSourceName(Type shardingDbContextType) - { - var virtualDataSource = GetVirtualDataSource(shardingDbContextType); - return virtualDataSource.DefaultDataSourceName; - } +// public string GetDefaultDataSourceName() +// { +// var virtualDataSource = GetVirtualDataSource(shardingDbContextType); +// return virtualDataSource.DefaultDataSourceName; +// } - public IPhysicDataSource GetPhysicDataSource(Type shardingDbContextType, string dataSourceName) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file +// public IPhysicDataSource GetPhysicDataSource(string dataSourceName) +// { +// throw new NotImplementedException(); +// } +// } +//} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualTables/DefaultVirtualTableManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualTables/VirtualTableManager.cs similarity index 98% rename from src/ShardingCore/Core/VirtualDatabase/VirtualTables/DefaultVirtualTableManager.cs rename to src/ShardingCore/Core/VirtualDatabase/VirtualTables/VirtualTableManager.cs index b240a11a..a4c2bf20 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualTables/DefaultVirtualTableManager.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualTables/VirtualTableManager.cs @@ -20,7 +20,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualTables /// /// 同一个数据库下的虚拟表管理者 /// - public class DefaultVirtualTableManager : IVirtualTableManager where TShardingDbContext : DbContext, IShardingDbContext + public class VirtualTableManager : IVirtualTableManager where TShardingDbContext : DbContext, IShardingDbContext { /// @@ -98,7 +98,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualTables ///// //private readonly ConcurrentDictionary> _shardingVirtualTables = new ConcurrentDictionary>(); //private readonly ConcurrentDictionary> _shardingVirtualTaleVirtualTables = new ConcurrentDictionary>(); - //public DefaultVirtualTableManager() + //public VirtualTableManager() //{ //} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs index f6d8dad1..6586a08d 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs @@ -14,6 +14,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes public interface IVirtualDataSourceRoute { Type EntityType { get; } + string ShardingKeyToDataSourceName(object shardingKeyValue); /// /// 根据查询条件路由返回物理数据源 diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs index 03c7cf09..06d58a4d 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs @@ -18,29 +18,21 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class DataSourceRouteRuleEngine : IDataSourceRouteRuleEngine + public class DataSourceRouteRuleEngine : IDataSourceRouteRuleEngine where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IVirtualDataSourceManager _virtualDataSourceManager; + private readonly IVirtualDataSource _virtualDataSource; - public DataSourceRouteRuleEngine(IVirtualDataSourceManager virtualDataSourceManager) + public DataSourceRouteRuleEngine(IVirtualDataSource virtualDataSource) { - _virtualDataSourceManager = virtualDataSourceManager; + _virtualDataSource = virtualDataSource; } - - public DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext) where TShardingDbContext : DbContext, IShardingDbContext + public DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext) { - return this.Route(typeof(TShardingDbContext), routeRuleContext); - } - - public DataSourceRouteResult Route(Type shardingDbContextType, DataSourceRouteRuleContext routeRuleContext) - { - if (!shardingDbContextType.IsShardingDataSource()) - throw new InvalidOperationException($"{shardingDbContextType} must impl {nameof(IShardingDbContext)}"); var dataSourceMaps = new Dictionary>(); var notShardingDataSourceEntityType = routeRuleContext.QueryEntities.FirstOrDefault(o => !o.IsShardingDataSource()); //存在不分表的 if (notShardingDataSourceEntityType != null) - dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet() { _virtualDataSourceManager.GetDefaultDataSourceName(shardingDbContextType) }); + dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet() { _virtualDataSource.DefaultDataSourceName }); var queryEntities = routeRuleContext.QueryEntities.Where(o => o.IsShardingDataSource()).ToList(); @@ -48,8 +40,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine throw new ShardingCoreNotSupportedException($"{routeRuleContext.Queryable.ShardingPrint()}"); foreach (var queryEntity in queryEntities) { - var virtualDataSource = _virtualDataSourceManager.GetVirtualDataSource(shardingDbContextType); - var dataSourceConfigs = virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable)); + var dataSourceConfigs = _virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable)); if (!dataSourceMaps.ContainsKey(queryEntity)) { dataSourceMaps.Add(queryEntity, dataSourceConfigs.ToHashSet()); diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs index 6b0d7af1..df6f1d26 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine { @@ -15,14 +17,14 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine /// /// 分库路由引擎工程 /// - public class DataSourceRouteRuleEngineFactory: IDataSourceRouteRuleEngineFactory + public class DataSourceRouteRuleEngineFactory: IDataSourceRouteRuleEngineFactory where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IDataSourceRouteRuleEngine _dataSourceRouteRuleEngine; + private readonly IDataSourceRouteRuleEngine _dataSourceRouteRuleEngine; /// /// ctor /// /// - public DataSourceRouteRuleEngineFactory(IDataSourceRouteRuleEngine dataSourceRouteRuleEngine) + public DataSourceRouteRuleEngineFactory(IDataSourceRouteRuleEngine dataSourceRouteRuleEngine) { _dataSourceRouteRuleEngine = dataSourceRouteRuleEngine; } @@ -40,24 +42,22 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine /// 路由到具体的物理数据源 /// /// - /// /// /// - public DataSourceRouteResult Route(Type shardingDbContextType, IQueryable queryable) + public DataSourceRouteResult Route(IQueryable queryable) { var ruleContext = CreateContext(queryable); - return _dataSourceRouteRuleEngine.Route(shardingDbContextType,ruleContext); + return _dataSourceRouteRuleEngine.Route(ruleContext); } /// /// 路由到具体的物理数据源 /// /// - /// /// /// - public DataSourceRouteResult Route(Type shardingDbContextType, DataSourceRouteRuleContext ruleContext) + public DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext) { - return _dataSourceRouteRuleEngine.Route(shardingDbContextType, ruleContext); + return _dataSourceRouteRuleEngine.Route(ruleContext); } } } diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngine.cs index 2e857be2..34b5700c 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngine.cs @@ -15,7 +15,12 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine */ public interface IDataSourceRouteRuleEngine { - DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext) where TShardingDbContext:DbContext,IShardingDbContext; - DataSourceRouteResult Route(Type shardingDbContextType, DataSourceRouteRuleContext routeRuleContext); + DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext); + } + + public interface IDataSourceRouteRuleEngine : IDataSourceRouteRuleEngine + where TShardingDbContext : DbContext, IShardingDbContext + { + } } diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs index 1e70084d..db861b19 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine { @@ -12,10 +14,12 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine * @Ver: 1.0 * @Email: 326308290@qq.com */ - public interface IDataSourceRouteRuleEngineFactory + + public interface IDataSourceRouteRuleEngineFactory + where TShardingDbContext : DbContext, IShardingDbContext { DataSourceRouteRuleContext CreateContext(IQueryable queryable); - DataSourceRouteResult Route(Type shardingDbContextType, IQueryable queryable); - DataSourceRouteResult Route(Type shardingDbContextType, DataSourceRouteRuleContext ruleContext); + DataSourceRouteResult Route(IQueryable queryable); + DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext); } } diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngine.cs index 2fa8d7ed..3cecace7 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngine.cs @@ -11,9 +11,10 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine * @Date: Thursday, 28 January 2021 10:25:22 * @Email: 326308290@qq.com */ - public interface ITableRouteRuleEngine + + public interface ITableRouteRuleEngine + where TShardingDbContext : DbContext, IShardingDbContext { - IEnumerable Route(TableRouteRuleContext tableRouteRuleContext) where TShardingDbContext:DbContext,IShardingDbContext; - IEnumerable Route(Type shardingDbContextType,TableRouteRuleContext tableRouteRuleContext); + IEnumerable Route(TableRouteRuleContext tableRouteRuleContext); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngineFactory.cs index 5f692a47..80d35240 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/ITableRouteRuleEngineFactory.cs @@ -12,10 +12,11 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine * @Date: Thursday, 28 January 2021 13:30:28 * @Email: 326308290@qq.com */ - public interface ITableRouteRuleEngineFactory + public interface ITableRouteRuleEngineFactory + where TShardingDbContext : DbContext, IShardingDbContext { TableRouteRuleContext CreateContext(IQueryable queryable); - IEnumerable Route(Type shardingDbContextType,IQueryable queryable); - IEnumerable Route(Type shardingDbContextType, TableRouteRuleContext ruleContext); + IEnumerable Route(IQueryable queryable); + IEnumerable Route(TableRouteRuleContext ruleContext); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleContext.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleContext.cs index 3bc993cf..d0522016 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleContext.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleContext.cs @@ -12,12 +12,10 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine */ public class TableRouteRuleContext { - private readonly IVirtualTableManager _virtualTableManager; - public TableRouteRuleContext(IQueryable queryable, IVirtualTableManager virtualTableManager) + public TableRouteRuleContext(IQueryable queryable) { Queryable = queryable; - _virtualTableManager = virtualTableManager; } public IQueryable Queryable { get; } diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngine.cs index 30b76b6b..ddca99a7 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngine.cs @@ -21,78 +21,16 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine * @Date: Thursday, 28 January 2021 10:51:59 * @Email: 326308290@qq.com */ - public class TableRouteRuleEngines:ITableRouteRuleEngine + public class TableRouteRuleEngine : ITableRouteRuleEngine where TShardingDbContext:DbContext,IShardingDbContext { - private readonly IVirtualTableManager _virtualTableManager; + private readonly IVirtualTableManager _virtualTableManager; - public TableRouteRuleEngines(IVirtualTableManager virtualTableManager) + public TableRouteRuleEngine(IVirtualTableManager virtualTableManager) { _virtualTableManager = virtualTableManager; } - public IEnumerable Route(TableRouteRuleContext tableRouteRuleContext) where TShardingDbContext : DbContext, IShardingDbContext - { - return Route(typeof(TShardingDbContext), tableRouteRuleContext); - ////先添加手动路由到当前上下文,之后将不再手动路由里面的自动路由添加到当前上下文 - //foreach (var kv in tableRouteRuleContext.ManualTails) - //{ - // var virtualTable = kv.Key; - // var addTails = kv.Value; - // var physicTables = virtualTable.GetAllPhysicTables().Where(o=>addTails.Contains(o.Tail)); - // if (!routeMaps.ContainsKey(virtualTable)) - // { - // routeMaps.Add(virtualTable,physicTables.ToHashSet()); - // } - // else - // { - // foreach (var physicTable in physicTables) - // { - // routeMaps[virtualTable].Add(physicTable); - // } - // } - //} - //foreach (var kv in tableRouteRuleContext.ManualPredicate) - //{ - // var virtualTable = kv.Key; - // var predicate = kv.Value; - // var physicTables = virtualTable.RouteTo(new TableRouteConfig(null, null, null, predicate)); - // if (!routeMaps.ContainsKey(virtualTable)) - // { - // routeMaps.Add(virtualTable, physicTables.ToHashSet()); - // } - // else - // { - // foreach (var physicTable in physicTables) - // { - // routeMaps[virtualTable].Add(physicTable); - // } - // } - //} - - //if (tableRouteRuleContext.AutoParseRoute) - //{ - // var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); - // foreach (var shardingEntity in shardingEntities) - // { - // var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntity); - - // var physicTables = virtualTable.RouteTo(new TableRouteConfig(tableRouteRuleContext.Queryable)); - // if (!routeMaps.ContainsKey(virtualTable)) - // { - // routeMaps.Add(virtualTable, physicTables.ToHashSet()); - // } - // else - // { - // foreach (var physicTable in physicTables) - // { - // routeMaps[virtualTable].Add(physicTable); - // } - // } - // } - //} - } - - public IEnumerable Route(Type shardingDbContextType, TableRouteRuleContext tableRouteRuleContext) + public IEnumerable Route(TableRouteRuleContext tableRouteRuleContext) { Dictionary> routeMaps = new Dictionary>(); var queryEntities = tableRouteRuleContext.Queryable.ParseQueryableRoute(); @@ -101,7 +39,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); foreach (var shardingEntity in shardingEntities) { - var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntity); + var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntity); var physicTables = virtualTable.RouteTo(new ShardingTableRouteConfig(tableRouteRuleContext.Queryable)); if (!routeMaps.ContainsKey(virtualTable)) diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngineFactory.cs index 435ba46b..2a7639f5 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteRuleEngineFactory.cs @@ -17,15 +17,13 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine /// /// ·ɹ湤 /// - public class TableRouteRuleEngineFactory : ITableRouteRuleEngineFactory + public class TableRouteRuleEngineFactory : ITableRouteRuleEngineFactory where TShardingDbContext : DbContext, IShardingDbContext { - private readonly ITableRouteRuleEngine _tableRouteRuleEngine; - private readonly IVirtualTableManager _virtualTableManager; + private readonly ITableRouteRuleEngine _tableRouteRuleEngine; - public TableRouteRuleEngineFactory(ITableRouteRuleEngine tableRouteRuleEngine, IVirtualTableManager virtualTableManager) + public TableRouteRuleEngineFactory(ITableRouteRuleEngine tableRouteRuleEngine) { _tableRouteRuleEngine = tableRouteRuleEngine; - _virtualTableManager = virtualTableManager; } /// /// · @@ -36,18 +34,18 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine /// public TableRouteRuleContext CreateContext(IQueryable queryable) { - return new TableRouteRuleContext(queryable, _virtualTableManager); + return new TableRouteRuleContext(queryable); } - public IEnumerable Route(Type shardingDbContextType, IQueryable queryable) + public IEnumerable Route(IQueryable queryable) { var ruleContext = CreateContext(queryable); - return _tableRouteRuleEngine.Route(shardingDbContextType,ruleContext); + return _tableRouteRuleEngine.Route(ruleContext); } - public IEnumerable Route(Type shardingDbContextType, TableRouteRuleContext ruleContext) + public IEnumerable Route(TableRouteRuleContext ruleContext) { - return _tableRouteRuleEngine.Route(shardingDbContextType,ruleContext); + return _tableRouteRuleEngine.Route(ruleContext); } } } \ No newline at end of file diff --git a/src/ShardingCore/DIExtension.cs b/src/ShardingCore/DIExtension.cs index 910365db..cf950609 100644 --- a/src/ShardingCore/DIExtension.cs +++ b/src/ShardingCore/DIExtension.cs @@ -13,13 +13,17 @@ using ShardingCore.Sharding.Abstractions; using ShardingCore.TableCreator; using System; using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.Extensions.DependencyInjection.Extensions; using ShardingCore.Core.QueryRouteManagers; using ShardingCore.Core.QueryRouteManagers.Abstractions; using ShardingCore.Core.ShardingPage; using ShardingCore.Core.ShardingPage.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; +using ShardingCore.DIExtensions; using ShardingCore.Sharding.ReadWriteConfigurations; using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; using ShardingCore.Sharding.ShardingQueryExecutors; @@ -34,25 +38,15 @@ namespace ShardingCore */ public static class DIExtension { - - public static IServiceCollection AddShardingDbContext(this IServiceCollection services, + public static ShardingCoreConfigBuilder 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, IShardingDbContext { - 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); - - services.AddShardingBaseOptions(shardingConfigOptions); + ShardingCoreHelper.CheckContextConstructors(); Action shardingOptionAction = option => { optionsAction?.Invoke(option); @@ -60,120 +54,173 @@ namespace ShardingCore }; services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); - services.AddInternalShardingCore(); - - - - return services; + return new ShardingCoreConfigBuilder(services); } - public static IServiceCollection AddShardingDbContext(this IServiceCollection services, - Action optionsAction = null, - Action> configure=null, + public static ShardingCoreConfigBuilder AddShardingDbContext(this IServiceCollection services, + Action optionsAction = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TActualDbContext : DbContext, IShardingTableDbContext where TShardingDbContext : DbContext, IShardingDbContext { - 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); - - - - services.AddShardingBaseOptions(shardingConfigOptions); - Action shardingOptionAction = (sp, option) => { - optionsAction?.Invoke(sp,option); + optionsAction?.Invoke(sp, option); option.UseSharding(); }; services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); - services.AddInternalShardingCore(); - - - - return services; + return new ShardingCoreConfigBuilder(services); } - internal static void AddShardingBaseOptions(this IServiceCollection services, - ShardingConfigOption shardingConfigOptions) - where TActualDbContext : DbContext, IShardingTableDbContext - where TShardingDbContext : DbContext, IShardingDbContext - { + //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, IShardingDbContext + //{ + // if (configure == null) + // throw new ArgumentNullException($"AddShardingDbContext params is null :{nameof(configure)}"); - //添加创建TActualDbContext 的DbContextOptionsBuilder创建者 - var config = new ShardingDbContextOptionsBuilderConfig(shardingConfigOptions.SameConnectionConfigure, shardingConfigOptions.DefaultQueryConfigure); - services.AddSingleton>(sp => config); + // ShardingCoreHelper.CheckContextConstructors(); + // var shardingConfigOptions = new ShardingConfigOption(); + // configure?.Invoke(shardingConfigOptions); + // services.AddSingleton>(sp=> shardingConfigOptions); - //添加创建TActualDbContext创建者 - services.AddSingleton>(sp => new DefaultShardingDbContextCreatorConfig(typeof(TActualDbContext))); + // services.AddShardingBaseOptions(shardingConfigOptions); - if (!shardingConfigOptions.UseReadWrite) - { - services.AddTransient>(); - } - else - { - services.AddTransient>(); + // Action shardingOptionAction = option => + // { + // optionsAction?.Invoke(option); + // option.UseSharding(); - services.AddSingleton>(sp=>new ReadWriteOptions(shardingConfigOptions.ReadWriteDefaultPriority, shardingConfigOptions.ReadWriteDefaultEnable, shardingConfigOptions.ReadConnStringGetStrategy)); - if (shardingConfigOptions.ReadStrategyEnum == ReadStrategyEnum.Loop) - { - services - .AddSingleton>(sp => - new LoopShardingConnectionStringResolver( - shardingConfigOptions.ReadConnStringConfigure(sp))); - }else if (shardingConfigOptions.ReadStrategyEnum == ReadStrategyEnum.Random) - { - services - .AddSingleton>(sp => - new RandomShardingConnectionStringResolver( - shardingConfigOptions.ReadConnStringConfigure(sp))); - } + // }; + // services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); + // services.AddInternalShardingCore(); - services.AddSingleton(); - services.AddSingleton>(); - } - } + + // return 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, IShardingDbContext + //{ + // 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); + + + + // services.AddShardingBaseOptions(shardingConfigOptions); + + + + // Action shardingOptionAction = (sp, option) => + // { + // optionsAction?.Invoke(sp,option); + // option.UseSharding(); + // }; + // services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); + // services.AddInternalShardingCore(); + + + + // return services; + //} + //internal static void AddShardingBaseOptions(this IServiceCollection services, + // ShardingConfigOption shardingConfigOptions) + // where TActualDbContext : DbContext, IShardingTableDbContext + // where TShardingDbContext : DbContext, IShardingDbContext + //{ + + // //添加创建TActualDbContext 的DbContextOptionsBuilder创建者 + // var config = new ShardingDbContextOptionsBuilderConfig(shardingConfigOptions.SameConnectionConfigure, shardingConfigOptions.DefaultQueryConfigure); + // services.AddSingleton, ShardingDbContextOptionsBuilderConfig>(sp => config); + + // //添加创建TActualDbContext创建者 + // services.AddSingleton>(sp => new DefaultShardingDbContextCreatorConfig(typeof(TActualDbContext))); + + // if (!shardingConfigOptions.UseReadWrite) + // { + // services.AddTransient>(); + // } + // else + // { + // services.AddTransient>(); + + // services.AddSingleton>(sp=>new ReadWriteOptions(shardingConfigOptions.ReadWriteDefaultPriority, shardingConfigOptions.ReadWriteDefaultEnable, shardingConfigOptions.ReadConnStringGetStrategy)); + // //if (shardingConfigOptions.ReadStrategyEnum == ReadStrategyEnum.Loop) + // //{ + // // services + // // .AddSingleton>(sp => + // // new LoopShardingConnectionStringResolver( + // // shardingConfigOptions.ReadConnStringConfigure(sp))); + // //}else if (shardingConfigOptions.ReadStrategyEnum == ReadStrategyEnum.Random) + // //{ + // // services + // // .AddSingleton>(sp => + // // new RandomShardingConnectionStringResolver( + // // shardingConfigOptions.ReadConnStringConfigure(sp))); + // //} + + + // services.TryAddSingleton(); + // services.AddSingleton>(); + // } + //} internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services) { - services.AddSingleton(); + services.TryAddSingleton(typeof(IStreamMergeContextFactory<>),typeof(StreamMergeContextFactory<>)); + services.TryAddSingleton(typeof(IShardingTableCreator<>),typeof(ShardingTableCreator<>)); + //虚拟数据源管理 + services.TryAddSingleton(typeof(IVirtualDataSource<>), typeof(VirtualDataSource<>)); + services.TryAddSingleton(typeof(IDataSourceRouteRuleEngine<>), typeof(DataSourceRouteRuleEngine<>)); + services.TryAddSingleton(typeof(IDataSourceRouteRuleEngineFactory<>), typeof(DataSourceRouteRuleEngineFactory<>)); + + + //虚拟表管理 + services.TryAddSingleton(typeof(IVirtualTableManager<>),typeof(VirtualTableManager<>)); + //分表dbcontext创建 + services.TryAddSingleton(typeof(IShardingDbContextFactory<>), typeof(ShardingDbContextFactory<>)); - services.AddSingleton(); - services.AddSingleton(); - //分表 - services.AddSingleton(); - //分表引擎工程 - services.AddSingleton(); //分表引擎 - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(typeof(ITableRouteRuleEngine<>),typeof(TableRouteRuleEngine<>)); + //分表引擎工程 + services.TryAddSingleton(typeof(ITableRouteRuleEngineFactory<>),typeof(TableRouteRuleEngineFactory<>)); + services.TryAddSingleton(); + services.TryAddSingleton(); //route manage - services.AddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); //sharding page - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); return services; } internal static DbContextOptionsBuilder UseSharding(this DbContextOptionsBuilder optionsBuilder) { return optionsBuilder.ReplaceService() - .ReplaceService() - .ReplaceService(); + .ReplaceService(); + //.ReplaceService(); } diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs new file mode 100644 index 00000000..1747dc16 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 20:49:03 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingCoreConfigBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + public IServiceCollection Services { get; } + + + public ShardingConfigOption ShardingConfigOption { get; } + + + + public ShardingCoreConfigBuilder(IServiceCollection services) + { + Services = services; + ShardingConfigOption = new ShardingConfigOption(); + } + + + public ShardingQueryBuilder Begin(bool ensureCreatedWithOutShardingTable, bool? createShardingTableOnStart = null,bool? ignoreCreateTableError = null) + { + ShardingConfigOption.EnsureCreatedWithOutShardingTable = ensureCreatedWithOutShardingTable; + ShardingConfigOption.CreateShardingTableOnStart = createShardingTableOnStart; + ShardingConfigOption.IgnoreCreateTableError = ignoreCreateTableError; + return new ShardingQueryBuilder(this); + } + //public ShardingCoreConfigBuilder AddDefaultDataSource(string dataSourceName, string connectionString) + //{ + // if (!string.IsNullOrWhiteSpace(defaultDataSourceName) || !string.IsNullOrWhiteSpace(defaultConnectionString)) + // throw new InvalidOperationException($"{nameof(AddDefaultDataSource)}-{dataSourceName}"); + // this.defaultDataSourceName = dataSourceName; + // this.defaultConnectionString = connectionString; + // return this; + //} + + //public ShardingCoreConfigBuilder AddDataSource(string dataSourceName, string connectionString) + //{ + // if (_dataSources.ContainsKey(dataSourceName)) + // throw new InvalidOperationException($"{nameof(AddDataSource)}-{dataSourceName} repeat"); + // _dataSources.Add(dataSourceName, connectionString); + // return this; + //} + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs new file mode 100644 index 00000000..b3b699e5 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using ShardingCore.Sharding; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ReadWriteConfigurations; +using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 22:36:20 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingCoreConfigEndBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingCoreConfigEndBuilder( + ShardingCoreConfigBuilder shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + + public IServiceCollection End() + { + var services = _shardingCoreConfigBuilder.Services; + services.AddSingleton>(sp => + _shardingCoreConfigBuilder.ShardingConfigOption); + + + //添加创建TActualDbContext 的DbContextOptionsBuilder创建者 + var config = new ShardingDbContextOptionsBuilderConfig( + _shardingCoreConfigBuilder.ShardingConfigOption.SameConnectionConfigure, + _shardingCoreConfigBuilder.ShardingConfigOption.DefaultQueryConfigure); + services + .AddSingleton, + ShardingDbContextOptionsBuilderConfig>(sp => config); + + //添加创建TActualDbContext创建者 + services + .AddSingleton>(sp => + new DefaultShardingDbContextCreatorConfig( + typeof(TActualDbContext))); + + if (!_shardingCoreConfigBuilder.ShardingConfigOption.UseReadWrite) + { + services.AddTransient, DefaultConnectionStringManager>(); + } + else + { + services.AddTransient, ReadWriteConnectionStringManager>(); + + services.AddSingleton>(sp => + new ReadWriteOptions( + _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority, + _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable, + _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy)); + if (_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum == ReadStrategyEnum.Loop) + { + services + .AddSingleton>(sp => + { + + var readConnString = _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringConfigure(sp); + var readWriteLoopConnectors = readConnString.Select(o => new ReadWriteLoopConnector(o.Key, o.Value)); + + return new LoopShardingConnectionStringResolver( + readWriteLoopConnectors); + }); + } + else if (_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum == ReadStrategyEnum.Random) + { + services + .AddSingleton>(sp => + { + var readConnString = _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringConfigure(sp); + var readWriteRandomConnectors = readConnString.Select(o => new ReadWriteRandomConnector(o.Key, o.Value)); + return new RandomShardingConnectionStringResolver( + readWriteRandomConnectors); + }); + } + + + services.TryAddSingleton(); + services.AddSingleton>(); + //foreach (var dataSourceKv in dataSources) + //{ + // if (dataSourceKv.Key == _shardingCoreConfigBuilder.DefaultDataSourceName) + // throw new InvalidOperationException($"{nameof(AddShardingDataBase)} include default data source name:{_shardingCoreConfigBuilder.DefaultDataSourceName}"); + // _shardingCoreConfigBuilder.AddShardingDataSource.Add(dataSourceKv.Key, dataSourceKv.Value); + //} + } + services.AddInternalShardingCore(); + + return services; + + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs b/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs new file mode 100644 index 00000000..74aeb4d9 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 21:37:11 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingDataBaseOrTableBuilder: ShardingReadWriteSeparationBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingDataBaseOrTableBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder):base(shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + + public ShardingTableBuilder AddShardingDataBase(Func> dataSourcesConfigure, Action shardingDatabaseConfigure) + { + + _shardingCoreConfigBuilder.ShardingConfigOption.AddShardingDataSource(dataSourcesConfigure); + var shardingDatabaseOptions = new ShardingDatabaseOptions(); + shardingDatabaseConfigure.Invoke(shardingDatabaseOptions); + var shardingDatabaseRoutes = shardingDatabaseOptions.GetShardingDatabaseRoutes(); + foreach (var shardingDatabaseRoute in shardingDatabaseRoutes) + { + _shardingCoreConfigBuilder.ShardingConfigOption.AddShardingDataSourceRoute(shardingDatabaseRoute); + } + + return new ShardingTableBuilder(_shardingCoreConfigBuilder); + } + + public ShardingReadWriteSeparationBuilder AddShardingTable(Action shardingTableConfigure) + { + + var shardingTableOptions = new ShardingTableOptions(); + shardingTableConfigure.Invoke(shardingTableOptions); + var shardingTableRoutes = shardingTableOptions.GetShardingTableRoutes(); + foreach (var shardingTableRoute in shardingTableRoutes) + { + _shardingCoreConfigBuilder.ShardingConfigOption.AddShardingTableRoute(shardingTableRoute); + } + return new ShardingReadWriteSeparationBuilder(_shardingCoreConfigBuilder); + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingDatabaseOrTableOptions.cs b/src/ShardingCore/DIExtensions/ShardingDatabaseOrTableOptions.cs new file mode 100644 index 00000000..f1986426 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingDatabaseOrTableOptions.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 22:21:45 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingDatabaseOptions + { + private readonly ICollection _virtualDataSourceRoutes = new LinkedList(); + + /// + /// 添加分表路由 + /// + /// + public void AddShardingDatabaseRoute() where TRoute : IVirtualDataSourceRoute + { + var routeType = typeof(TRoute); + _virtualDataSourceRoutes.Add(routeType); + } + + public ICollection GetShardingDatabaseRoutes() + { + return _virtualDataSourceRoutes; + } + } + public class ShardingTableOptions + { + private readonly ICollection _virtualTableRoutes = new LinkedList(); + + /// + /// 添加分表路由 + /// + /// + public void AddShardingTableRoute() where TRoute : IVirtualTableRoute + { + var routeType = typeof(TRoute); + _virtualTableRoutes.Add(routeType); + } + + public ICollection GetShardingTableRoutes() + { + return _virtualTableRoutes; + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingDefaultDataSourceBuilder.cs b/src/ShardingCore/DIExtensions/ShardingDefaultDataSourceBuilder.cs new file mode 100644 index 00000000..3a3f6a37 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingDefaultDataSourceBuilder.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 21:33:21 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingDefaultDataSourceBuilder: ShardingCoreConfigEndBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingDefaultDataSourceBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder):base(shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + public ShardingDataBaseOrTableBuilder AddDefaultDataSource(string dataSourceName, string connectionString) + { + if (!string.IsNullOrWhiteSpace(_shardingCoreConfigBuilder.ShardingConfigOption.DefaultDataSourceName) || !string.IsNullOrWhiteSpace(_shardingCoreConfigBuilder.ShardingConfigOption.DefaultConnectionString)) + throw new InvalidOperationException($"{nameof(AddDefaultDataSource)}-{dataSourceName}"); + _shardingCoreConfigBuilder.ShardingConfigOption.DefaultDataSourceName = dataSourceName; + _shardingCoreConfigBuilder.ShardingConfigOption.DefaultConnectionString = connectionString; + return new ShardingDataBaseOrTableBuilder(_shardingCoreConfigBuilder); + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingQueryBuilder.cs b/src/ShardingCore/DIExtensions/ShardingQueryBuilder.cs new file mode 100644 index 00000000..e237ec05 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingQueryBuilder.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.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 21:11:48 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingQueryBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingQueryBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + public ShardingTransactionBuilder AddShardingQuery(Action queryConfigure) + { + _shardingCoreConfigBuilder.ShardingConfigOption.UseShardingQuery(queryConfigure); + return new ShardingTransactionBuilder(_shardingCoreConfigBuilder); + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs b/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs new file mode 100644 index 00000000..8da23f63 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ReadWriteConfigurations; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 22:44:54 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingReadWriteSeparationBuilder : ShardingCoreConfigEndBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingReadWriteSeparationBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder) : base(shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + + public ShardingCoreConfigEndBuilder AddReadWriteSeparation( + Func>> readWriteSeparationConfigure, + ReadStrategyEnum readStrategyEnum, + bool defaultEnable = false, + int defaultPriority = 10, + ReadConnStringGetStrategyEnum readConnStringGetStrategy = ReadConnStringGetStrategyEnum.LatestFirstTime) + { + _shardingCoreConfigBuilder.ShardingConfigOption.UseReadWriteConfiguration(readWriteSeparationConfigure,readStrategyEnum, defaultEnable,defaultPriority); + return new ShardingCoreConfigEndBuilder(_shardingCoreConfigBuilder); + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs b/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs new file mode 100644 index 00000000..afaf4958 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 22:56:44 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingTableBuilder : ShardingReadWriteSeparationBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingTableBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder) : base(shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + + public ShardingReadWriteSeparationBuilder AddShardingTable(Action shardingTableConfigure) + { + + var shardingTableOptions = new ShardingTableOptions(); + shardingTableConfigure.Invoke(shardingTableOptions); + var shardingTableRoutes = shardingTableOptions.GetShardingTableRoutes(); + foreach (var shardingTableRoute in shardingTableRoutes) + { + _shardingCoreConfigBuilder.ShardingConfigOption.AddShardingTableRoute(shardingTableRoute); + } + return new ShardingReadWriteSeparationBuilder(_shardingCoreConfigBuilder); + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingTransactionBuilder.cs b/src/ShardingCore/DIExtensions/ShardingTransactionBuilder.cs new file mode 100644 index 00000000..d5dae339 --- /dev/null +++ b/src/ShardingCore/DIExtensions/ShardingTransactionBuilder.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.DIExtensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/19 21:13:43 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingTransactionBuilder + where TActualDbContext : DbContext + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingTransactionBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + public ShardingDefaultDataSourceBuilder AddShardingTransaction(Action transactionConfigure) + { + _shardingCoreConfigBuilder.ShardingConfigOption.UseShardingTransaction(transactionConfigure); + return new ShardingDefaultDataSourceBuilder(_shardingCoreConfigBuilder); + } + } +} diff --git a/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs index b7de173b..276c3f5e 100644 --- a/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs @@ -13,11 +13,8 @@ namespace ShardingCore.DbContexts * @Date: Thursday, 24 December 2020 08:22:23 * @Email: 326308290@qq.com */ - public interface IShardingDbContextFactory + public interface IShardingDbContextFactory where TShardingDbContext:DbContext,IShardingDbContext { DbContext Create(ShardingDbContextOptions shardingDbContextOptions); } - public interface IShardingDbContextFactory: IShardingDbContextFactory where TShardingDbContext:DbContext,IShardingDbContext - { - } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs index e34eef0c..02b02e60 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs @@ -15,28 +15,22 @@ namespace ShardingCore.DbContexts * @Date: Thursday, 24 December 2020 08:22:48 * @Email: 326308290@qq.com */ - public class ShardingDbContextFactory:IShardingDbContextFactory + public class ShardingDbContextFactory : IShardingDbContextFactory where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IEnumerable _shardingDbContextCreatorConfigs; + private readonly IShardingDbContextCreatorConfig _shardingDbContextCreatorConfig; public ShardingDbContextFactory(IEnumerable shardingDbContextCreatorConfigs) { - _shardingDbContextCreatorConfigs = shardingDbContextCreatorConfigs; + _shardingDbContextCreatorConfig = shardingDbContextCreatorConfigs + .FirstOrDefault(o => o.ShardingDbContextType == typeof(TShardingDbContext)) + ??throw new ShardingCoreException( + $"{typeof(TShardingDbContext).FullName} cant found DefaultShardingDbContextCreatorConfig<{typeof(TShardingDbContext).Name}> should use {nameof(DIExtension.AddShardingDbContext)}"); } - public DbContext Create(Type shardingDbContextType, ShardingDbContextOptions shardingDbContextOptions) + public DbContext Create(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 routeTail=shardingDbContextOptions.RouteTail; - var dbContext = shardingDbContextCreatorConfig.Creator(shardingDbContextOptions); + var dbContext = _shardingDbContextCreatorConfig.Creator(shardingDbContextOptions); if (dbContext is IShardingTableDbContext shardingTableDbContext) { shardingTableDbContext.RouteTail = routeTail; @@ -44,11 +38,5 @@ namespace ShardingCore.DbContexts var dbContextModel = dbContext.Model; return dbContext; } - - - 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/DefaultShardingDbContextCreatorConfig.cs b/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs index 22095b55..2d589cdb 100644 --- a/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs +++ b/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs @@ -15,7 +15,7 @@ namespace ShardingCore */ public class DefaultShardingDbContextCreatorConfig : IShardingDbContextCreatorConfig where TShardingDbContext : DbContext, IShardingDbContext - where TActualDbContext : DbContext, IShardingTableDbContext + where TActualDbContext : DbContext { private readonly Func _creator; public DefaultShardingDbContextCreatorConfig(Type actualDbContextType) diff --git a/src/ShardingCore/EFCores/RelationTransactions/ShardingRelationalTransaction.cs b/src/ShardingCore/EFCores/RelationTransactions/ShardingRelationalTransaction.cs index 07710759..6929fa26 100644 --- a/src/ShardingCore/EFCores/RelationTransactions/ShardingRelationalTransaction.cs +++ b/src/ShardingCore/EFCores/RelationTransactions/ShardingRelationalTransaction.cs @@ -1,65 +1,65 @@ -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage; -using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.ShardingTransactions; +//using System; +//using System.Collections.Generic; +//using System.Data.Common; +//using System.Text; +//using System.Threading; +//using System.Threading.Tasks; +//using Microsoft.EntityFrameworkCore; +//using Microsoft.EntityFrameworkCore.Diagnostics; +//using Microsoft.EntityFrameworkCore.Infrastructure; +//using Microsoft.EntityFrameworkCore.Storage; +//using ShardingCore.Sharding.Abstractions; +//using ShardingCore.Sharding.ShardingTransactions; -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/9/5 20:37:36 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class ShardingRelationalTransaction : RelationalTransaction - { - private readonly IShardingTransaction _shardingDbContext; - public ShardingRelationalTransaction(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, IDiagnosticsLogger logger, bool transactionOwned) : base(connection, transaction, transactionId, logger, transactionOwned) - { - _shardingDbContext = (IShardingDbContext)null; - _shardingDbContext.UseShardingTransaction(transaction); - } +//namespace ShardingCore.EFCores +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: 2021/9/5 20:37:36 +// * @Ver: 1.0 +// * @Email: 326308290@qq.com +// */ +// public class ShardingRelationalTransaction : RelationalTransaction +// { +// private readonly IShardingTransaction _shardingDbContext; +// public ShardingRelationalTransaction(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, IDiagnosticsLogger logger, bool transactionOwned) : base(connection, transaction, transactionId, logger, transactionOwned) +// { +// _shardingDbContext = (IShardingDbContext)null; +// _shardingDbContext.UseShardingTransaction(transaction); +// } - protected override void ClearTransaction() - { - base.ClearTransaction(); - _shardingDbContext.UseShardingTransaction(null); - } +// protected override void ClearTransaction() +// { +// base.ClearTransaction(); +// _shardingDbContext.UseShardingTransaction(null); +// } - protected override async Task ClearTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) - { - await base.ClearTransactionAsync(cancellationToken); - _shardingDbContext.UseShardingTransaction(null); +// protected override async Task ClearTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// await base.ClearTransactionAsync(cancellationToken); +// _shardingDbContext.UseShardingTransaction(null); - } +// } - public override void Commit() - { - base.Commit(); - } +// public override void Commit() +// { +// base.Commit(); +// } - public override Task CommitAsync(CancellationToken cancellationToken = new CancellationToken()) - { - return base.CommitAsync(cancellationToken); - } +// public override Task CommitAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// return base.CommitAsync(cancellationToken); +// } - public override void Rollback() - { - base.Rollback(); - } +// public override void Rollback() +// { +// base.Rollback(); +// } - public override Task RollbackAsync(CancellationToken cancellationToken = new CancellationToken()) - { - return base.RollbackAsync(cancellationToken); - } - } -} +// public override Task RollbackAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// return base.RollbackAsync(cancellationToken); +// } +// } +//} diff --git a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs index 5dbf2187..05a95ebf 100644 --- a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs +++ b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs @@ -40,8 +40,8 @@ namespace ShardingCore.EFCores { var singleQueryRouteTail = (ISingleQueryRouteTail) shardingTableDbContext.RouteTail; var tail = singleQueryRouteTail.GetTail(); - var virtualTableManager = ShardingContainer.Services.GetService(); - var typeMap = virtualTableManager.GetAllVirtualTables(_shardingDbContextType).Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet(); + var virtualTableManager = ShardingContainer.GetService>(); + var typeMap = virtualTableManager.GetAllVirtualTables().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/EFCores/ShardingRelationalConnection.cs b/src/ShardingCore/EFCores/ShardingRelationalConnection.cs index 0a8f4960..983a6279 100644 --- a/src/ShardingCore/EFCores/ShardingRelationalConnection.cs +++ b/src/ShardingCore/EFCores/ShardingRelationalConnection.cs @@ -1,205 +1,205 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.EntityFrameworkCore.Storage.Internal; -using Microsoft.Extensions.DependencyInjection; -using ShardingCore.Extensions; -using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.ShardingTransactions; +//using System; +//using System.Collections.Generic; +//using System.Data; +//using System.Data.Common; +//using System.Text; +//using System.Threading; +//using System.Threading.Tasks; +//using Microsoft.EntityFrameworkCore; +//using Microsoft.EntityFrameworkCore.Internal; +//using Microsoft.EntityFrameworkCore.Query.Internal; +//using Microsoft.EntityFrameworkCore.Storage; +//using Microsoft.EntityFrameworkCore.Storage.Internal; +//using Microsoft.Extensions.DependencyInjection; +//using ShardingCore.Extensions; +//using ShardingCore.Sharding.Abstractions; +//using ShardingCore.Sharding.ShardingTransactions; -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/9/5 15:41:20 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class ShardingRelationalConnection : IRelationalConnection - { - private readonly IRelationalConnection _relationalConnection; +//namespace ShardingCore.EFCores +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: 2021/9/5 15:41:20 +// * @Ver: 1.0 +// * @Email: 326308290@qq.com +// */ +// public class ShardingRelationalConnection : IRelationalConnection +// { +// private readonly IRelationalConnection _relationalConnection; - private readonly ISupportShardingTransaction _supportShardingTransaction; - public ShardingRelationalConnection(IRelationalConnection _relationalConnection, DbTransaction transaction) - { - this._relationalConnection = _relationalConnection; - if (Context is ISupportShardingTransaction supportShardingTransaction) - { - _supportShardingTransaction = supportShardingTransaction; - } - } +// private readonly ISupportShardingTransaction _supportShardingTransaction; +// public ShardingRelationalConnection(IRelationalConnection _relationalConnection, DbTransaction transaction) +// { +// this._relationalConnection = _relationalConnection; +// if (Context is ISupportShardingTransaction supportShardingTransaction) +// { +// _supportShardingTransaction = supportShardingTransaction; +// } +// } - public void ResetState() - { - _relationalConnection.ResetState(); - } +// public void ResetState() +// { +// _relationalConnection.ResetState(); +// } - public Task ResetStateAsync(CancellationToken cancellationToken = new CancellationToken()) - { - return _relationalConnection.ResetStateAsync(cancellationToken); - } +// public Task ResetStateAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// return _relationalConnection.ResetStateAsync(cancellationToken); +// } - public IDbContextTransaction BeginTransaction() - { - var dbContextTransaction = _relationalConnection.BeginTransaction(); - _supportShardingTransaction?.BeginTransaction(); - return dbContextTransaction; - } +// public IDbContextTransaction BeginTransaction() +// { +// var dbContextTransaction = _relationalConnection.BeginTransaction(); +// _supportShardingTransaction?.BeginTransaction(); +// return dbContextTransaction; +// } - public async Task BeginTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) - { - var dbContextTransaction = await _relationalConnection.BeginTransactionAsync(cancellationToken); - _supportShardingTransaction?.BeginTransaction(); - return dbContextTransaction; - } +// public async Task BeginTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// var dbContextTransaction = await _relationalConnection.BeginTransactionAsync(cancellationToken); +// _supportShardingTransaction?.BeginTransaction(); +// return dbContextTransaction; +// } - public void CommitTransaction() - { - _relationalConnection.CommitTransaction(); - _supportShardingTransaction?.Commit(); - } +// public void CommitTransaction() +// { +// _relationalConnection.CommitTransaction(); +// _supportShardingTransaction?.Commit(); +// } - public void RollbackTransaction() - { - _relationalConnection.RollbackTransaction(); - _supportShardingTransaction?.Rollback(); - } -#if EFCORE5 - public IDbContextTransaction UseTransaction(DbTransaction transaction, Guid transactionId) - { - var dbContextTransaction = _relationalConnection.UseTransaction(transaction, transactionId); - _supportShardingTransaction?.UseTransaction(transaction); - return dbContextTransaction; - } - public async Task UseTransactionAsync(DbTransaction transaction, Guid transactionId, - CancellationToken cancellationToken = new CancellationToken()) - { - var dbContextTransaction = await _relationalConnection.UseTransactionAsync(transaction, transactionId, cancellationToken); - _supportShardingTransaction?.UseTransaction(transaction); - return dbContextTransaction; - } +// public void RollbackTransaction() +// { +// _relationalConnection.RollbackTransaction(); +// _supportShardingTransaction?.Rollback(); +// } +//#if EFCORE5 +// public IDbContextTransaction UseTransaction(DbTransaction transaction, Guid transactionId) +// { +// var dbContextTransaction = _relationalConnection.UseTransaction(transaction, transactionId); +// _supportShardingTransaction?.UseTransaction(transaction); +// return dbContextTransaction; +// } +// public async Task UseTransactionAsync(DbTransaction transaction, Guid transactionId, +// CancellationToken cancellationToken = new CancellationToken()) +// { +// var dbContextTransaction = await _relationalConnection.UseTransactionAsync(transaction, transactionId, cancellationToken); +// _supportShardingTransaction?.UseTransaction(transaction); +// return dbContextTransaction; +// } - public async Task CommitTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) - { - await _relationalConnection.CommitTransactionAsync(cancellationToken); +// public async Task CommitTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// await _relationalConnection.CommitTransactionAsync(cancellationToken); - if (_supportShardingTransaction != null) - await _supportShardingTransaction.CommitAsync(cancellationToken); +// if (_supportShardingTransaction != null) +// await _supportShardingTransaction.CommitAsync(cancellationToken); - } - public async Task RollbackTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) - { - await _relationalConnection.RollbackTransactionAsync(cancellationToken); - if (_supportShardingTransaction != null) - await _supportShardingTransaction.RollbackAsync(cancellationToken); - } -#endif +// } +// public async Task RollbackTransactionAsync(CancellationToken cancellationToken = new CancellationToken()) +// { +// await _relationalConnection.RollbackTransactionAsync(cancellationToken); +// if (_supportShardingTransaction != null) +// await _supportShardingTransaction.RollbackAsync(cancellationToken); +// } +//#endif -#if !EFCORE5 - public bool IsMultipleActiveResultSetsEnabled => _relationalConnection.IsMultipleActiveResultSetsEnabled; +//#if !EFCORE5 +// public bool IsMultipleActiveResultSetsEnabled => _relationalConnection.IsMultipleActiveResultSetsEnabled; -# endif - IDbContextTransaction IRelationalConnection.CurrentTransaction => _relationalConnection.CurrentTransaction; +//# endif +// IDbContextTransaction IRelationalConnection.CurrentTransaction => _relationalConnection.CurrentTransaction; - IDbContextTransaction IDbContextTransactionManager.CurrentTransaction => _relationalConnection.CurrentTransaction; +// IDbContextTransaction IDbContextTransactionManager.CurrentTransaction => _relationalConnection.CurrentTransaction; - public SemaphoreSlim Semaphore => _relationalConnection.Semaphore; +// public SemaphoreSlim Semaphore => _relationalConnection.Semaphore; - public bool Open(bool errorsExpected = false) - { - return _relationalConnection.Open(errorsExpected); - } +// public bool Open(bool errorsExpected = false) +// { +// return _relationalConnection.Open(errorsExpected); +// } - public Task OpenAsync(CancellationToken cancellationToken, bool errorsExpected = false) - { - return _relationalConnection.OpenAsync(cancellationToken, errorsExpected); - } +// public Task OpenAsync(CancellationToken cancellationToken, bool errorsExpected = false) +// { +// return _relationalConnection.OpenAsync(cancellationToken, errorsExpected); +// } - public bool Close() - { - return _relationalConnection.Close(); - } +// public bool Close() +// { +// return _relationalConnection.Close(); +// } - public DbConnection DbConnection => _relationalConnection.DbConnection; +// public DbConnection DbConnection => _relationalConnection.DbConnection; - public DbContext Context => - _relationalConnection.Context; - public Guid ConnectionId => _relationalConnection.ConnectionId; +// public DbContext Context => +// _relationalConnection.Context; +// public Guid ConnectionId => _relationalConnection.ConnectionId; - public int? CommandTimeout - { - get - { - return _relationalConnection.CommandTimeout; - } - set - { - _relationalConnection.CommandTimeout = value; - } - } +// public int? CommandTimeout +// { +// get +// { +// return _relationalConnection.CommandTimeout; +// } +// set +// { +// _relationalConnection.CommandTimeout = value; +// } +// } - public IDbContextTransaction BeginTransaction(IsolationLevel isolationLevel) - { - var dbContextTransaction = _relationalConnection.BeginTransaction(isolationLevel); - _supportShardingTransaction?.BeginTransaction(isolationLevel); - return dbContextTransaction; - } +// public IDbContextTransaction BeginTransaction(IsolationLevel isolationLevel) +// { +// var dbContextTransaction = _relationalConnection.BeginTransaction(isolationLevel); +// _supportShardingTransaction?.BeginTransaction(isolationLevel); +// return dbContextTransaction; +// } - public async Task BeginTransactionAsync(IsolationLevel isolationLevel, - CancellationToken cancellationToken = new CancellationToken()) - { - var dbContextTransaction = await _relationalConnection.BeginTransactionAsync(isolationLevel, cancellationToken); - _supportShardingTransaction?.BeginTransaction(isolationLevel); - return dbContextTransaction; - } +// public async Task BeginTransactionAsync(IsolationLevel isolationLevel, +// CancellationToken cancellationToken = new CancellationToken()) +// { +// var dbContextTransaction = await _relationalConnection.BeginTransactionAsync(isolationLevel, cancellationToken); +// _supportShardingTransaction?.BeginTransaction(isolationLevel); +// return dbContextTransaction; +// } - public IDbContextTransaction UseTransaction(DbTransaction transaction) - { - var dbContextTransaction = _relationalConnection.UseTransaction(transaction); - _supportShardingTransaction?.UseTransaction(transaction); - return dbContextTransaction; - } +// public IDbContextTransaction UseTransaction(DbTransaction transaction) +// { +// var dbContextTransaction = _relationalConnection.UseTransaction(transaction); +// _supportShardingTransaction?.UseTransaction(transaction); +// return dbContextTransaction; +// } - public void Dispose() - { - _relationalConnection.Dispose(); - } +// public void Dispose() +// { +// _relationalConnection.Dispose(); +// } - public string ConnectionString => _relationalConnection.ConnectionString; +// public string ConnectionString => _relationalConnection.ConnectionString; - public async Task UseTransactionAsync(DbTransaction transaction, CancellationToken cancellationToken = new CancellationToken()) - { - var dbContextTransaction = await _relationalConnection.UseTransactionAsync(transaction, cancellationToken); - ((IShardingTransaction)Context).UseShardingTransaction(transaction); - return dbContextTransaction; +// public async Task UseTransactionAsync(DbTransaction transaction, CancellationToken cancellationToken = new CancellationToken()) +// { +// var dbContextTransaction = await _relationalConnection.UseTransactionAsync(transaction, cancellationToken); +// ((IShardingTransaction)Context).UseShardingTransaction(transaction); +// return dbContextTransaction; - } +// } - public Task CloseAsync() - { - return _relationalConnection.CloseAsync(); - } +// public Task CloseAsync() +// { +// return _relationalConnection.CloseAsync(); +// } - public ValueTask DisposeAsync() - { - return _relationalConnection.DisposeAsync(); - } - } -} +// public ValueTask DisposeAsync() +// { +// return _relationalConnection.DisposeAsync(); +// } +// } +//} diff --git a/src/ShardingCore/EFCores/ShardingRelationalTransactionFactory.cs b/src/ShardingCore/EFCores/ShardingRelationalTransactionFactory.cs index 87a02357..473559a8 100644 --- a/src/ShardingCore/EFCores/ShardingRelationalTransactionFactory.cs +++ b/src/ShardingCore/EFCores/ShardingRelationalTransactionFactory.cs @@ -1,33 +1,33 @@ -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.Text; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage; -using ShardingCore.Sharding.Abstractions; +//using System; +//using System.Collections.Generic; +//using System.Data.Common; +//using System.Text; +//using Microsoft.EntityFrameworkCore; +//using Microsoft.EntityFrameworkCore.Diagnostics; +//using Microsoft.EntityFrameworkCore.Infrastructure; +//using Microsoft.EntityFrameworkCore.Storage; +//using ShardingCore.Sharding.Abstractions; -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/9/5 16:03:04 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class ShardingRelationalTransactionFactory: RelationalTransactionFactory - { - private readonly RelationalTransactionFactoryDependencies _dependencies; - public ShardingRelationalTransactionFactory(RelationalTransactionFactoryDependencies dependencies) : base(dependencies) - { - _dependencies = dependencies; - } - public override RelationalTransaction Create(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, - IDiagnosticsLogger logger, bool transactionOwned) - { - return new RelationalTransaction(new ShardingRelationalConnection(connection, transaction), transaction, transactionId, logger, transactionOwned); - } - } -} +//namespace ShardingCore.EFCores +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: 2021/9/5 16:03:04 +// * @Ver: 1.0 +// * @Email: 326308290@qq.com +// */ +// public class ShardingRelationalTransactionFactory: RelationalTransactionFactory +// { +// private readonly RelationalTransactionFactoryDependencies _dependencies; +// public ShardingRelationalTransactionFactory(RelationalTransactionFactoryDependencies dependencies) : base(dependencies) +// { +// _dependencies = dependencies; +// } +// public override RelationalTransaction Create(IRelationalConnection connection, DbTransaction transaction, Guid transactionId, +// IDiagnosticsLogger logger, bool transactionOwned) +// { +// return new RelationalTransaction(new ShardingRelationalConnection(connection, transaction), transaction, transactionId, logger, transactionOwned); +// } +// } +//} diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs index 286f879a..afa24757 100644 --- a/src/ShardingCore/Extensions/ShardingExtension.cs +++ b/src/ShardingCore/Extensions/ShardingExtension.cs @@ -7,12 +7,14 @@ using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using ShardingCore.Core; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Core.VirtualTables; using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; +using ShardingCore.Utils; namespace ShardingCore.Extensions { @@ -68,26 +70,86 @@ namespace ShardingCore.Extensions /// /// 根据对象集合解析 /// + /// /// /// /// /// - public static IDictionary> BulkShardingEnumerable(this IShardingDbContext shardingDbContext, - IEnumerable entities) where TEntity : class + public static IDictionary> BulkShardingEnumerable(this TShardingDbContext shardingDbContext, + IEnumerable entities) where TShardingDbContext:DbContext,IShardingDbContext where TEntity : class { var entityType = typeof(TEntity); var routeTailFactory = ShardingContainer.GetService(); - if (!entityType.IsShardingTable()) + var virtualDataSource = ShardingContainer.GetService>(); + var dataSourceNames = new HashSet(); + if (!entityType.IsShardingDataSource()) { - var routeTail = routeTailFactory.Create(string.Empty); - var dbContext = shardingDbContext.GetDbContext(true, routeTail); - return new Dictionary>() - { - {dbContext,entities } - }; + dataSourceNames.Add(virtualDataSource.DefaultDataSourceName); } else { + var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType); + var allDataSourceNames = virtualDataSourceRoute.GetAllDataSourceNames(); + + var shardingEntityConfig = ShardingUtil.Parse(entityType); + foreach (var entity in entities) + { + entity.GetPropertyValue(shardingEntityConfig.ShardingDataSourceField) + virtualDataSourceRoute.ShardingKeyToDataSourceName(entity) + dataSourceNames.Add(dataSourceName); + } + } + if (!entityType.IsShardingDataSource()) + { + virtualDataSource. + var defaultDataSourceName = virtualDataSource.DefaultDataSourceName; + if (!entityType.IsShardingTable()) + { + var routeTail = routeTailFactory.Create(string.Empty); + var dbContext = shardingDbContext.GetDbContext(defaultDataSourceName, true, routeTail); + return new Dictionary>() + { + {dbContext,entities } + }; + } + else + { + var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContext.ShardingDbContextType)); + var virtualTable = virtualTableManager.GetVirtualTable(entityType); + + var virtualTableRoute = virtualTable.GetVirtualRoute(); + var hashSet = virtualTableRoute.GetAllTails().ToHashSet(); + var dic = new Dictionary>(); + foreach (var entity in entities) + { + var shardingKey = entity.GetPropertyValue(virtualTable.ShardingConfig.ShardingField); + var tail = virtualTableRoute.ShardingKeyToTail(shardingKey); + if (!hashSet.Contains(tail)) + throw new ShardingKeyRouteNotMatchException( + $"Entity:{entityType.FullName},ShardingKey:{shardingKey},ShardingTail:{tail}"); + + var routeTail = routeTailFactory.Create(tail); + var routeTailIdentity = routeTail.GetRouteTailIdentity(); + if (!dic.TryGetValue(routeTailIdentity, out var bulkDicEntry)) + { + var dbContext = shardingDbContext.GetDbContext(defaultDataSourceName, true, routeTail); + bulkDicEntry = new BulkDicEntry(dbContext, new LinkedList()); + dic.Add(routeTailIdentity, bulkDicEntry); + } + + bulkDicEntry.InnerEntities.AddLast(entity); + } + + return dic.Values.ToDictionary(o => o.InnerDbContext, o => o.InnerEntities.Select(t => t)); + + } + } + else + { + if (!entityType.IsShardingTable()) + { + + } var virtualTableManager = ShardingContainer.GetService(); var virtualTable = virtualTableManager.GetVirtualTable(shardingDbContext.ShardingDbContextType, entityType); diff --git a/src/ShardingCore/Extensions/StreamMergeContextExtension.cs b/src/ShardingCore/Extensions/StreamMergeContextExtension.cs index 19044d5d..a78361ba 100644 --- a/src/ShardingCore/Extensions/StreamMergeContextExtension.cs +++ b/src/ShardingCore/Extensions/StreamMergeContextExtension.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Sharding; namespace ShardingCore.Extensions @@ -20,11 +21,17 @@ namespace ShardingCore.Extensions /// public static bool IsShardingQuery(this StreamMergeContext streamMergeContext) { - return streamMergeContext.RouteResults.Count() > 1; + return streamMergeContext.TableRouteResults.Count() > 1; } public static bool IsSingleShardingTableQuery(this StreamMergeContext streamMergeContext) { - return streamMergeContext.RouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1; + return streamMergeContext.TableRouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1; + } + + public static IVirtualTableManager GetVirtualTableManager(this StreamMergeContext streamMergeContext) + { + return (IVirtualTableManager)ShardingContainer.GetService( + typeof(IVirtualTableManager<>).GetGenericType0(streamMergeContext.GetShardingDbContext().GetType())); } } } \ No newline at end of file diff --git a/src/ShardingCore/Extensions/VirtualDataBaseExtension.cs b/src/ShardingCore/Extensions/VirtualDataBaseExtension.cs index af9c4ac1..9599912c 100644 --- a/src/ShardingCore/Extensions/VirtualDataBaseExtension.cs +++ b/src/ShardingCore/Extensions/VirtualDataBaseExtension.cs @@ -7,6 +7,7 @@ using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualTables; @@ -73,10 +74,22 @@ namespace ShardingCore.Extensions public static string GetTableTail(this IVirtualTableManager virtualTableManager, TEntity entity) where TEntity : class { - if (entity.IsShardingTable()) + if (!entity.IsShardingTable()) return string.Empty; var physicTable = virtualTableManager.GetVirtualTable(entity.GetType()).RouteTo(new ShardingTableRouteConfig(null, entity as IShardingTable, null))[0]; return physicTable.Tail; } + public static bool IsVirtualDataSourceRoute(this Type routeType) + { + if (routeType == null) + throw new ArgumentNullException(nameof(routeType)); + return typeof(IVirtualDataSourceRoute).IsAssignableFrom(routeType); + } + public static bool IsIVirtualTableRoute(this Type routeType) + { + if (routeType == null) + throw new ArgumentNullException(nameof(routeType)); + return typeof(IVirtualTableRoute).IsAssignableFrom(routeType); + } } } diff --git a/src/ShardingCore/Extensions/VirtualDataSourceManagerExtension.cs b/src/ShardingCore/Extensions/VirtualDataSourceExtension.cs similarity index 66% rename from src/ShardingCore/Extensions/VirtualDataSourceManagerExtension.cs rename to src/ShardingCore/Extensions/VirtualDataSourceExtension.cs index cd855617..aeabab36 100644 --- a/src/ShardingCore/Extensions/VirtualDataSourceManagerExtension.cs +++ b/src/ShardingCore/Extensions/VirtualDataSourceExtension.cs @@ -19,11 +19,10 @@ namespace ShardingCore.Extensions * @Ver: 1.0 * @Email: 326308290@qq.com */ - public static class VirtualDataSourceManagerExtension + public static class VirtualDataSourceExtension { - public static string GetDataSourceName(this IVirtualDataSourceManager virtualDataSourceManager,TEntity entity) where TEntity : class + public static string GetDataSourceName(this IVirtualDataSource virtualDataSource,TEntity entity) where TShardingDbContext : DbContext, IShardingDbContext where TEntity : class { - var virtualDataSource = virtualDataSourceManager.GetVirtualDataSource(); if (!entity.IsShardingDataSource()) return virtualDataSource.DefaultDataSourceName; @@ -31,10 +30,10 @@ namespace ShardingCore.Extensions new ShardingDataSourceRouteConfig(shardingDataSource: entity as IShardingDataSource))[0]; } - public static List GetDataSourceNames(this IVirtualDataSourceManager virtualDataSourceManager,Expression> where) + public static List GetDataSourceNames(this IVirtualDataSource virtualDataSource, Expression> where) + where TShardingDbContext : DbContext, IShardingDbContext where TEntity : class { - var virtualDataSource = virtualDataSourceManager.GetVirtualDataSource(); return virtualDataSource.RouteTo(typeof(TEntity),new ShardingDataSourceRouteConfig(predicate: where)) .ToList(); } diff --git a/src/ShardingCore/Helpers/ShardingCoreHelper.cs b/src/ShardingCore/Helpers/ShardingCoreHelper.cs index f6d4af14..2d6f5ba4 100644 --- a/src/ShardingCore/Helpers/ShardingCoreHelper.cs +++ b/src/ShardingCore/Helpers/ShardingCoreHelper.cs @@ -106,7 +106,7 @@ namespace ShardingCore.Helpers //} } - public static Func CreateActivator() where TContext : DbContext, IShardingTableDbContext + public static Func CreateActivator() where TContext : DbContext { var constructors = typeof(TContext).GetTypeInfo().DeclaredConstructors @@ -149,7 +149,7 @@ namespace ShardingCore.Helpers /// /// /// - private static Func CreateShardingDbContextOptionsActivator(ConstructorInfo constructor, Type paramType) where TContext : DbContext, IShardingTableDbContext + private static Func CreateShardingDbContextOptionsActivator(ConstructorInfo constructor, Type paramType) where TContext : DbContext { var po = Expression.Parameter(paramType, "o"); var newExpression = Expression.New(constructor, po); @@ -168,7 +168,7 @@ namespace ShardingCore.Helpers /// /// /// - private static Func CreateDbContextOptionsGenericActivator(ConstructorInfo constructor, Type paramType) where TContext : DbContext, IShardingTableDbContext + private static Func CreateDbContextOptionsGenericActivator(ConstructorInfo constructor, Type paramType) where TContext : DbContext { var parameterExpression = Expression.Parameter(typeof(ShardingDbContextOptions), "o"); //o.DbContextOptions diff --git a/src/ShardingCore/IShardingConfigOption.cs b/src/ShardingCore/IShardingConfigOption.cs index df9698f8..6d456262 100644 --- a/src/ShardingCore/IShardingConfigOption.cs +++ b/src/ShardingCore/IShardingConfigOption.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Text; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore { @@ -15,11 +17,13 @@ namespace ShardingCore public interface IShardingConfigOption { Type ShardingDbContextType { get;} - Type ActualDbContextType { get;} bool UseReadWrite { get; } - void AddShardingTableRoute() where TRoute : IVirtualTableRoute; - Type GetVirtualRouteType(Type entityType); + Type GetVirtualTableRouteType(Type entityType); + Type GetVirtualDataSourceRouteType(Type entityType); + + + IDictionary GetDataSources(); /// @@ -34,5 +38,13 @@ namespace ShardingCore /// 忽略建表时的错误 /// public bool? IgnoreCreateTableError { get; set; } + + public string DefaultDataSourceName { get; set; } + public string DefaultConnectionString { get; set; } + } + + public interface IShardingConfigOption: IShardingConfigOption where TShardingDbContext : DbContext, IShardingDbContext + { + } } diff --git a/src/ShardingCore/IShardingDbContextCreatorConfig.cs b/src/ShardingCore/IShardingDbContextCreatorConfig.cs index 54ec6be2..707bd8bc 100644 --- a/src/ShardingCore/IShardingDbContextCreatorConfig.cs +++ b/src/ShardingCore/IShardingDbContextCreatorConfig.cs @@ -20,6 +20,5 @@ namespace ShardingCore Type ActualDbContextType { get; } DbContext Creator(ShardingDbContextOptions shardingDbContextOptions); - } } diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index 96ea017b..4d8e5eeb 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -45,16 +45,14 @@ namespace ShardingCore.Sharding public AbstractShardingDbContext(DbContextOptions options) : base(options) { - ShardingDbContextType = this.GetType(); ActualDbContextType = typeof(TDbContext); _shardingDbContextExecutor = (IShardingDbContextExecutor)Activator.CreateInstance( - typeof(ShardingDbContextExecutor<,>).GetGenericType1(ShardingDbContextType, ActualDbContextType)); + typeof(ShardingDbContextExecutor<,>).GetGenericType1(this.GetType(), ActualDbContextType)); } - public Type ShardingDbContextType { get; } public Type ActualDbContextType { get; } /// /// 读写分离优先级 diff --git a/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs b/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs index 3b837697..25eac021 100644 --- a/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs @@ -13,11 +13,8 @@ namespace ShardingCore.Sharding.Abstractions * @Ver: 1.0 * @Email: 326308290@qq.com */ - public interface IConnectionStringManager + public interface IConnectionStringManager where TShardingDbContext:DbContext,IShardingDbContext { string GetConnectionString(string dataSourceName); } - public interface IConnectionStringManager: IConnectionStringManager where TShardingDbContext:DbContext,IShardingDbContext - { - } } diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs index a4c68fe3..b9831746 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs @@ -16,10 +16,6 @@ namespace ShardingCore.Sharding.Abstractions */ public interface IShardingDbContext { - /// - /// 当前sharding的db context type - /// - Type ShardingDbContextType { get; } /// /// 真实的db context type /// diff --git a/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs b/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs index 4c2db7bb..d51cc938 100644 --- a/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs +++ b/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs @@ -1,16 +1,21 @@ using System.Linq; using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; namespace ShardingCore.Sharding.Abstractions { -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 28 January 2021 16:51:41 -* @Email: 326308290@qq.com -*/ - public interface IStreamMergeContextFactory + /* + * @Author: xjm + * @Description: + * @Date: Thursday, 28 January 2021 16:51:41 + * @Email: 326308290@qq.com + */ + public interface IStreamMergeContextFactory { StreamMergeContext Create(IQueryable queryable, IShardingDbContext shardingDbContext); } + + public interface IStreamMergeContextFactory : IStreamMergeContextFactory where TShardingDbContext:DbContext,IShardingDbContext + { + } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/ActualConnectionStringManager.cs b/src/ShardingCore/Sharding/ActualConnectionStringManager.cs index 71a1a67b..72bbf6a2 100644 --- a/src/ShardingCore/Sharding/ActualConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/ActualConnectionStringManager.cs @@ -18,17 +18,17 @@ namespace ShardingCore.Sharding */ public class ActualConnectionStringManager where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IConnectionStringManager _connectionStringManager; + private readonly IConnectionStringManager _connectionStringManager; private readonly IReadWriteOptions _readWriteOptions; private readonly bool _useReadWriteSeparation; private readonly IShardingReadWriteManager _shardingReadWriteManager; - private readonly IVirtualDataSource _virtualDataSource; + private readonly IVirtualDataSource _virtualDataSource; public int ReadWriteSeparationPriority { get; set; } public bool ReadWriteSeparation { get; set; } private string _cacheConnectionString; public ActualConnectionStringManager() { - _virtualDataSource=ShardingContainer.GetService>().GetVirtualDataSource(); + _virtualDataSource=ShardingContainer.GetService>(); _connectionStringManager = ShardingContainer.GetService>(); _readWriteOptions = ShardingContainer.GetService>(); _shardingReadWriteManager = ShardingContainer.GetService(); diff --git a/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs b/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs index c479b03e..0b439623 100644 --- a/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs @@ -13,11 +13,11 @@ namespace ShardingCore.Sharding */ public class DefaultConnectionStringManager : IConnectionStringManager where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IVirtualDataSource _virtualDataSource; + private readonly IVirtualDataSource _virtualDataSource; - public DefaultConnectionStringManager(IVirtualDataSourceManager virtualDataSourceManager) + public DefaultConnectionStringManager(IVirtualDataSource virtualDataSource) { - _virtualDataSource = virtualDataSourceManager.GetVirtualDataSource(); + _virtualDataSource = virtualDataSource; } public string GetConnectionString(string dataSourceName) { diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/RandomShardingConnectionStringResolver.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/RandomShardingConnectionStringResolver.cs index ff586cd3..1ca3c341 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/RandomShardingConnectionStringResolver.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/RandomShardingConnectionStringResolver.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; @@ -16,22 +17,26 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class RandomShardingConnectionStringResolver :IShardingConnectionStringResolver + public class RandomShardingConnectionStringResolver : IShardingConnectionStringResolver where TShardingDbContext : DbContext, IShardingDbContext { - public Type ShardingDbContextType => typeof(TShardingDbContext); - - private readonly string[] _connectionStrings; - private readonly int _length; - public RandomShardingConnectionStringResolver(IEnumerable connectionStrings) + private readonly ConcurrentDictionary _connectors = + new ConcurrentDictionary(); + public RandomShardingConnectionStringResolver(IEnumerable connectors) { - _connectionStrings = connectionStrings.ToArray(); - _length = _connectionStrings.Length; + var enumerator = connectors.GetEnumerator(); + while (enumerator.MoveNext()) + { + var currentConnector = enumerator.Current; + if (currentConnector != null) + _connectors.TryAdd(currentConnector.DataSourceName, currentConnector); + } } - public string GetConnectionString() - { - var next = RandomHelper.Next(0, _length); - return _connectionStrings[next]; + public string GetConnectionString(string dataSourceName) + { + if (!_connectors.TryGetValue(dataSourceName, out var connector)) + throw new InvalidOperationException($"read write connector not found, data source name:[{dataSourceName}]"); + return connector.GetConnectionString(); } } } diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteRandomConnector.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteRandomConnector.cs new file mode 100644 index 00000000..68b84a6a --- /dev/null +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteRandomConnector.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ShardingCore.Helpers; + +namespace ShardingCore.Sharding.ReadWriteConfigurations +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/18 20:58:42 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ReadWriteRandomConnector + { + private readonly string[] _connectionStrings; + private readonly int _length; + public ReadWriteRandomConnector(string dataSourceName,IEnumerable connectionStrings) + { + DataSourceName = dataSourceName; + _connectionStrings = connectionStrings.ToArray(); + _length = _connectionStrings.Length; + } + public string GetConnectionString() + { + var next = RandomHelper.Next(0, _length); + return _connectionStrings[next]; + + } + + public string DataSourceName { get; } + } +} diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ShardingReadWriteManager.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ShardingReadWriteManager.cs index c35a8b71..97d29910 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ShardingReadWriteManager.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ShardingReadWriteManager.cs @@ -21,6 +21,12 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations { private readonly ConcurrentDictionary _shardingReadWriteAccessors; + + public ShardingReadWriteManager(IEnumerable shardingReadWriteAccessors) + { + + _shardingReadWriteAccessors = new ConcurrentDictionary(shardingReadWriteAccessors.ToDictionary(o => o.ShardingDbContextType, o => o)); + } public ShardingReadWriteContext GetCurrent() where TShardingDbContext : DbContext, IShardingDbContext { return GetCurrent(typeof(TShardingDbContext)); @@ -36,12 +42,6 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations throw new InvalidOperationException(shardingDbContextType.FullName); } - public ShardingReadWriteManager(IEnumerable shardingReadWriteAccessors) - { - - _shardingReadWriteAccessors = new ConcurrentDictionary(shardingReadWriteAccessors.ToDictionary(o => o.ShardingDbContextType, o => o)); - } - public ShardingReadWriteScope CreateScope() where TShardingDbContext : DbContext, IShardingDbContext { var shardingPageScope = new ShardingReadWriteScope(_shardingReadWriteAccessors.Values); diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutor.cs index b8634d77..82043e4f 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutor.cs @@ -1,14 +1,4 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using ShardingCore.Core; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes.TableRoutes; @@ -18,9 +8,15 @@ using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.ReadWriteConfigurations; -using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; using ShardingCore.Sharding.ShardingTransactions; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; namespace ShardingCore.Sharding { @@ -39,9 +35,9 @@ namespace ShardingCore.Sharding { private readonly ConcurrentDictionary> _dbContextCaches = new ConcurrentDictionary>(); public IShardingTransaction CurrentShardingTransaction { get; private set; } - private readonly IVirtualDataSourceManager _virtualDataSourceManager; + private readonly IVirtualDataSource _virtualDataSource; private readonly IVirtualTableManager _virtualTableManager; - private readonly IShardingDbContextFactory _shardingDbContextFactory; + private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig; private readonly IRouteTailFactory _routeTailFactory; @@ -63,7 +59,7 @@ namespace ShardingCore.Sharding public ShardingDbContextExecutor() { - _virtualDataSourceManager = ShardingContainer.GetService>(); + _virtualDataSource = ShardingContainer.GetService>(); _virtualTableManager = ShardingContainer.GetService>(); _shardingDbContextFactory = ShardingContainer.GetService>(); _shardingDbContextOptionsBuilderConfig = ShardingContainer.GetService>(); @@ -157,7 +153,7 @@ namespace ShardingCore.Sharding public DbContext CreateGenericDbContext(TEntity entity) where TEntity : class { - var dataSourceName = _virtualDataSourceManager.GetDataSourceName(entity); + var dataSourceName = _virtualDataSource.GetDataSourceName(entity); var tail = _virtualTableManager.GetTableTail(entity); return CreateDbContext(true, dataSourceName, _routeTailFactory.Create(tail)); @@ -167,7 +163,7 @@ namespace ShardingCore.Sharding public IEnumerable CreateExpressionDbContext(Expression> @where) where TEntity : class { - var dataSourceNames = _virtualDataSourceManager.GetDataSourceNames(where); + var dataSourceNames = _virtualDataSource.GetDataSourceNames(where); if (typeof(TEntity).IsShardingTable()) { diff --git a/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs b/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs index 535a5e94..2f5e515d 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfig.cs @@ -14,7 +14,7 @@ namespace ShardingCore.Sharding * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class ShardingDbContextOptionsBuilderConfig : IShardingDbContextOptionsBuilderConfig where TShardingDbContext : DbContext, IShardingDbContext + public class ShardingDbContextOptionsBuilderConfig : IShardingDbContextOptionsBuilderConfig where TShardingDbContext : DbContext, IShardingDbContext { public ShardingDbContextOptionsBuilderConfig(Action sameConnectionDbContextOptionsCreator, Action defaultQueryDbContextOptionsCreator) { diff --git a/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs b/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs index 7332a081..556910bb 100644 --- a/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs @@ -24,12 +24,7 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors */ public class DefaultShardingQueryExecutor : IShardingQueryExecutor { - private readonly IStreamMergeContextFactory _streamMergeContextFactory; - public DefaultShardingQueryExecutor(IStreamMergeContextFactory streamMergeContextFactory) - { - _streamMergeContextFactory = streamMergeContextFactory; - } public TResult Execute(ICurrentDbContext currentContext, Expression query) { var currentDbContext = currentContext.Context; @@ -129,10 +124,15 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors type = type.MakeGenericType(queryEntityType); var queryable = Activator.CreateInstance(type, query); - var streamMergeContextMethod = _streamMergeContextFactory.GetType().GetMethod("Create"); + var streamMergeContextFactory = (IStreamMergeContextFactory)ShardingContainer.GetService(typeof(IStreamMergeContextFactory<>).GetGenericType0(shardingDbContext.GetType())); + + // private readonly IStreamMergeContextFactory _streamMergeContextFactory; + + + var streamMergeContextMethod = streamMergeContextFactory.GetType().GetMethod("Create"); if (streamMergeContextMethod == null) throw new ShardingCoreException("cant found IStreamMergeContextFactory method [Create]"); - var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(_streamMergeContextFactory, new[] { queryable, shardingDbContext }); + var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamMergeContextFactory, new[] { queryable, shardingDbContext }); Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<>); diff --git a/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs b/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs index 508b3a10..9352b7b7 100644 --- a/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs @@ -35,7 +35,7 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors { _streamMergeContext = streamMergeContext; _shardingPageManager = ShardingContainer.GetService(); - _virtualTableManager = ShardingContainer.GetService(); + _virtualTableManager = streamMergeContext.GetVirtualTableManager(); } public IEnumeratorStreamMergeEngine ExecuteAsync(CancellationToken cancellationToken = new CancellationToken()) @@ -50,8 +50,8 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSingleShardingTableQuery() && _shardingPageManager.Current != null) { //获取虚拟表判断是否启用了分页配置 - var shardingEntityType = _streamMergeContext.RouteResults.First().ReplaceTables.First().EntityType; - var virtualTable = _virtualTableManager.GetVirtualTable(_streamMergeContext.GetShardingDbContext().ShardingDbContextType, shardingEntityType); + var shardingEntityType = _streamMergeContext.TableRouteResults.First().ReplaceTables.First().EntityType; + var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType); if (virtualTable.EnablePagination) { var paginationMetadata = virtualTable.PaginationMetadata; diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index 08780212..441d2667 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -7,8 +7,10 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Sharding.Abstractions; using System.Collections.Generic; using System.Linq; +using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; +using ShardingCore.Extensions; namespace ShardingCore.Sharding @@ -24,8 +26,6 @@ namespace ShardingCore.Sharding //private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IQueryable _source; private readonly IShardingDbContext _shardingDbContext; - private readonly IDataSourceRouteRuleEngineFactory _dataSourceRouteRuleEngineFactory; - private readonly ITableRouteRuleEngineFactory _tableTableRouteRuleEngineFactory; private readonly IRouteTailFactory _routeTailFactory; private readonly IQueryable _reWriteSource; @@ -40,13 +40,14 @@ namespace ShardingCore.Sharding public IEnumerable TableRouteResults { get; } public DataSourceRouteResult DataSourceRouteResult { get; } - public StreamMergeContext(IQueryable source,IShardingDbContext shardingDbContext, IDataSourceRouteRuleEngineFactory dataSourceRouteRuleEngineFactory, ITableRouteRuleEngineFactory tableTableRouteRuleEngineFactory, IRouteTailFactory routeTailFactory) + public StreamMergeContext(IQueryable source,IShardingDbContext shardingDbContext, + DataSourceRouteResult dataSourceRouteResult, + IEnumerable tableRouteResults, + IRouteTailFactory routeTailFactory) { //_shardingScopeFactory = shardingScopeFactory; _source = source; _shardingDbContext = shardingDbContext; - _dataSourceRouteRuleEngineFactory = dataSourceRouteRuleEngineFactory; - _tableTableRouteRuleEngineFactory = tableTableRouteRuleEngineFactory; _routeTailFactory = routeTailFactory; var reWriteResult = new ReWriteEngine(source).ReWrite(); Skip = reWriteResult.Skip; @@ -55,9 +56,8 @@ namespace ShardingCore.Sharding SelectContext = reWriteResult.SelectContext; GroupByContext = reWriteResult.GroupByContext; _reWriteSource = reWriteResult.ReWriteQueryable; - DataSourceRouteResult = - dataSourceRouteRuleEngineFactory.Route(_shardingDbContext.ShardingDbContextType, _source); - TableRouteResults= _tableTableRouteRuleEngineFactory.Route(_shardingDbContext.ShardingDbContextType, _source); + DataSourceRouteResult = dataSourceRouteResult; + TableRouteResults= tableRouteResults; //RouteResults = _tableTableRouteRuleEngineFactory.Route(_shardingDbContext.ShardingDbContextType, _source); } //public StreamMergeContext(IQueryable source,IEnumerable routeResults, @@ -135,5 +135,6 @@ namespace ShardingCore.Sharding { return _shardingDbContext; } + } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeContextFactory.cs b/src/ShardingCore/Sharding/StreamMergeContextFactory.cs index ef107d88..68c2216a 100644 --- a/src/ShardingCore/Sharding/StreamMergeContextFactory.cs +++ b/src/ShardingCore/Sharding/StreamMergeContextFactory.cs @@ -1,6 +1,7 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Sharding.Abstractions; using System.Linq; +using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; @@ -12,14 +13,14 @@ namespace ShardingCore.Sharding * @Date: Thursday, 28 January 2021 16:52:43 * @Email: 326308290@qq.com */ - public class StreamMergeContextFactory:IStreamMergeContextFactory + public class StreamMergeContextFactory : IStreamMergeContextFactory where TShardingDbContext:DbContext,IShardingDbContext { - private readonly IDataSourceRouteRuleEngineFactory _dataSourceRouteRuleEngineFactory; - private readonly ITableRouteRuleEngineFactory _tableRouteRuleEngineFactory; + private readonly IDataSourceRouteRuleEngineFactory _dataSourceRouteRuleEngineFactory; + private readonly ITableRouteRuleEngineFactory _tableRouteRuleEngineFactory; private readonly IRouteTailFactory _routeTailFactory; - public StreamMergeContextFactory(IDataSourceRouteRuleEngineFactory dataSourceRouteRuleEngineFactory, - ITableRouteRuleEngineFactory tableRouteRuleEngineFactory,IRouteTailFactory routeTailFactory) + public StreamMergeContextFactory(IDataSourceRouteRuleEngineFactory dataSourceRouteRuleEngineFactory, + ITableRouteRuleEngineFactory tableRouteRuleEngineFactory,IRouteTailFactory routeTailFactory) { _dataSourceRouteRuleEngineFactory = dataSourceRouteRuleEngineFactory; _tableRouteRuleEngineFactory = tableRouteRuleEngineFactory; @@ -27,7 +28,9 @@ namespace ShardingCore.Sharding } public StreamMergeContext Create(IQueryable queryable,IShardingDbContext shardingDbContext) { - return new StreamMergeContext(queryable,shardingDbContext, _dataSourceRouteRuleEngineFactory, _tableRouteRuleEngineFactory, _routeTailFactory); + var dataSourceRouteResult = _dataSourceRouteRuleEngineFactory.Route(queryable); + var tableRouteResults = _tableRouteRuleEngineFactory.Route(queryable); + return new StreamMergeContext(queryable,shardingDbContext, dataSourceRouteResult, tableRouteResults, _routeTailFactory); } } } \ 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 6d67c647..29a1e555 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs @@ -57,7 +57,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions } - _mergeContext = ShardingContainer.GetService().Create(_queryable, shardingDbContext); + _mergeContext = ((IStreamMergeContextFactory)ShardingContainer.GetService(typeof(IStreamMergeContextFactory<>).GetGenericType0(shardingDbContext.GetType()))).Create(_queryable, shardingDbContext); _parllelDbbContexts = new List(); } /// diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs index 3c4bb562..15ef8d4d 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs @@ -38,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines { foreach (var routeQueryResult in result) { - _shardingPageManager.Current.RouteQueryResults.Add(new RouteQueryResult(routeQueryResult.TableRouteResult, routeQueryResult.QueryResult)); + _shardingPageManager.Current.RouteQueryResults.Add(new RouteQueryResult(routeQueryResult.DataSourceName, routeQueryResult.TableRouteResult, routeQueryResult.QueryResult)); } } return result.Sum(o=>o.QueryResult); diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs index f678a897..aacee0bf 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs @@ -95,7 +95,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. { Skip = (int)skip; Take = (int)take; - DSName = routeQueryResult.DSName; + DSName = routeQueryResult.DataSourceName; TableRouteResult = routeQueryResult.TableRouteResult; } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs index c5bcb8b4..d778d083 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs @@ -25,13 +25,12 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. public override IStreamMergeAsyncEnumerator[] GetDbStreamMergeAsyncEnumerators(bool async) { var dataSourceRouteResult = StreamMergeContext.DataSourceRouteResult; - var enumeratorTasks = dataSourceRouteResult.IntersectDataSources.SelectMany(physicDataSource => + var enumeratorTasks = dataSourceRouteResult.IntersectDataSources.SelectMany(dataSourceName => { - var dsname = physicDataSource.DataSourceName; - var tableRouteResults = StreamMergeContext.GetTableRouteResults(dsname); + var tableRouteResults = StreamMergeContext.TableRouteResults; return tableRouteResults.Select(routeResult => { - var newQueryable = CreateAsyncExecuteQueryable(dsname,routeResult); + var newQueryable = CreateAsyncExecuteQueryable(dataSourceName, routeResult); return AsyncQueryEnumerator(newQueryable, async); }); diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs index 66f09821..91cac6ea 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs @@ -42,12 +42,11 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. var reverseOrderQueryable = noPaginationNoOrderQueryable.Take((int)realSkip+(int)take).OrderWithExpression(propertyOrders); var dataSourceRouteResult = StreamMergeContext.DataSourceRouteResult; - var enumeratorTasks = dataSourceRouteResult.IntersectDataSources.SelectMany(physicDataSource => + var enumeratorTasks = dataSourceRouteResult.IntersectDataSources.SelectMany(dataSourceName => { - var dsname = physicDataSource.DataSourceName; - return StreamMergeContext.GetTableRouteResults(dsname).Select(routeResult => + return StreamMergeContext.TableRouteResults.Select(routeResult => { - var newQueryable = CreateAsyncExecuteQueryable(dsname,reverseOrderQueryable, routeResult); + var newQueryable = CreateAsyncExecuteQueryable(dataSourceName, reverseOrderQueryable, routeResult); return AsyncQueryEnumerator(newQueryable, async); }); }).ToArray();; diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs index 35fb340c..79718058 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs @@ -20,9 +20,9 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. public override IStreamMergeAsyncEnumerator[] GetDbStreamMergeAsyncEnumerators(bool async) { - var physicDataSource = StreamMergeContext.DataSourceRouteResult.IntersectDataSources.First(); - var routeResult = StreamMergeContext.GetTableRouteResults(physicDataSource.DataSourceName).First(); - var shardingDbContext = StreamMergeContext.CreateDbContext(physicDataSource.DataSourceName,routeResult); + var dataSourceName = StreamMergeContext.DataSourceRouteResult.IntersectDataSources.First(); + var routeResult = StreamMergeContext.TableRouteResults.First(); + var shardingDbContext = StreamMergeContext.CreateDbContext(dataSourceName, routeResult); DbContextQueryStore.TryAdd(routeResult, shardingDbContext); var newQueryable = (IQueryable) StreamMergeContext.GetOriginalQueryable().ReplaceDbContextQueryable(shardingDbContext); if (async) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs b/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs index 878f0ee1..65468c43 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs @@ -14,13 +14,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines */ public class RouteQueryResult { - public string DSName { get; } + public string DataSourceName { get; } public TableRouteResult TableRouteResult { get; } public TResult QueryResult { get; } - public RouteQueryResult(string dsname,TableRouteResult tableRouteResult,TResult queryResult) + public RouteQueryResult(string dataSourceName,TableRouteResult tableRouteResult,TResult queryResult) { - DSName = dsname; + DataSourceName = dataSourceName; TableRouteResult = tableRouteResult; QueryResult = queryResult; } diff --git a/src/ShardingCore/ShardingBootstrapper.cs b/src/ShardingCore/ShardingBootstrapper.cs index f8e8e23c..a31eb97d 100644 --- a/src/ShardingCore/ShardingBootstrapper.cs +++ b/src/ShardingCore/ShardingBootstrapper.cs @@ -27,150 +27,22 @@ namespace ShardingCore */ public class ShardingBootstrapper : IShardingBootstrapper { - private readonly IServiceProvider _serviceProvider; private readonly IEnumerable _shardingConfigOptions; - private readonly IVirtualTableManager _virtualTableManager; - private readonly IShardingTableCreator _tableCreator; - private readonly ILogger _logger; - private readonly IRouteTailFactory _routeTailFactory; - private readonly IShardingDbContextFactory _shardingDbContextFactory; - public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable shardingConfigOptions, - IVirtualTableManager virtualTableManager - , IShardingTableCreator tableCreator, ILogger logger, - IShardingDbContextFactory shardingDbContextFactory,IRouteTailFactory routeTailFactory) + public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable shardingConfigOptions) { ShardingContainer.SetServices(serviceProvider); - _serviceProvider = serviceProvider; _shardingConfigOptions = shardingConfigOptions; - _virtualTableManager = virtualTableManager; - _tableCreator = tableCreator; - _logger = logger; - _routeTailFactory = routeTailFactory; - _shardingDbContextFactory = shardingDbContextFactory; } public void Start() { - - - using (var scope = _serviceProvider.CreateScope()) + foreach (var shardingConfigOption in _shardingConfigOptions) { - foreach (var shardingConfigOption in _shardingConfigOptions) - { - 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的实际表名 - var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName(); - virtualTable.SetOriginalTableName(tableName); - _virtualTableManager.AddVirtualTable(shardingConfigOption.ShardingDbContextType,virtualTable); - CreateDataTable(shardingConfigOption.ShardingDbContextType,virtualTable, shardingConfigOption); - } - } - - } + var instance = (IShardingDbContextBootstrapper)Activator.CreateInstance(typeof(ShardingDbContextBootstrapper<>).GetGenericType0(shardingConfigOption.ShardingDbContextType), shardingConfigOption); + instance.Initialize(); } } - - private IVirtualTableRoute CreateVirtualRoute(Type virtualRouteType) - { - var constructors - = virtualRouteType.GetTypeInfo().DeclaredConstructors - .Where(c => !c.IsStatic && c.IsPublic) - .ToArray(); - if (constructors.IsEmpty()) - { - object o = Activator.CreateInstance(virtualRouteType); - return (IVirtualTableRoute) o; - } - else - { - if (constructors.Length > 1) - { - throw new ArgumentException( - $"virtual route :[{virtualRouteType}] found more declared constructor "); - } - - var @params = constructors[0].GetParameters().Select(x => _serviceProvider.GetService(x.ParameterType)) - .ToArray(); - object o = Activator.CreateInstance(virtualRouteType, @params); - return (IVirtualTableRoute) o; - } - } - - private IVirtualTable CreateVirtualTable(Type entityType, IVirtualTableRoute virtualTableRoute) - { - Type type = typeof(DefaultVirtualTable<>); - type = type.MakeGenericType(entityType); - object o = Activator.CreateInstance(type, virtualTableRoute); - return (IVirtualTable) o; - } - - private void EnsureCreated(DbContext context) - { - if (context is IShardingDbContext shardingDbContext) - { - var dbContext = shardingDbContext.GetDbContext(false,_routeTailFactory.Create(string.Empty)); - var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); - - lock (modelCacheSyncObject) - { - dbContext.RemoveDbContextRelationModelThatIsShardingTable(); - dbContext.Database.EnsureCreated(); - dbContext.RemoveModelCache(); - } - } - } - - private bool NeedCreateTable(ShardingTableConfig config, IShardingConfigOption shardingConfigOption) - { - if (config.AutoCreateTable.HasValue) - { - return config.AutoCreateTable.Value; - } - - return shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault(); - } - - private void CreateDataTable(Type shardingDbContextType,IVirtualTable virtualTable,IShardingConfigOption shardingConfigOption) - { - var shardingConfig = virtualTable.ShardingConfig; - foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails()) - { - if (NeedCreateTable(shardingConfig, shardingConfigOption)) - { - try - { - //添加物理表 - virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); - _tableCreator.CreateTable(shardingDbContextType,virtualTable.EntityType, tail); - } - catch (Exception e) - { - if (!shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) - { - _logger.LogWarning( - $"table :{virtualTable.GetVirtualTableName()}{shardingConfig.TailPrefix}{tail} will created.",e); - } - } - } - else - { - //添加物理表 - virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); - } - - } - } } } \ No newline at end of file diff --git a/src/ShardingCore/ShardingConfigOption.cs b/src/ShardingCore/ShardingConfigOption.cs index bd1a03b4..1875e024 100644 --- a/src/ShardingCore/ShardingConfigOption.cs +++ b/src/ShardingCore/ShardingConfigOption.cs @@ -1,15 +1,14 @@ -using System; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ReadWriteConfigurations; +using System; +using System.Collections.Concurrent; 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; -using ShardingCore.Sharding.ReadWriteConfigurations; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Extensions; namespace ShardingCore { @@ -20,28 +19,46 @@ namespace ShardingCore * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class ShardingConfigOption : IShardingConfigOption - where TActualDbContext : DbContext, IShardingTableDbContext - where TShardingDbContext : DbContext, IShardingDbContext + public class ShardingConfigOption : IShardingConfigOption + where TShardingDbContext : DbContext, IShardingDbContext { - private readonly Dictionary _virtualRoutes = new Dictionary(); + private readonly Dictionary _virtualDataSourceRoutes = new Dictionary(); + private readonly Dictionary _virtualTableRoutes = new Dictionary(); - public Action SameConnectionConfigure { get;private set; } - public Action DefaultQueryConfigure { get; private set; } - /// - /// 配置数据库分表查询和保存时的DbContext创建方式 - /// - /// DbConnection下如何配置因为不同的DbContext支持事务需要使用同一个DbConnection - /// 默认查询DbContext创建的配置 + public Action SameConnectionConfigure { get; private set; } + public Action DefaultQueryConfigure { get; private set; } - public void UseShardingOptionsBuilder(Action sameConnectionConfigure, Action defaultQueryConfigure = null) + public Func> DataSourcesConfigure { get; private set; } + + public void UseShardingQuery(Action queryConfigure) { - SameConnectionConfigure = sameConnectionConfigure ?? throw new ArgumentNullException(nameof(sameConnectionConfigure)); - DefaultQueryConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure)); + DefaultQueryConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure)); + } + public void UseShardingTransaction(Action transactionConfigure) + { + SameConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure)); } + public void AddShardingDataSource(Func> dataSourcesConfigure) + { + DataSourcesConfigure = dataSourcesConfigure ?? throw new ArgumentNullException(nameof(dataSourcesConfigure)); + } + + + ///// + ///// 配置数据库分表查询和保存时的DbContext创建方式 + ///// + ///// DbConnection下如何配置因为不同的DbContext支持事务需要使用同一个DbConnection + ///// 默认查询DbContext创建的配置 + + //public void UseShardingOptionsBuilder(Action sameConnectionConfigure, Action defaultQueryConfigure = null) + //{ + // SameConnectionConfigure = sameConnectionConfigure ?? throw new ArgumentNullException(nameof(sameConnectionConfigure)); + // DefaultQueryConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure)); + //} + public bool UseReadWrite => ReadConnStringConfigure != null; - public Func> ReadConnStringConfigure { get; private set; } + public Func>> ReadConnStringConfigure { get; private set; } public ReadStrategyEnum ReadStrategyEnum { get; private set; } public bool ReadWriteDefaultEnable { get; private set; } public int ReadWriteDefaultPriority { get; private set; } @@ -55,7 +72,7 @@ namespace ShardingCore /// 考虑到很多时候读写分离的延迟需要马上用到写入的数据所以默认关闭需要的话自己开启或者通过IShardingReadWriteManager,false表示默认不走读写分离除非你自己开启,true表示默认走读写分离除非你禁用, /// IShardingReadWriteManager.CreateScope()会判断dbcontext的priority然后判断是否启用readwrite /// 读写分离可能会造成每次查询不一样甚至分表后的分页会有错位问题,因为他不是一个原子操作,所以如果整个请求为一次读写切换大多数更加合适 - public void UseReadWriteConfiguration(Func> readConnStringConfigure, ReadStrategyEnum readStrategyEnum,bool defaultEnable=false,int defaultPriority=10,ReadConnStringGetStrategyEnum readConnStringGetStrategy= ReadConnStringGetStrategyEnum.LatestFirstTime) + public void UseReadWriteConfiguration(Func>> readConnStringConfigure, ReadStrategyEnum readStrategyEnum, bool defaultEnable = false, int defaultPriority = 10, ReadConnStringGetStrategyEnum readConnStringGetStrategy = ReadConnStringGetStrategyEnum.LatestFirstTime) { ReadConnStringConfigure = readConnStringConfigure ?? throw new ArgumentNullException(nameof(readConnStringConfigure)); ReadStrategyEnum = readStrategyEnum; @@ -66,8 +83,34 @@ namespace ShardingCore public Type ShardingDbContextType => typeof(TShardingDbContext); - public Type ActualDbContextType => typeof(TActualDbContext); + /// + /// 添加分表路由 + /// + /// + public void AddShardingDataSourceRoute() where TRoute : IVirtualDataSourceRoute + { + var routeType = typeof(TRoute); + AddShardingDataSourceRoute(routeType); + } + public void AddShardingDataSourceRoute(Type routeType) + { + if (!routeType.IsVirtualDataSourceRoute()) + throw new InvalidOperationException(routeType.FullName); + //获取类型 + var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualDataSourceRoute<>) + && it.GetGenericArguments().Any()); + if (genericVirtualRoute == null) + throw new ArgumentException("add sharding route type error not assignable from IVirtualDataSourceRoute<>."); + + var shardingEntityType = genericVirtualRoute.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IVirtualDataSourceRoute<>"); + if (!_virtualDataSourceRoutes.ContainsKey(shardingEntityType)) + { + _virtualDataSourceRoutes.Add(shardingEntityType, routeType); + } + } /// /// 添加分表路由 /// @@ -75,6 +118,12 @@ namespace ShardingCore public void AddShardingTableRoute() where TRoute : IVirtualTableRoute { var routeType = typeof(TRoute); + AddShardingTableRoute(routeType); + } + public void AddShardingTableRoute(Type routeType) + { + if (!routeType.IsIVirtualTableRoute()) + throw new InvalidOperationException(routeType.FullName); //获取类型 var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualTableRoute<>) && it.GetGenericArguments().Any()); @@ -84,17 +133,29 @@ namespace ShardingCore 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)) + if (!_virtualTableRoutes.ContainsKey(shardingEntityType)) { - _virtualRoutes.Add(shardingEntityType, routeType); + _virtualTableRoutes.Add(shardingEntityType, routeType); } } - public Type GetVirtualRouteType(Type entityType) + public Type GetVirtualTableRouteType(Type entityType) { - if (!_virtualRoutes.ContainsKey(entityType)) + if (!_virtualTableRoutes.ContainsKey(entityType)) throw new ArgumentException($"{entityType} not found IVirtualTableRoute"); - return _virtualRoutes[entityType]; + return _virtualTableRoutes[entityType]; + } + public Type GetVirtualDataSourceRouteType(Type entityType) + { + if (!_virtualDataSourceRoutes.ContainsKey(entityType)) + throw new ArgumentException($"{entityType} not found IVirtualDataSourceRoute"); + return _virtualDataSourceRoutes[entityType]; + } + + public IDictionary GetDataSources() + { + var defaultDataSources = new Dictionary(){{DefaultDataSourceName,DefaultConnectionString}}; + return defaultDataSources.Concat(DataSourcesConfigure?.Invoke(ShardingContainer.Services)??new Dictionary()).ToDictionary(o=>o.Key,o=>o.Value); } @@ -113,5 +174,7 @@ namespace ShardingCore /// public bool? IgnoreCreateTableError { get; set; } + public string DefaultDataSourceName { get; set; } + public string DefaultConnectionString { get; set; } } } \ No newline at end of file diff --git a/src/ShardingCore/ShardingContainer.cs b/src/ShardingCore/ShardingContainer.cs index 446cc1e8..20297d3e 100644 --- a/src/ShardingCore/ShardingContainer.cs +++ b/src/ShardingCore/ShardingContainer.cs @@ -1,5 +1,11 @@ using System; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using ShardingCore.Core.VirtualDatabase.VirtualTables; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine; +using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore { @@ -33,15 +39,6 @@ namespace ShardingCore { return Services.GetService(serviceType); } - public static object GetGenericTypeService0(Type genericServiceType,Type genericArg0Type) - { - var serviceType = genericServiceType.MakeGenericType(genericArg0Type); - return GetService(serviceType); - } - public static object GetGenericTypeService1(Type genericServiceType, Type genericArg0Type, Type genericArg1Type) - { - var serviceType = genericServiceType.MakeGenericType(genericArg0Type, genericArg1Type); - return GetService(serviceType); - } + } } \ No newline at end of file diff --git a/src/ShardingCore/ShardingCore.csproj b/src/ShardingCore/ShardingCore.csproj index ee8ab93e..db14c741 100644 --- a/src/ShardingCore/ShardingCore.csproj +++ b/src/ShardingCore/ShardingCore.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 $(EFCORE5) diff --git a/src/ShardingCore/ShardingDbContextBootstrapper.cs b/src/ShardingCore/ShardingDbContextBootstrapper.cs new file mode 100644 index 00000000..aead7237 --- /dev/null +++ b/src/ShardingCore/ShardingDbContextBootstrapper.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using ShardingCore.Core.PhysicTables; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualTables; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; +using ShardingCore.Core.VirtualTables; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.TableCreator; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/9/20 14:04:55 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public interface IShardingDbContextBootstrapper + { + void Initialize(); + } + + public class ShardingDbContextBootstrapper: IShardingDbContextBootstrapper where TShardingDbContext:DbContext,IShardingDbContext + { + private readonly IShardingConfigOption _shardingConfigOption; + private readonly IRouteTailFactory _routeTailFactory; + private readonly IVirtualTableManager _virtualTableManager; + private readonly IShardingTableCreator _tableCreator; + private readonly ILogger> _logger; + + public ShardingDbContextBootstrapper(IShardingConfigOption shardingConfigOption) + { + _shardingConfigOption = shardingConfigOption; + _routeTailFactory = ShardingContainer.GetService(); + _virtualTableManager = ShardingContainer.GetService>(); + _tableCreator=ShardingContainer.GetService>(); + _logger = ShardingContainer.GetService>>(); + } + public void Initialize() + { + var virtualDataSource = ShardingContainer.GetService>(); + using (var serviceScope = ShardingContainer.Services.CreateScope()) + { + var dataSources = _shardingConfigOption.GetDataSources(); + virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(_shardingConfigOption.DefaultDataSourceName, _shardingConfigOption.DefaultConnectionString,true)); + //foreach (var dataSourceKv in dataSources) + //{ + // virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceKv.Key, + // dataSourceKv.Value, false)); + //} + foreach (var dataSourceKv in dataSources) + { + var dataSourceName = dataSourceKv.Key; + var connectionString = dataSourceKv.Value; + virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, + connectionString, false)); + using var context = + (DbContext)serviceScope.ServiceProvider.GetService(_shardingConfigOption.ShardingDbContextType); + EnsureCreated(context, dataSourceName); + foreach (var entity in context.Model.GetEntityTypes()) + { + var entityType = entity.ClrType; + if (entityType.IsShardingDataSource()) + { + var routeType = _shardingConfigOption.GetVirtualDataSourceRouteType(entityType); + var virtualRoute = CreateVirtualDataSourceRoute(routeType); + virtualDataSource.AddVirtualDataSourceRoute(virtualRoute); + } + if (entityType.IsShardingTable()) + { + var routeType = _shardingConfigOption.GetVirtualTableRouteType(entityType); + var virtualRoute = CreateVirtualTableRoute(routeType); + var virtualTable = CreateVirtualTable(entityType, virtualRoute); + + //获取ShardingEntity的实际表名 + var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName(); + virtualTable.SetOriginalTableName(tableName); + _virtualTableManager.AddVirtualTable(virtualTable); + CreateDataTable(dataSourceName,virtualTable); + } + } + } + } + } + private void EnsureCreated(DbContext context,string dataSourceName) + { + if (context is IShardingDbContext shardingDbContext) + { + var dbContext = shardingDbContext.GetDbContext(dataSourceName,false, _routeTailFactory.Create(string.Empty)); + var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); + + lock (modelCacheSyncObject) + { + dbContext.RemoveDbContextRelationModelThatIsShardingTable(); + dbContext.Database.EnsureCreated(); + dbContext.RemoveModelCache(); + } + } + } + + + + private IVirtualDataSourceRoute CreateVirtualDataSourceRoute(Type virtualRouteType) + { + var constructors + = virtualRouteType.GetTypeInfo().DeclaredConstructors + .Where(c => !c.IsStatic && c.IsPublic) + .ToArray(); + if (constructors.IsEmpty()) + { + object o = Activator.CreateInstance(virtualRouteType); + return (IVirtualDataSourceRoute)o; + } + else + { + if (constructors.Length > 1) + { + throw new ArgumentException( + $"virtual route :[{virtualRouteType}] found more declared constructor "); + } + + var @params = constructors[0].GetParameters().Select(x => ShardingContainer.GetService(x.ParameterType)) + .ToArray(); + object o = Activator.CreateInstance(virtualRouteType, @params); + return (IVirtualDataSourceRoute)o; + } + } + + + + private IVirtualTableRoute CreateVirtualTableRoute(Type virtualRouteType) + { + var constructors + = virtualRouteType.GetTypeInfo().DeclaredConstructors + .Where(c => !c.IsStatic && c.IsPublic) + .ToArray(); + if (constructors.IsEmpty()) + { + object o = Activator.CreateInstance(virtualRouteType); + return (IVirtualTableRoute)o; + } + else + { + if (constructors.Length > 1) + { + throw new ArgumentException( + $"virtual route :[{virtualRouteType}] found more declared constructor "); + } + + var @params = constructors[0].GetParameters().Select(x => ShardingContainer.GetService(x.ParameterType)) + .ToArray(); + object o = Activator.CreateInstance(virtualRouteType, @params); + return (IVirtualTableRoute)o; + } + } + + private IVirtualTable CreateVirtualTable(Type entityType, IVirtualTableRoute virtualTableRoute) + { + Type type = typeof(DefaultVirtualTable<>); + type = type.MakeGenericType(entityType); + object o = Activator.CreateInstance(type, virtualTableRoute); + return (IVirtualTable)o; + } + + private bool NeedCreateTable(ShardingTableConfig config) + { + if (config.AutoCreateTable.HasValue) + { + return config.AutoCreateTable.Value; + } + + return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault(); + } + private void CreateDataTable(string dataSourceName,IVirtualTable virtualTable) + { + var shardingConfig = virtualTable.ShardingConfig; + foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails()) + { + if (NeedCreateTable(shardingConfig)) + { + try + { + //添加物理表 + virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); + _tableCreator.CreateTable(dataSourceName,virtualTable.EntityType, tail); + } + catch (Exception e) + { + if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) + { + _logger.LogWarning( + $"table :{virtualTable.GetVirtualTableName()}{shardingConfig.TailPrefix}{tail} will created.", e); + } + } + } + else + { + //添加物理表 + virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); + } + + } + } + + } +} diff --git a/src/ShardingCore/TableCreator/IShardingTableCreator.cs b/src/ShardingCore/TableCreator/IShardingTableCreator.cs index d7941bef..b0782b20 100644 --- a/src/ShardingCore/TableCreator/IShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/IShardingTableCreator.cs @@ -6,30 +6,29 @@ using ShardingCore.Sharding.Abstractions; namespace ShardingCore.TableCreator { -/* -* @Author: xjm -* @Description: -* @Date: Monday, 21 December 2020 11:22:08 -* @Email: 326308290@qq.com -*/ -/// -/// -/// - public interface IShardingTableCreator + /* + * @Author: xjm + * @Description: + * @Date: Monday, 21 December 2020 11:22:08 + * @Email: 326308290@qq.com + */ + public interface IShardingTableCreator where TShardingDbContext : DbContext, IShardingDbContext { + /// /// 创建表 /// + /// /// /// - void CreateTable(string tail) where T : class, IShardingTable where TShardingDbContext:DbContext,IShardingDbContext; + void CreateTable(string dataSourceName, string tail) where T : class, IShardingTable; /// /// 创建表 /// - /// + /// /// /// /// - void CreateTable(Type shardingDbContextType,Type shardingEntityType,string tail); + void CreateTable(string dataSourceName, 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 b17bfc40..17e36e8e 100644 --- a/src/ShardingCore/TableCreator/ShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/ShardingTableCreator.cs @@ -23,54 +23,47 @@ namespace ShardingCore.TableCreator * @Date: Monday, 21 December 2020 11:23:22 * @Email: 326308290@qq.com */ - public class ShardingTableCreator : IShardingTableCreator + public class ShardingTableCreator : IShardingTableCreator where TShardingDbContext : DbContext, IShardingDbContext { - private readonly ILogger _logger; - private readonly IShardingDbContextFactory _shardingDbContextFactory; - private readonly IVirtualTableManager _virtualTableManager; + private readonly ILogger> _logger; + private readonly IShardingDbContextFactory _shardingDbContextFactory; + private readonly IVirtualTableManager _virtualTableManager; private readonly IServiceProvider _serviceProvider; - private readonly IEnumerable _shardingConfigOptions; + private readonly IShardingConfigOption _shardingConfigOption; private readonly IRouteTailFactory _routeTailFactory; - public ShardingTableCreator(ILogger logger, IShardingDbContextFactory shardingDbContextFactory, - IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable shardingConfigOptions,IRouteTailFactory routeTailFactory) + public ShardingTableCreator(ILogger> logger, IShardingDbContextFactory shardingDbContextFactory, + IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable shardingConfigOptions,IRouteTailFactory routeTailFactory) { _logger = logger; _shardingDbContextFactory = shardingDbContextFactory; _virtualTableManager = virtualTableManager; _serviceProvider = serviceProvider; - _shardingConfigOptions = shardingConfigOptions; + _shardingConfigOption = shardingConfigOptions.FirstOrDefault(o => o.ShardingDbContextType == typeof(TShardingDbContext)) + ??throw new ArgumentNullException(typeof(TShardingDbContext).FullName); _routeTailFactory = routeTailFactory; } - public void CreateTable(string tail) where TShardingDbContext : DbContext, IShardingDbContext where T : class, IShardingTable + public void CreateTable< T>(string dataSourceName, string tail) where T : class, IShardingTable { - CreateTable(typeof(TShardingDbContext),typeof(T), tail); + CreateTable(dataSourceName,typeof(T), tail); } /// /// /// - /// + /// /// /// /// - public void CreateTable(Type shardingDbContextType,Type shardingEntityType, string tail) + public void CreateTable(string dataSourceName,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 virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntityType); - var dbContext = (DbContext)serviceScope.ServiceProvider.GetService(shardingDbContextType); + var virtualTable = _virtualTableManager.GetVirtualTable( shardingEntityType); + var dbContext = serviceScope.ServiceProvider.GetService(); var shardingDbContext = (IShardingDbContext)dbContext; - var context = shardingDbContext.GetDbContext(false,_routeTailFactory.Create(tail)); + var context = shardingDbContext.GetDbContext(dataSourceName,false, _routeTailFactory.Create(tail)); var modelCacheSyncObject = context.GetModelCacheSyncObject(); @@ -84,7 +77,7 @@ namespace ShardingCore.TableCreator } catch (Exception ex) { - if (!shardingConfigOptions.IgnoreCreateTableError.GetValueOrDefault()) + if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) { _logger.LogWarning( $"create table error maybe table:[{virtualTable.GetVirtualTableName()}{virtualTable.ShardingConfig.TailPrefix}{tail}]"); diff --git a/test/ShardingCore.Test50/ShardingDefaultDbContext.cs b/test/ShardingCore.Test50/ShardingDefaultDbContext.cs index 79cd7c3a..f699362c 100644 --- a/test/ShardingCore.Test50/ShardingDefaultDbContext.cs +++ b/test/ShardingCore.Test50/ShardingDefaultDbContext.cs @@ -29,6 +29,5 @@ namespace ShardingCore.Test50 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 24d18235..74b30662 100644 --- a/test/ShardingCore.Test50/Startup.cs +++ b/test/ShardingCore.Test50/Startup.cs @@ -48,16 +48,17 @@ namespace ShardingCore.Test50 // ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) { - services.AddShardingDbContext(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]) - ,op => + services.AddShardingDbContext(o => + o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])) + .Begin(true) + .AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)) + .AddShardingTransaction((connection, builder) =>builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) + .AddDefaultDataSource("ds0",hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]) + .AddShardingTable(op => { - op.EnsureCreatedWithOutShardingTable = true; - op.CreateShardingTableOnStart = true; - op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger), - (conStr,builder)=> builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)); op.AddShardingTableRoute(); op.AddShardingTableRoute(); - }); + }).End(); // services.AddShardingDbContext(o => o.UseMySql(hostBuilderContext.Configuration.GetSection("MySql")["ConnectionString"],new MySqlServerVersion("5.7.15")) // ,op => // {