diff --git a/samples/Sample.SqlServer/DbContexts/DefaultDbContext.cs b/samples/Sample.SqlServer/DbContexts/DefaultDbContext.cs new file mode 100644 index 00000000..c25ddc0b --- /dev/null +++ b/samples/Sample.SqlServer/DbContexts/DefaultDbContext.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace Sample.SqlServer.DbContexts +{ + public class DefaultDbContext: DbContext + { + } +} diff --git a/samples/Sample.SqlServer/Sample.SqlServer.csproj b/samples/Sample.SqlServer/Sample.SqlServer.csproj index b6fabc6c..3b6947b1 100644 --- a/samples/Sample.SqlServer/Sample.SqlServer.csproj +++ b/samples/Sample.SqlServer/Sample.SqlServer.csproj @@ -1,4 +1,4 @@ - + net5.0 diff --git a/samples/Sample.SqlServer/Startup.cs b/samples/Sample.SqlServer/Startup.cs index defadee5..38395afa 100644 --- a/samples/Sample.SqlServer/Startup.cs +++ b/samples/Sample.SqlServer/Startup.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Sample.SqlServer.DbContexts; using Sample.SqlServer.Shardings; using ShardingCore.SqlServer; @@ -21,14 +22,12 @@ namespace Sample.SqlServer services.AddControllers(); services.AddShardingSqlServer(o => { - o.ConnectionString = ""; - o.AddSharding(); - o.UseShardingCoreConfig((provider, config) => + o.AddShardingDbContext("conn1","123", dbConfig => { - //如果是development就判断并且新建数据库如果不存在的话 - config.EnsureCreated = provider.GetService().IsDevelopment(); - config.CreateShardingTableOnStart = true; + dbConfig.AddShardingTableRoute(); }); + //o.AddDataSourceVirtualRoute<>(); + }); } diff --git a/samples/Samples.AutoByDate.SqlServer/Jobs/AutoCreateTableByDay.cs b/samples/Samples.AutoByDate.SqlServer/Jobs/AutoCreateTableByDay.cs index f905c592..fd947bfc 100644 --- a/samples/Samples.AutoByDate.SqlServer/Jobs/AutoCreateTableByDay.cs +++ b/samples/Samples.AutoByDate.SqlServer/Jobs/AutoCreateTableByDay.cs @@ -14,35 +14,35 @@ namespace Samples.AutoByDate.SqlServer.Jobs * @Date: Tuesday, 02 February 2021 17:24:17 * @Email: 326308290@qq.com */ - public class AutoCreateTableByDay : IJob - { - /// - /// 每天中午12点执行,启动的时候执行以下 - /// - /// - /// - [JobRun(Name = "定时创建分表组件",Cron = "0 0 12 * * ?",RunOnceOnStart = true)] + //public class AutoCreateTableByDay : IJob + //{ + // /// + // /// 每天中午12点执行,启动的时候执行以下 + // /// + // /// + // /// + // [JobRun(Name = "定时创建分表组件",Cron = "0 0 12 * * ?",RunOnceOnStart = true)] - public void AutoCreateTable(IVirtualTableManager virtualTableManager, IShardingTableCreator tableCreator) - { - var allVirtualTables = virtualTableManager.GetAllVirtualTables(); - foreach (var virtualTable in allVirtualTables) - { - if (virtualTable.EntityType == typeof(SysUserLogByDay)) - { - var now = DateTime.Now.Date.AddDays(1); - var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now); - try - { - tableCreator.CreateTable(tail); - virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail)); - } - catch (Exception e) - { - //ignore - } - } - } - } - } + // public void AutoCreateTable(IVirtualTableManager virtualTableManager, IShardingTableCreator tableCreator) + // { + // var allVirtualTables = virtualTableManager.GetAllVirtualTables(); + // foreach (var virtualTable in allVirtualTables) + // { + // if (virtualTable.EntityType == typeof(SysUserLogByDay)) + // { + // var now = DateTime.Now.Date.AddDays(1); + // var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now); + // try + // { + // tableCreator.CreateTable(tail); + // virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail)); + // } + // catch (Exception e) + // { + // //ignore + // } + // } + // } + // } + //} } \ No newline at end of file diff --git a/samples/Samples.AutoByDate.SqlServer/Startup.cs b/samples/Samples.AutoByDate.SqlServer/Startup.cs index 067f59ac..33f98f5f 100644 --- a/samples/Samples.AutoByDate.SqlServer/Startup.cs +++ b/samples/Samples.AutoByDate.SqlServer/Startup.cs @@ -31,17 +31,17 @@ namespace Samples.AutoByDate.SqlServer { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Samples.AutoByDate.SqlServer", Version = "v1"}); }); - services.AddShardingSqlServer(o => - { - o.ConnectionString = ""; - o.AddSharding(); - o.UseShardingCoreConfig((provider, config) => - { - //如果是development就判断并且新建数据库如果不存在的话 - config.EnsureCreated = provider.GetService().IsDevelopment(); - config.CreateShardingTableOnStart = true; - }); - }); + //services.AddShardingSqlServer(o => + //{ + // o.ConnectionString = ""; + // o.AddSharding(); + // o.UseShardingCoreConfig((provider, config) => + // { + // //如果是development就判断并且新建数据库如果不存在的话 + // config.EnsureCreated = provider.GetService().IsDevelopment(); + // config.CreateShardingTableOnStart = true; + // }); + //}); services.AddChronusJob(); } diff --git a/src/ShardingCore.MySql/DIExtension.cs b/src/ShardingCore.MySql/DIExtension.cs index 5dba083b..17f86e57 100644 --- a/src/ShardingCore.MySql/DIExtension.cs +++ b/src/ShardingCore.MySql/DIExtension.cs @@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualTables; using ShardingCore.DbContexts; using ShardingCore.DbContexts.VirtualDbContexts; @@ -40,26 +41,10 @@ namespace ShardingCore.MySql services.AddScoped(); services.AddSingleton(); - if (options.HasSharding) - { - foreach (var shardingRoute in options.ShardingRoutes) - { - var genericVirtualRoute = shardingRoute.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualRoute<>) - && it.GetGenericArguments().Any()); - if (genericVirtualRoute == null) - throw new ArgumentException("add sharding route type error not assignable from IVirtualRoute<>."); - var shardingEntity=genericVirtualRoute.GetGenericArguments()[0]; - if(!shardingEntity.IsShardingEntity()) - throw new ArgumentException("add sharding route type error generic arguments first not assignable from IShardingEntity."); - Type genericType = typeof(IVirtualRoute<>); - Type interfaceType = genericType.MakeGenericType(shardingEntity); - services.AddSingleton(interfaceType, shardingRoute); - } - } + services.AddSingleton(sp => { var shardingCoreConfig = new ShardingCoreConfig(); - options.ShardingCoreConfigConfigure?.Invoke(sp,shardingCoreConfig); return shardingCoreConfig; }); services.AddSingleton(); diff --git a/src/ShardingCore.MySql/EFCores/ShardingMySqlQuerySqlGenerator.cs b/src/ShardingCore.MySql/EFCores/ShardingMySqlQuerySqlGenerator.cs index b9828ae9..d98dc341 100644 --- a/src/ShardingCore.MySql/EFCores/ShardingMySqlQuerySqlGenerator.cs +++ b/src/ShardingCore.MySql/EFCores/ShardingMySqlQuerySqlGenerator.cs @@ -64,7 +64,7 @@ namespace ShardingCore.MySql.EFCores if (shardingAccessor?.ShardingContext != null) { var virtualTableManager = ShardingContainer.Services.GetService(); - var virtualTable = virtualTableManager.GetAllVirtualTables().FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Name); + var virtualTable = virtualTableManager.GetAllVirtualTables(shardingAccessor.ShardingContext.ConnectKey).FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Name); if(virtualTable!=null) { var tails = shardingAccessor.ShardingContext.GetContextQueryTails(virtualTable); @@ -74,7 +74,7 @@ namespace ShardingCore.MySql.EFCores if (tails.IsEmpty()) { - var firstTail = virtualTableManager.GetVirtualTable(tableExpression.Name).GetAllPhysicTables()[0].Tail; + var firstTail = virtualTableManager.GetVirtualTable(shardingAccessor.ShardingContext.ConnectKey,tableExpression.Name).GetAllPhysicTables()[0].Tail; newTableName = $"( select * from {sqlGenerationHelper.DelimitIdentifier($"{tableExpression.Name}{tailPrefix}{firstTail}", tableExpression.Schema)} where 1=2 )"; } else if (tails.Count == 1) @@ -173,7 +173,7 @@ namespace ShardingCore.MySql.EFCores if (shardingAccessor?.ShardingContext != null) { var virtualTableManager = ShardingContainer.Services.GetService(); - var virtualTable = virtualTableManager.GetAllVirtualTables().FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Table); + var virtualTable = virtualTableManager.GetAllVirtualTables(shardingAccessor.ShardingContext.ConnectKey).FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Table); if(virtualTable!=null) { var tails = shardingAccessor.ShardingContext.GetContextQueryTails(virtualTable); @@ -183,7 +183,7 @@ namespace ShardingCore.MySql.EFCores if (tails.IsEmpty()) { - var firstTail = virtualTableManager.GetVirtualTable(tableExpression.Table).GetAllPhysicTables()[0].Tail; + var firstTail = virtualTableManager.GetVirtualTable(shardingAccessor.ShardingContext.ConnectKey,tableExpression.Table).GetAllPhysicTables()[0].Tail; newTableName = $"( select * from {sqlGenerationHelper.DelimitIdentifier($"{tableExpression.Table}{tailPrefix}{firstTail}", tableExpression.Schema)} where 1=2 )"; } else if (tails.Count == 1) diff --git a/src/ShardingCore.MySql/MySqlDbContextOptionsProvider.cs b/src/ShardingCore.MySql/MySqlDbContextOptionsProvider.cs index 168a90ee..79cc7d35 100644 --- a/src/ShardingCore.MySql/MySqlDbContextOptionsProvider.cs +++ b/src/ShardingCore.MySql/MySqlDbContextOptionsProvider.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; @@ -10,7 +11,9 @@ using MySql.Data.MySqlClient; using MySqlConnector; #endif using ShardingCore.DbContexts.VirtualDbContexts; +using ShardingCore.DbContexts.VirtualDbContexts.ShareDbContextOptionsProviders; using ShardingCore.EFCores; +using ShardingCore.Extensions; namespace ShardingCore.MySql { @@ -22,34 +25,46 @@ namespace ShardingCore.MySql */ public class MySqlDbContextOptionsProvider:IDbContextOptionsProvider { - private DbContextOptions _dbContextOptions; - private MySqlConnection _connection; + private readonly MySqlOptions _mySqlOptions; + private readonly ILoggerFactory _loggerFactory; + private readonly IShardingCoreOptions _shardingCoreOptions; - public MySqlDbContextOptionsProvider(MySqlOptions mySqlOptions,ILoggerFactory loggerFactory) + private readonly Dictionary _contextWrapItems = + new Dictionary(); + + public MySqlDbContextOptionsProvider(MySqlOptions mySqlOptions,ILoggerFactory loggerFactory,IShardingCoreOptions shardingCoreOptions) { - _connection=new MySqlConnection(mySqlOptions.ConnectionString); - _dbContextOptions = new DbContextOptionsBuilder() + _mySqlOptions = mySqlOptions; + _loggerFactory = loggerFactory; + _shardingCoreOptions = shardingCoreOptions; + } + public DbContextOptions GetDbContextOptions(string connectKey) + { + if (!_contextWrapItems.ContainsKey(connectKey)) + { + var connectionString = _shardingCoreOptions.GetShardingConfig(connectKey).ConnectionString; + var connection = new MySqlConnection(connectionString); + var dbContextOptions= new DbContextOptionsBuilder() #if EFCORE5 - .UseMySql(_connection,mySqlOptions.ServerVersion,mySqlOptions.MySqlOptionsAction) + .UseMySql(connection, _mySqlOptions.ServerVersion, _mySqlOptions.MySqlOptionsAction) #endif #if !EFCORE5 - .UseMySql(_connection,mySqlOptions.MySqlOptionsAction) + .UseMySql(connection, _mySqlOptions.MySqlOptionsAction) #endif - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - .UseLoggerFactory(loggerFactory) - .ReplaceService() - .ReplaceService() - .UseShardingSqlServerQuerySqlGenerator() - .Options; - } - public DbContextOptions GetDbContextOptions() - { - return _dbContextOptions; + .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) + .UseLoggerFactory(_loggerFactory) + .ReplaceService() + .ReplaceService() + .UseShardingSqlServerQuerySqlGenerator() + .Options; + _contextWrapItems.Add(connectKey,new ShareDbContextWrapItem(connection, dbContextOptions)); + } + return _contextWrapItems[connectKey].ContextOptions; } public void Dispose() { - _connection?.Dispose(); + _contextWrapItems.ForEach(o=>o.Value.Connection?.Dispose()); } } } \ No newline at end of file diff --git a/src/ShardingCore.MySql/MySqlOptions.cs b/src/ShardingCore.MySql/MySqlOptions.cs index cea6f1bd..dfdc1b33 100644 --- a/src/ShardingCore.MySql/MySqlOptions.cs +++ b/src/ShardingCore.MySql/MySqlOptions.cs @@ -1,8 +1,15 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.DbContexts.ShardingDbContexts; +using ShardingCore.Exceptions; using ShardingCore.Extensions; namespace ShardingCore.MySql @@ -15,29 +22,118 @@ namespace ShardingCore.MySql */ public class MySqlOptions { - public LinkedList ShardingRoutes=new LinkedList(); - public string ConnectionString { get; set; } #if EFCORE5 public MySqlServerVersion ServerVersion { get; set; } #endif public Action MySqlOptionsAction { get; set; } - - public void AddSharding()where TRoute:IVirtualRoute - { - ShardingRoutes.AddLast(typeof(TRoute)); - } - - public bool HasSharding => ShardingRoutes.IsNotEmpty(); - public Action ShardingCoreConfigConfigure { get; private set; } - + public void SetMySqlOptions(Action action) { MySqlOptionsAction = action; } - public void CreateIfNotExists(Action action) + private readonly IDictionary _shardingConfigs = new Dictionary(); + + public void AddShardingDbContext(string connectKey, string connectString, Action func) where TContext : DbContext { - ShardingCoreConfigConfigure = action; + if (_shardingConfigs.ContainsKey(connectKey)) + { + throw new ArgumentException($"same connect key:[{connectKey}]"); + } + + CheckContextConstructors(); + var creator = CreateActivator(); + var config = new ShardingConfigEntry(connectKey, connectString, creator, typeof(TContext), func); + _shardingConfigs.Add(connectKey, config); + } + private static void CheckContextConstructors() + where TContext : DbContext + { + var contextType = typeof(TContext); + var declaredConstructors = contextType.GetTypeInfo().DeclaredConstructors.ToList(); + if (!contextType.IsShardingDbContext()) + { + throw new ArgumentException($"dbcontext : {contextType} is assignable from {typeof(AbstractShardingDbContext)} "); + } + if (declaredConstructors.Count != 1) + { + throw new ArgumentException($"dbcontext : {contextType} declared constructor count more {contextType}"); + } + if (declaredConstructors[0].GetParameters().Length != 1) + { + throw new ArgumentException($"dbcontext : {contextType} declared constructor parameters more "); + } + if (declaredConstructors[0].GetParameters()[0].ParameterType != typeof(ShardingDbContextOptions)) + { + throw new ArgumentException($"dbcontext : {contextType} is assignable from {typeof(AbstractShardingDbContext)} declared constructor parameters should use {typeof(ShardingDbContextOptions)} "); + } + + } + + private static Func CreateActivator() where TContext : DbContext + { + var constructors + = typeof(TContext).GetTypeInfo().DeclaredConstructors + .Where(c => !c.IsStatic && c.IsPublic) + .ToArray(); + + var parameters = constructors[0].GetParameters(); + var parameterType = parameters[0].ParameterType; + + var po = Expression.Parameter(parameterType, "o"); + var new1 = Expression.New(constructors[0], po); + var inner = Expression.Lambda(new1, po); + + var args = Expression.Parameter(typeof(ShardingDbContextOptions), "args"); + var body = Expression.Invoke(inner, Expression.Convert(args, po.Type)); + var outer = Expression.Lambda>(body, args); + var func = outer.Compile(); + return func; + } + + public void AddShardingDbContext(string connectKey, string connectString) where T : DbContext + { + AddShardingDbContext(connectKey, connectString, null); + } + + + private readonly Dictionary _virtualRoutes = new Dictionary(); + public void AddDataSourceVirtualRoute() where TRoute : IDataSourceVirtualRoute + { + var virtualRouteType = typeof(TRoute); + //获取类型 + var shardingEntityType = virtualRouteType.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IDataSourceVirtualRoute<>"); + if (!_virtualRoutes.ContainsKey(shardingEntityType)) + { + _virtualRoutes.Add(shardingEntityType, virtualRouteType); + } + } + + + public ISet GetShardingConfigs() + { + return _shardingConfigs.Select(o => o.Value).ToHashSet(); + } + + public ShardingConfigEntry GetShardingConfig(string connectKey) + { + if (!_shardingConfigs.ContainsKey(connectKey)) + throw new ShardingConfigNotFoundException(connectKey); + return _shardingConfigs[connectKey]; + } + + public ISet GetVirtualRoutes() + { + return _virtualRoutes.Select(o => o.Value).ToHashSet(); + } + + public Type GetVirtualRoute(Type entityType) + { + if (!_virtualRoutes.ContainsKey(entityType)) + throw new ArgumentException("not found IDataSourceVirtualRoute"); + return _virtualRoutes[entityType]; } } } \ No newline at end of file diff --git a/src/ShardingCore.MySql/ShardingMySqlParallelDbContextFactory.cs b/src/ShardingCore.MySql/ShardingMySqlParallelDbContextFactory.cs index 6c663264..d9c5c206 100644 --- a/src/ShardingCore.MySql/ShardingMySqlParallelDbContextFactory.cs +++ b/src/ShardingCore.MySql/ShardingMySqlParallelDbContextFactory.cs @@ -18,30 +18,35 @@ namespace ShardingCore.MySql public class ShardingMySqlParallelDbContextFactory : IShardingParallelDbContextFactory { private readonly IVirtualTableManager _virtualTableManager; + private readonly IShardingDbContextFactory _shardingDbContextFactory; + private readonly IShardingCoreOptions _shardingCoreOptions; private readonly MySqlOptions _mySqlOptions; - public ShardingMySqlParallelDbContextFactory(IVirtualTableManager virtualTableManager, MySqlOptions mySqlOptions) + public ShardingMySqlParallelDbContextFactory(IVirtualTableManager virtualTableManager,IShardingDbContextFactory shardingDbContextFactory,IShardingCoreOptions shardingCoreOptions, MySqlOptions mySqlOptions) { _virtualTableManager = virtualTableManager; + _shardingDbContextFactory = shardingDbContextFactory; + _shardingCoreOptions = shardingCoreOptions; _mySqlOptions = mySqlOptions; } - public ShardingDbContext Create(string tail) + public DbContext Create(string connectKey, string tail) { - var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables().GetVirtualTableDbContextConfigs(); - var shardingDbContextOptions = new ShardingDbContextOptions(CreateOptions(), tail, virtualTableConfigs); - return new ShardingDbContext(shardingDbContextOptions); + var shardingConfigEntry = _shardingCoreOptions.GetShardingConfig(connectKey); + var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables(connectKey).GetVirtualTableDbContextConfigs(); + var shardingDbContextOptions = new ShardingDbContextOptions(CreateOptions(shardingConfigEntry.ConnectionString), tail, virtualTableConfigs); + return _shardingDbContextFactory.Create(connectKey, shardingDbContextOptions); } - private DbContextOptions CreateOptions() + private DbContextOptions CreateOptions(string connectionString) { return new DbContextOptionsBuilder() #if EFCORE5 - .UseMySql(_mySqlOptions.ConnectionString,_mySqlOptions.ServerVersion,_mySqlOptions.MySqlOptionsAction) + .UseMySql(connectionString,_mySqlOptions.ServerVersion,_mySqlOptions.MySqlOptionsAction) #endif #if !EFCORE5 - .UseMySql(_mySqlOptions.ConnectionString,_mySqlOptions.MySqlOptionsAction) + .UseMySql(connectionString, _mySqlOptions.MySqlOptionsAction) #endif .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) .ReplaceService() diff --git a/src/ShardingCore.SqlServer/DIExtension.cs b/src/ShardingCore.SqlServer/DIExtension.cs index f4cdc6ba..e3cd0817 100644 --- a/src/ShardingCore.SqlServer/DIExtension.cs +++ b/src/ShardingCore.SqlServer/DIExtension.cs @@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.DependencyInjection; using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualTables; using ShardingCore.DbContexts; using ShardingCore.DbContexts.VirtualDbContexts; @@ -33,31 +34,15 @@ namespace ShardingCore.SqlServer var options = new SqlServerOptions(); configure(options); - services.AddSingleton(options); + services.AddSingleton(sp=> options); services.AddShardingCore(); services.AddScoped(); services.AddSingleton(); - if (options.HasSharding) - { - foreach (var shardingRoute in options.ShardingRoutes) - { - var genericVirtualRoute = shardingRoute.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualRoute<>) - && it.GetGenericArguments().Any()); - if (genericVirtualRoute == null) - throw new ArgumentException("add sharding route type error not assignable from IVirtualRoute<>."); - var shardingEntity=genericVirtualRoute.GetGenericArguments()[0]; - if(!shardingEntity.IsShardingEntity()) - throw new ArgumentException("add sharding route type error generic arguments first not assignable from IShardingEntity."); - Type genericType = typeof(IVirtualRoute<>); - Type interfaceType = genericType.MakeGenericType(shardingEntity); - services.AddSingleton(interfaceType, shardingRoute); - } - } + services.AddSingleton(sp => { var shardingCoreConfig = new ShardingCoreConfig(); - options.ShardingCoreConfigConfigure?.Invoke(sp,shardingCoreConfig); return shardingCoreConfig; }); services.AddSingleton(); diff --git a/src/ShardingCore.SqlServer/EFCores/ShardingSqlServerQuerySqlGenerator.cs b/src/ShardingCore.SqlServer/EFCores/ShardingSqlServerQuerySqlGenerator.cs index 21d59df8..2aac6992 100644 --- a/src/ShardingCore.SqlServer/EFCores/ShardingSqlServerQuerySqlGenerator.cs +++ b/src/ShardingCore.SqlServer/EFCores/ShardingSqlServerQuerySqlGenerator.cs @@ -55,7 +55,7 @@ namespace ShardingCore.SqlServer.EFCores if (shardingAccessor?.ShardingContext != null) { var virtualTableManager = ShardingContainer.Services.GetService(); - var virtualTable = virtualTableManager.GetAllVirtualTables().FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Name); + var virtualTable = virtualTableManager.GetAllVirtualTables(shardingAccessor.ShardingContext.ConnectKey).FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Name); if(virtualTable!=null) { var tails = shardingAccessor.ShardingContext.GetContextQueryTails(virtualTable); @@ -65,7 +65,7 @@ namespace ShardingCore.SqlServer.EFCores if (tails.IsEmpty()) { - var firstTail = virtualTableManager.GetVirtualTable(tableExpression.Name).GetAllPhysicTables()[0].Tail; + var firstTail = virtualTableManager.GetVirtualTable(shardingAccessor.ShardingContext.ConnectKey,tableExpression.Name).GetAllPhysicTables()[0].Tail; newTableName = $"( select * from {sqlGenerationHelper.DelimitIdentifier($"{tableExpression.Name}{tailPrefix}{firstTail}", tableExpression.Schema)} where 1=2 )"; } else if (tails.Count == 1) @@ -174,7 +174,7 @@ namespace ShardingCore.SqlServer.EFCores if (shardingAccessor?.ShardingContext != null) { var virtualTableManager = ShardingContainer.Services.GetService(); - var virtualTable = virtualTableManager.GetAllVirtualTables().FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Table); + var virtualTable = virtualTableManager.GetAllVirtualTables(shardingAccessor.ShardingContext.ConnectKey).FirstOrDefault(o => o.GetOriginalTableName() == tableExpression.Table); if(virtualTable!=null) { var tails = shardingAccessor.ShardingContext.GetContextQueryTails(virtualTable); @@ -184,7 +184,7 @@ namespace ShardingCore.SqlServer.EFCores if (tails.IsEmpty()) { - var firstTail = virtualTableManager.GetVirtualTable(tableExpression.Table).GetAllPhysicTables()[0].Tail; + var firstTail = virtualTableManager.GetVirtualTable(shardingAccessor.ShardingContext.ConnectKey,tableExpression.Table).GetAllPhysicTables()[0].Tail; newTableName = $"( select * from {sqlGenerationHelper.DelimitIdentifier($"{tableExpression.Table}{tailPrefix}{firstTail}", tableExpression.Schema)} where 1=2 )"; } else if (tails.Count == 1) diff --git a/src/ShardingCore.SqlServer/ShardingSqlServerParallelDbContextFactory.cs b/src/ShardingCore.SqlServer/ShardingSqlServerParallelDbContextFactory.cs index 83e4877a..94861ba4 100644 --- a/src/ShardingCore.SqlServer/ShardingSqlServerParallelDbContextFactory.cs +++ b/src/ShardingCore.SqlServer/ShardingSqlServerParallelDbContextFactory.cs @@ -1,3 +1,7 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; @@ -18,25 +22,28 @@ namespace ShardingCore.SqlServer public class ShardingSqlServerParallelDbContextFactory : IShardingParallelDbContextFactory { private readonly IVirtualTableManager _virtualTableManager; - private readonly SqlServerOptions _sqlServerOptions; + private readonly IShardingDbContextFactory _shardingDbContextFactory; + private readonly IShardingCoreOptions _shardingCoreOptions; - public ShardingSqlServerParallelDbContextFactory(IVirtualTableManager virtualTableManager, SqlServerOptions sqlServerOptions) + public ShardingSqlServerParallelDbContextFactory(IVirtualTableManager virtualTableManager,IShardingCoreOptions shardingCoreOptions, IShardingDbContextFactory shardingDbContextFactory) { _virtualTableManager = virtualTableManager; - _sqlServerOptions = sqlServerOptions; + _shardingDbContextFactory = shardingDbContextFactory; + _shardingCoreOptions = shardingCoreOptions; } - public ShardingDbContext Create(string tail) + public DbContext Create(string connectKey,string tail) { - var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables().GetVirtualTableDbContextConfigs(); - var shardingDbContextOptions = new ShardingDbContextOptions(CreateOptions(), tail, virtualTableConfigs); - return new ShardingDbContext(shardingDbContextOptions); + var shardingConfigEntry = _shardingCoreOptions.GetShardingConfig(connectKey); + var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables(connectKey).GetVirtualTableDbContextConfigs(); + var shardingDbContextOptions = new ShardingDbContextOptions(CreateOptions(shardingConfigEntry.ConnectionString), tail, virtualTableConfigs); + return _shardingDbContextFactory.Create(connectKey, shardingDbContextOptions); } - private DbContextOptions CreateOptions() + private DbContextOptions CreateOptions(string connectString) { return new DbContextOptionsBuilder() - .UseSqlServer(_sqlServerOptions.ConnectionString) + .UseSqlServer(connectString) .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) .ReplaceService() .ReplaceService() diff --git a/src/ShardingCore.SqlServer/SqlServerDbContextOptionsProvider.cs b/src/ShardingCore.SqlServer/SqlServerDbContextOptionsProvider.cs index 60cc5198..67a407cd 100644 --- a/src/ShardingCore.SqlServer/SqlServerDbContextOptionsProvider.cs +++ b/src/ShardingCore.SqlServer/SqlServerDbContextOptionsProvider.cs @@ -1,9 +1,12 @@ +using System.Collections.Generic; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.Logging; using ShardingCore.DbContexts.VirtualDbContexts; +using ShardingCore.DbContexts.VirtualDbContexts.ShareDbContextOptionsProviders; using ShardingCore.EFCores; +using ShardingCore.Extensions; #if EFCORE2 using System.Data.SqlClient; #endif @@ -21,29 +24,39 @@ namespace ShardingCore.SqlServer */ public class SqlServerDbContextOptionsProvider:IDbContextOptionsProvider { - private DbContextOptions _dbContextOptions; - private SqlConnection _connection; + private readonly ILoggerFactory _loggerFactory; + private readonly IShardingCoreOptions _shardingCoreOptions; - public SqlServerDbContextOptionsProvider(SqlServerOptions sqlServerOptions,ILoggerFactory loggerFactory) + private readonly Dictionary _contextWrapItems = + new Dictionary(); + + public SqlServerDbContextOptionsProvider(ILoggerFactory loggerFactory,IShardingCoreOptions shardingCoreOptions) { - _connection=new SqlConnection(sqlServerOptions.ConnectionString); - _dbContextOptions = new DbContextOptionsBuilder() - .UseSqlServer(_connection) - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - .UseLoggerFactory(loggerFactory) - .ReplaceService() - .ReplaceService() - .UseShardingSqlServerQuerySqlGenerator() - .Options; + _loggerFactory = loggerFactory; + _shardingCoreOptions = shardingCoreOptions; } - public DbContextOptions GetDbContextOptions() + public DbContextOptions GetDbContextOptions(string connectKey) { - return _dbContextOptions; + if (_contextWrapItems.ContainsKey(connectKey)) + { + var connectionString = _shardingCoreOptions.GetShardingConfig(connectKey).ConnectionString; + var connection = new SqlConnection(connectionString); + var dbContextOptions = new DbContextOptionsBuilder() + .UseSqlServer(connection) + .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) + .UseLoggerFactory(_loggerFactory) + .ReplaceService() + .ReplaceService() + .UseShardingSqlServerQuerySqlGenerator() + .Options; + _contextWrapItems.Add(connectKey, new ShareDbContextWrapItem(connection, dbContextOptions)); + } + return _contextWrapItems[connectKey].ContextOptions; } public void Dispose() { - _connection?.Dispose(); + _contextWrapItems.ForEach(o => o.Value.Connection?.Dispose()); } } } \ No newline at end of file diff --git a/src/ShardingCore.SqlServer/SqlServerOptions.cs b/src/ShardingCore.SqlServer/SqlServerOptions.cs index 69328a07..b5c11cd6 100644 --- a/src/ShardingCore.SqlServer/SqlServerOptions.cs +++ b/src/ShardingCore.SqlServer/SqlServerOptions.cs @@ -1,6 +1,17 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Infrastructure; +using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.DbContexts.ShardingDbContexts; +using ShardingCore.Exceptions; using ShardingCore.Extensions; namespace ShardingCore.SqlServer @@ -11,21 +22,110 @@ namespace ShardingCore.SqlServer * @Date: 2020年4月7日 8:34:04 * @Email: 326308290@qq.com */ - public class SqlServerOptions + public class SqlServerOptions: IShardingCoreOptions { - public LinkedList ShardingRoutes=new LinkedList(); - public string ConnectionString { get; set; } + private readonly IDictionary _shardingConfigs = new Dictionary(); - public void AddSharding()where TRoute:IVirtualRoute + public void AddShardingDbContext(string connectKey,string connectString,Action func) where TContext : DbContext { - ShardingRoutes.AddLast(typeof(TRoute)); + if (_shardingConfigs.ContainsKey(connectKey)) + { + throw new ArgumentException($"same connect key:[{connectKey}]"); + } + + CheckContextConstructors(); + var creator = CreateActivator(); + var config = new ShardingConfigEntry(connectKey, connectString, creator, typeof(TContext), func); + _shardingConfigs.Add(connectKey, config); + } + private static void CheckContextConstructors() + where TContext : DbContext + { + var contextType = typeof(TContext); + var declaredConstructors = contextType.GetTypeInfo().DeclaredConstructors.ToList(); + if (!contextType.IsShardingDbContext()) + { + throw new ArgumentException($"dbcontext : {contextType} is assignable from {typeof(AbstractShardingDbContext)} "); + } + if (declaredConstructors.Count != 1) + { + throw new ArgumentException($"dbcontext : {contextType} declared constructor count more {contextType}"); + } + if (declaredConstructors[0].GetParameters().Length != 1) + { + throw new ArgumentException($"dbcontext : {contextType} declared constructor parameters more "); + } + if (declaredConstructors[0].GetParameters()[0].ParameterType != typeof(ShardingDbContextOptions)) + { + throw new ArgumentException($"dbcontext : {contextType} is assignable from {typeof(AbstractShardingDbContext)} declared constructor parameters should use {typeof(ShardingDbContextOptions)} "); + } + } - public bool HasSharding => ShardingRoutes.IsNotEmpty(); - public Action ShardingCoreConfigConfigure { get; private set; } - public void UseShardingCoreConfig(Action function) + private static Func CreateActivator() where TContext:DbContext { - ShardingCoreConfigConfigure = function; + var constructors + = typeof(TContext).GetTypeInfo().DeclaredConstructors + .Where(c => !c.IsStatic && c.IsPublic) + .ToArray(); + + var parameters = constructors[0].GetParameters(); + var parameterType=parameters[0].ParameterType; + + var po = Expression.Parameter(parameterType, "o"); + var new1 = Expression.New(constructors[0], po); + var inner = Expression.Lambda(new1, po); + + var args = Expression.Parameter(typeof(ShardingDbContextOptions), "args"); + var body = Expression.Invoke(inner, Expression.Convert(args, po.Type)); + var outer = Expression.Lambda>(body, args); + var func = outer.Compile(); + return func; + } + + public void AddShardingDbContext(string connectKey, string connectString) where T : DbContext + { + AddShardingDbContext(connectKey, connectString,null); + } + + + private readonly Dictionary _virtualRoutes = new Dictionary(); + public void AddDataSourceVirtualRoute() where TRoute : IDataSourceVirtualRoute + { + var virtualRouteType = typeof(TRoute); + //获取类型 + var shardingEntityType = virtualRouteType.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IDataSourceVirtualRoute<>"); + if (!_virtualRoutes.ContainsKey(shardingEntityType)) + { + _virtualRoutes.Add(shardingEntityType,virtualRouteType); + } + } + + + public ISet GetShardingConfigs() + { + return _shardingConfigs.Select(o=>o.Value).ToHashSet(); + } + + public ShardingConfigEntry GetShardingConfig(string connectKey) + { + if (!_shardingConfigs.ContainsKey(connectKey)) + throw new ShardingConfigNotFoundException(connectKey); + return _shardingConfigs[connectKey]; + } + + public ISet GetVirtualRoutes() + { + return _virtualRoutes.Select(o=>o.Value).ToHashSet(); + } + + public Type GetVirtualRoute(Type entityType) + { + if (!_virtualRoutes.ContainsKey(entityType)) + throw new ArgumentException("not found IDataSourceVirtualRoute"); + return _virtualRoutes[entityType]; } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/DataSourceAccessors/DataSourceAccessor.cs b/src/ShardingCore/Core/DataSourceAccessors/DataSourceAccessor.cs new file mode 100644 index 00000000..351aec23 --- /dev/null +++ b/src/ShardingCore/Core/DataSourceAccessors/DataSourceAccessor.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; + +namespace ShardingCore.Core.DataSourceAccessors +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/1 16:32:30 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + /// + /// 创建数据库数据 + /// + public class DataSourceAccessor: IDataSourceAccessor + { + public DbContext CreateDbContext() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/ShardingCore/Core/DataSourceAccessors/DataSourceAccessorContext.cs b/src/ShardingCore/Core/DataSourceAccessors/DataSourceAccessorContext.cs new file mode 100644 index 00000000..fc5b125a --- /dev/null +++ b/src/ShardingCore/Core/DataSourceAccessors/DataSourceAccessorContext.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ShardingCore.Core.DataSourceAccessors +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/1 16:11:10 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + /// + /// 数据访问器上下文 + /// + public class DataSourceAccessorContext + { + private readonly IQueryable _queryable; + + public DataSourceAccessorContext(IQueryable queryable) + { + _queryable = queryable; + } + } +} diff --git a/src/ShardingCore/Core/DataSourceAccessors/DataSourceRouteResult.cs b/src/ShardingCore/Core/DataSourceAccessors/DataSourceRouteResult.cs new file mode 100644 index 00000000..f3813fe6 --- /dev/null +++ b/src/ShardingCore/Core/DataSourceAccessors/DataSourceRouteResult.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.Internal.RoutingRuleEngines; + +namespace ShardingCore.Core.DataSourceAccessors +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/1 16:27:03 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DataSourceRouteResult + { + public DataSourceRouteResult() + { + + } + public IEnumerable TableRouteResults { get; } + } +} diff --git a/src/ShardingCore/Core/DataSourceAccessors/IDataSourceRouteRuleEngine.cs b/src/ShardingCore/Core/DataSourceAccessors/IDataSourceRouteRuleEngine.cs new file mode 100644 index 00000000..30d209af --- /dev/null +++ b/src/ShardingCore/Core/DataSourceAccessors/IDataSourceRouteRuleEngine.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ShardingCore.Core.DataSourceAccessors +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/1 16:23:13 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + /// + /// 分库数据路由规则引擎 + /// + public interface IDataSourceRouteRuleEngine + { + + } +} diff --git a/src/ShardingCore/Core/Internal/RoutingRuleEngines/IRoutingRuleEngineFactory.cs b/src/ShardingCore/Core/Internal/RoutingRuleEngines/IRoutingRuleEngineFactory.cs index 3f775c3e..4e726691 100644 --- a/src/ShardingCore/Core/Internal/RoutingRuleEngines/IRoutingRuleEngineFactory.cs +++ b/src/ShardingCore/Core/Internal/RoutingRuleEngines/IRoutingRuleEngineFactory.cs @@ -13,8 +13,8 @@ namespace ShardingCore.Core.Internal.RoutingRuleEngines public interface IRoutingRuleEngineFactory { IRouteRuleEngine CreateEngine(); - RouteRuleContext CreateContext(IQueryable queryable); - IEnumerable Route(IQueryable queryable); - IEnumerable Route(IQueryable queryable,RouteRuleContext ruleContext); + RouteRuleContext CreateContext(string connectKey,IQueryable queryable); + IEnumerable Route(string connectKey, IQueryable queryable); + IEnumerable Route(string connectKey, IQueryable queryable,RouteRuleContext ruleContext); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/Internal/RoutingRuleEngines/QueryRouteRuleEngine.cs b/src/ShardingCore/Core/Internal/RoutingRuleEngines/QueryRouteRuleEngine.cs index d3c2c03e..5696f9cb 100644 --- a/src/ShardingCore/Core/Internal/RoutingRuleEngines/QueryRouteRuleEngine.cs +++ b/src/ShardingCore/Core/Internal/RoutingRuleEngines/QueryRouteRuleEngine.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualTables; using ShardingCore.Extensions; #if !EFCORE5 @@ -30,29 +31,14 @@ namespace ShardingCore.Core.Internal.RoutingRuleEngines { Dictionary> routeMaps = new Dictionary>(); var queryEntities = routeRuleContext.Queryable.ParseQueryableRoute(); - //先添加手动路由到当前上下文,之后将不再手动路由里面的自动路由添加到当前上下文 - foreach (var kv in routeRuleContext.ManualTails) + + + var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); + foreach (var shardingEntity in shardingEntities) { - 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 routeRuleContext.ManualPredicate) - { - var virtualTable = kv.Key; - var predicate = kv.Value; - var physicTables = virtualTable.RouteTo(new RouteConfig(null, null, null, predicate)); + var virtualTable = _virtualTableManager.GetVirtualTable(routeRuleContext.ConnectKey,shardingEntity); + + var physicTables = virtualTable.RouteTo(new TableRouteConfig(routeRuleContext.Queryable)); if (!routeMaps.ContainsKey(virtualTable)) { routeMaps.Add(virtualTable, physicTables.ToHashSet()); @@ -65,28 +51,63 @@ namespace ShardingCore.Core.Internal.RoutingRuleEngines } } } + ////先添加手动路由到当前上下文,之后将不再手动路由里面的自动路由添加到当前上下文 + //foreach (var kv in routeRuleContext.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 routeRuleContext.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 (routeRuleContext.AutoParseRoute) - { - var shardingEntities = queryEntities.Where(o => o.IsShardingEntity()); - foreach (var shardingEntity in shardingEntities) - { - var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntity); + //if (routeRuleContext.AutoParseRoute) + //{ + // var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); + // foreach (var shardingEntity in shardingEntities) + // { + // var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntity); - var physicTables = virtualTable.RouteTo(new RouteConfig(routeRuleContext.Queryable)); - if (!routeMaps.ContainsKey(virtualTable)) - { - routeMaps.Add(virtualTable, physicTables.ToHashSet()); - } - else - { - foreach (var physicTable in physicTables) - { - routeMaps[virtualTable].Add(physicTable); - } - } - } - } + // var physicTables = virtualTable.RouteTo(new TableRouteConfig(routeRuleContext.Queryable)); + // if (!routeMaps.ContainsKey(virtualTable)) + // { + // routeMaps.Add(virtualTable, physicTables.ToHashSet()); + // } + // else + // { + // foreach (var physicTable in physicTables) + // { + // routeMaps[virtualTable].Add(physicTable); + // } + // } + // } + //} return routeMaps.Select(o => o.Value).Cartesian().Select(o=>new RouteResult(o)); } diff --git a/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleConfig.cs b/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleConfig.cs deleted file mode 100644 index e70fc147..00000000 --- a/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleConfig.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -namespace ShardingCore.Core.Internal.RoutingRuleEngines -{ -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 28 January 2021 10:53:55 -* @Email: 326308290@qq.com -*/ - public class RouteRuleConfig - { - private bool _autoParseRoute = true; - - public bool GetAutoParseRoute() - { - return _autoParseRoute; - } - - /// - /// 启用自动路由 - /// - public void EnableAutoRouteParse() - { - _autoParseRoute = true; - } - - /// - /// 禁用自动路由 - /// - public void DisableAutoRouteParse() - { - _autoParseRoute = false; - } - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleContext.cs b/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleContext.cs index ec19ecea..75f46831 100644 --- a/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleContext.cs +++ b/src/ShardingCore/Core/Internal/RoutingRuleEngines/RouteRuleContext.cs @@ -16,84 +16,86 @@ namespace ShardingCore.Core.Internal.RoutingRuleEngines { private readonly IVirtualTableManager _virtualTableManager; - public RouteRuleContext(IQueryable queryable, IVirtualTableManager virtualTableManager) + public RouteRuleContext(string connectKey,IQueryable queryable, IVirtualTableManager virtualTableManager) { + ConnectKey = connectKey; Queryable = queryable; _virtualTableManager = virtualTableManager; } + public string ConnectKey { get; } public IQueryable Queryable { get; } - /// - /// - /// - public readonly Dictionary ManualPredicate = new Dictionary(); - public readonly Dictionary> ManualTails = new Dictionary>(); + ///// + ///// + ///// + //public readonly Dictionary ManualPredicate = new Dictionary(); + //public readonly Dictionary> ManualTails = new Dictionary>(); - public bool AutoParseRoute = true; + //public bool AutoParseRoute = true; - /// - /// 启用自动路由 - /// - public void EnableAutoRouteParse() - { - AutoParseRoute = true; - } + ///// + ///// 启用自动路由 + ///// + //public void EnableAutoRouteParse() + //{ + // AutoParseRoute = true; + //} - /// - /// 禁用自动路由 - /// - public void DisableAutoRouteParse() - { - AutoParseRoute = false; - } + ///// + ///// 禁用自动路由 + ///// + //public void DisableAutoRouteParse() + //{ + // AutoParseRoute = false; + //} - /// - /// 添加手动路由 - /// - /// - /// - public void AddRoute(Expression> predicate) where TShardingEntity : class, IShardingEntity - { - var virtualTable = _virtualTableManager.GetVirtualTable(); - if (!ManualPredicate.ContainsKey(virtualTable)) - { - ShardingCore.Extensions.ExpressionExtension.And((Expression>) ManualPredicate[virtualTable], predicate); - } - else - { - ManualPredicate.Add(virtualTable, predicate); - } - } - public void AddRoute(Type shardingEntityType,string tail) - { - var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType); - AddRoute(virtualTable, tail); - } + ///// + ///// 添加手动路由 + ///// + ///// + ///// + //public void AddRoute(Expression> predicate) where TShardingEntity : class, IShardingEntity + //{ + // var virtualTable = _virtualTableManager.GetVirtualTable(); + // if (!ManualPredicate.ContainsKey(virtualTable)) + // { + // ShardingCore.Extensions.ExpressionExtension.And((Expression>) ManualPredicate[virtualTable], predicate); + // } + // else + // { + // ManualPredicate.Add(virtualTable, predicate); + // } + //} + //public void AddRoute(Type shardingEntityType,string tail) + //{ + // var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType); + // AddRoute(virtualTable, tail); + //} - public void AddRoute(string tail) where TShardingEntity : class, IShardingEntity - { - AddRoute(typeof(TShardingEntity), tail); - } + //public void AddRoute(string tail) where TShardingEntity : class, IShardingEntity + //{ + // AddRoute(typeof(TShardingEntity), tail); + //} - public void AddRoute(IVirtualTable virtualTable, string tail) - { - if (ManualTails.ContainsKey(virtualTable)) - { - var tails = ManualTails[virtualTable]; - if (!tails.Contains(tail)) - { - tails.Add(tail); - } - } - else - { - ManualTails.Add(virtualTable, new HashSet() - { - tail - }); - } - } + //public void AddRoute(IVirtualTable virtualTable, string tail) + //{ + // if (ManualTails.ContainsKey(virtualTable)) + // { + // var tails = ManualTails[virtualTable]; + // if (!tails.Contains(tail)) + // { + // tails.Add(tail); + // } + // } + // else + // { + // ManualTails.Add(virtualTable, new HashSet() + // { + // tail + // }); + // } + //} } } \ No newline at end of file diff --git a/src/ShardingCore/Core/Internal/RoutingRuleEngines/RoutingRuleEngineFactory.cs b/src/ShardingCore/Core/Internal/RoutingRuleEngines/RoutingRuleEngineFactory.cs index f47da73a..14c9989c 100644 --- a/src/ShardingCore/Core/Internal/RoutingRuleEngines/RoutingRuleEngineFactory.cs +++ b/src/ShardingCore/Core/Internal/RoutingRuleEngines/RoutingRuleEngineFactory.cs @@ -27,19 +27,19 @@ namespace ShardingCore.Core.Internal.RoutingRuleEngines return _routeRuleEngine; } - public RouteRuleContext CreateContext(IQueryable queryable) + public RouteRuleContext CreateContext(string connectKey, IQueryable queryable) { - return new RouteRuleContext(queryable, _virtualTableManager); + return new RouteRuleContext(connectKey,queryable, _virtualTableManager); } - public IEnumerable Route(IQueryable queryable) + public IEnumerable Route(string connectKey, IQueryable queryable) { var engine = CreateEngine(); - var ruleContext = CreateContext(queryable); + var ruleContext = CreateContext(connectKey,queryable); return engine.Route(ruleContext); } - public IEnumerable Route(IQueryable queryable, RouteRuleContext ruleContext) + public IEnumerable Route(string connectKey, IQueryable queryable, RouteRuleContext ruleContext) { var engine = CreateEngine(); return engine.Route(ruleContext); diff --git a/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericInMemoryMergeEngine.cs b/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericInMemoryMergeEngine.cs index 36064fb6..eab556cb 100644 --- a/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericInMemoryMergeEngine.cs +++ b/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericInMemoryMergeEngine.cs @@ -28,11 +28,11 @@ namespace ShardingCore.Core.Internal.StreamMerge.GenericMerges return new GenericInMemoryMergeEngine(mergeContext); } - private async Task EFCoreExecute(IQueryable newQueryable,RouteResult routeResult,Func> efQuery) + private async Task EFCoreExecute(string connectKey,IQueryable newQueryable,RouteResult routeResult,Func> efQuery) { using (var scope = _mergeContext.CreateScope()) { - scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult); + scope.ShardingAccessor.ShardingContext = ShardingContext.Create(connectKey,routeResult); return await efQuery(newQueryable); } } @@ -41,27 +41,32 @@ namespace ShardingCore.Core.Internal.StreamMerge.GenericMerges if (_mergeContext.Skip.HasValue || _mergeContext.Take.HasValue) throw new InvalidOperationException("aggregate not support skip take"); //从各个分表获取数据 - List parallelDbContexts = new List(_mergeContext.RouteResults.Count()); + ICollection parallelDbContexts = new LinkedList(); try { - var enumeratorTasks = _mergeContext.RouteResults.Select(routeResult => + + var enumeratorTasks = _mergeContext.GetDataSourceRoutingResult().IntersectConfigs.SelectMany(connectKey => { - return Task.Run(async () => + return _mergeContext.GetRouteResults(connectKey).Select(routeResult => { - var shardingDbContext = _mergeContext.CreateDbContext(); - parallelDbContexts.Add(shardingDbContext); - var newQueryable = (IQueryable) _mergeContext.GetReWriteQueryable().ReplaceDbContextQueryable(shardingDbContext); - - return await EFCoreExecute(newQueryable,routeResult,efQuery); + return Task.Run(async () => + { + var shardingDbContext = _mergeContext.CreateDbContext(connectKey); + parallelDbContexts.Add(shardingDbContext); + var newQueryable = (IQueryable)_mergeContext.GetReWriteQueryable() + .ReplaceDbContextQueryable(shardingDbContext); + + return await EFCoreExecute(connectKey,newQueryable, routeResult, efQuery); + }); }); }).ToArray(); + return (await Task.WhenAll(enumeratorTasks)).ToList(); } finally { parallelDbContexts.ForEach(o => o.Dispose()); } - } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericStreamMergeEngine.cs b/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericStreamMergeEngine.cs index 00d5005b..d54f708c 100644 --- a/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericStreamMergeEngine.cs +++ b/src/ShardingCore/Core/Internal/StreamMerge/GenericMerges/GenericStreamMergeEngine.cs @@ -24,12 +24,12 @@ namespace ShardingCore.Core.Internal.StreamMerge.GenericMerges internal class GenericStreamMergeEngine : IStreamMergeEngine { private readonly StreamMergeContext _mergeContext; - private readonly List _parallelDbContexts; + private readonly ICollection _parallelDbContexts; public GenericStreamMergeEngine(StreamMergeContext mergeContext) { _mergeContext = mergeContext; - _parallelDbContexts = new List(mergeContext.RouteResults.Count()); + _parallelDbContexts = new LinkedList(); } public static GenericStreamMergeEngine Create(StreamMergeContext mergeContext) @@ -37,11 +37,11 @@ namespace ShardingCore.Core.Internal.StreamMerge.GenericMerges return new GenericStreamMergeEngine(mergeContext); } - private async Task> GetAsyncEnumerator(IQueryable newQueryable, RouteResult routeResult) + private async Task> GetAsyncEnumerator(string connectKey,IQueryable newQueryable, RouteResult routeResult) { using (var scope = _mergeContext.CreateScope()) { - scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult); + scope.ShardingAccessor.ShardingContext = ShardingContext.Create(connectKey,routeResult); #if !EFCORE2 var enumator = newQueryable.AsAsyncEnumerable().GetAsyncEnumerator(); await enumator.MoveNextAsync(); @@ -56,18 +56,23 @@ namespace ShardingCore.Core.Internal.StreamMerge.GenericMerges public async Task> GetStreamEnumerator() { - var enumeratorTasks = _mergeContext.RouteResults.Select(routeResult => + var enumeratorTasks = _mergeContext.GetDataSourceRoutingResult().IntersectConfigs.SelectMany(connectKey => { - return Task.Run(async () => + return _mergeContext.GetRouteResults(connectKey).Select(routeResult => { - var shardingDbContext = _mergeContext.CreateDbContext(); - _parallelDbContexts.Add(shardingDbContext); - var newQueryable = (IQueryable) _mergeContext.GetReWriteQueryable().ReplaceDbContextQueryable(shardingDbContext); + return Task.Run(async () => + { + var shardingDbContext = _mergeContext.CreateDbContext(connectKey); + _parallelDbContexts.Add(shardingDbContext); + var newQueryable = (IQueryable) _mergeContext.GetReWriteQueryable() + .ReplaceDbContextQueryable(shardingDbContext); - var asyncEnumerator = await GetAsyncEnumerator(newQueryable, routeResult); - return new StreamMergeAsyncEnumerator(asyncEnumerator); + var asyncEnumerator = await GetAsyncEnumerator(connectKey,newQueryable, routeResult); + return new StreamMergeAsyncEnumerator(asyncEnumerator); + }); }); }).ToArray(); + var streamEnumerators = await Task.WhenAll(enumeratorTasks); if (_mergeContext.HasSkipTake()) return new NoPaginationStreamMergeEnumerator(_mergeContext,streamEnumerators ); diff --git a/src/ShardingCore/Core/Internal/StreamMerge/IStreamMergeContextFactory.cs b/src/ShardingCore/Core/Internal/StreamMerge/IStreamMergeContextFactory.cs index 60a45646..14a201af 100644 --- a/src/ShardingCore/Core/Internal/StreamMerge/IStreamMergeContextFactory.cs +++ b/src/ShardingCore/Core/Internal/StreamMerge/IStreamMergeContextFactory.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using ShardingCore.Core.Internal.RoutingRuleEngines; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine; namespace ShardingCore.Core.Internal.StreamMerge { @@ -13,8 +14,8 @@ namespace ShardingCore.Core.Internal.StreamMerge */ internal interface IStreamMergeContextFactory { - StreamMergeContext Create(IQueryable queryable, IEnumerable routeResults); + //StreamMergeContext Create(IQueryable queryable, DataSourceRoutingResult dataSourceRoutingResult); StreamMergeContext Create(IQueryable queryable); - StreamMergeContext Create(IQueryable queryable, RouteRuleContext ruleContext); + StreamMergeContext Create(IQueryable queryable, DataSourceRoutingRuleContext ruleContext); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContext.cs b/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContext.cs index 7d0e8f3f..2b44c7da 100644 --- a/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContext.cs +++ b/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContext.cs @@ -7,6 +7,7 @@ using ShardingCore.Core.Internal.Visitors; using ShardingCore.Core.Internal.Visitors.GroupBys; using ShardingCore.Core.Internal.Visitors.Selects; using ShardingCore.Core.ShardingAccessors; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine; using ShardingCore.DbContexts; using ShardingCore.Extensions; @@ -23,8 +24,12 @@ namespace ShardingCore.Core.Internal.StreamMerge private readonly IShardingParallelDbContextFactory _shardingParallelDbContextFactory; private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IQueryable _source; + private readonly IDataSourceRoutingRuleEngineFactory _dataSourceRoutingRuleEngineFactory; + private readonly IRoutingRuleEngineFactory _tableRoutingRuleEngineFactory; + private readonly IQueryable _reWriteSource; - public IEnumerable RouteResults { get; } + //public IEnumerable RouteResults { get; } + //public DataSourceRoutingResult RoutingResult { get; } public int? Skip { get; private set; } public int? Take { get; private set; } public IEnumerable Orders { get; private set; } @@ -32,13 +37,14 @@ namespace ShardingCore.Core.Internal.StreamMerge public SelectContext SelectContext { get; private set; } public GroupByContext GroupByContext { get; private set; } - public StreamMergeContext(IQueryable source,IEnumerable routeResults, + public StreamMergeContext(IQueryable source, IDataSourceRoutingRuleEngineFactory dataSourceRoutingRuleEngineFactory,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory) { _shardingParallelDbContextFactory = shardingParallelDbContextFactory; _shardingScopeFactory = shardingScopeFactory; _source = source; - RouteResults = routeResults; + _dataSourceRoutingRuleEngineFactory = dataSourceRoutingRuleEngineFactory; + _tableRoutingRuleEngineFactory = tableRoutingRuleEngineFactory; var reWriteResult = new ReWriteEngine(source).ReWrite(); Skip = reWriteResult.Skip; Take = reWriteResult.Take; @@ -47,10 +53,34 @@ namespace ShardingCore.Core.Internal.StreamMerge GroupByContext = reWriteResult.GroupByContext; _reWriteSource = reWriteResult.ReWriteQueryable; } + //public StreamMergeContext(IQueryable source,IEnumerable routeResults, + // IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory) + //{ + // _shardingParallelDbContextFactory = shardingParallelDbContextFactory; + // _shardingScopeFactory = shardingScopeFactory; + // _source = source; + // RouteResults = routeResults; + // var reWriteResult = new ReWriteEngine(source).ReWrite(); + // Skip = reWriteResult.Skip; + // Take = reWriteResult.Take; + // Orders = reWriteResult.Orders ?? Enumerable.Empty(); + // SelectContext = reWriteResult.SelectContext; + // GroupByContext = reWriteResult.GroupByContext; + // _reWriteSource = reWriteResult.ReWriteQueryable; + //} - public DbContext CreateDbContext() + public DbContext CreateDbContext(string connectKey) { - return _shardingParallelDbContextFactory.Create(string.Empty); + return _shardingParallelDbContextFactory.Create(connectKey, string.Empty); + } + + public DataSourceRoutingResult GetDataSourceRoutingResult() + { + return _dataSourceRoutingRuleEngineFactory.Route(_source); + } + public IEnumerable GetRouteResults(string connectKey) + { + return _tableRoutingRuleEngineFactory.Route(connectKey,_source); } public ShardingScope CreateScope() diff --git a/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContextFactory.cs b/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContextFactory.cs index f20e1150..afbaa1d3 100644 --- a/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContextFactory.cs +++ b/src/ShardingCore/Core/Internal/StreamMerge/StreamMergeContextFactory.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using ShardingCore.Core.Internal.RoutingRuleEngines; using ShardingCore.Core.ShardingAccessors; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine; using ShardingCore.DbContexts; namespace ShardingCore.Core.Internal.StreamMerge @@ -18,24 +19,35 @@ namespace ShardingCore.Core.Internal.StreamMerge private readonly IShardingParallelDbContextFactory _shardingParallelDbContextFactory; private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IRoutingRuleEngineFactory _routingRuleEngineFactory; + private readonly IDataSourceRoutingRuleEngineFactory _dataSourceRoutingRuleEngineFactory; - public StreamMergeContextFactory(IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory,IRoutingRuleEngineFactory routingRuleEngineFactory) + public StreamMergeContextFactory(IShardingParallelDbContextFactory shardingParallelDbContextFactory, + IShardingScopeFactory shardingScopeFactory, + IRoutingRuleEngineFactory routingRuleEngineFactory, + IDataSourceRoutingRuleEngineFactory dataSourceRoutingRuleEngineFactory) { _shardingParallelDbContextFactory = shardingParallelDbContextFactory; _shardingScopeFactory = shardingScopeFactory; _routingRuleEngineFactory = routingRuleEngineFactory; + _dataSourceRoutingRuleEngineFactory = dataSourceRoutingRuleEngineFactory; } - public StreamMergeContext Create(IQueryable queryable, IEnumerable routeResults) - { - return new StreamMergeContext(queryable, routeResults, _shardingParallelDbContextFactory, _shardingScopeFactory); - } + //public StreamMergeContext Create(IQueryable queryable, IEnumerable routeResults) + //{ + // return new StreamMergeContext(queryable, routeResults, _shardingParallelDbContextFactory, _shardingScopeFactory); + //} + //public StreamMergeContext Create(IQueryable queryable, DataSourceRoutingResult dataSourceRoutingResult) + //{ + // return new StreamMergeContext(queryable, dataSourceRoutingResult, _shardingParallelDbContextFactory, _shardingScopeFactory); + //} public StreamMergeContext Create(IQueryable queryable) { - return new StreamMergeContext(queryable, _routingRuleEngineFactory.Route(queryable), _shardingParallelDbContextFactory, _shardingScopeFactory); + //return new StreamMergeContext(queryable, _routingRuleEngineFactory.Route(queryable), _shardingParallelDbContextFactory, _shardingScopeFactory); + return new StreamMergeContext(queryable, _dataSourceRoutingRuleEngineFactory, _routingRuleEngineFactory, _shardingParallelDbContextFactory, _shardingScopeFactory); } - public StreamMergeContext Create(IQueryable queryable,RouteRuleContext ruleContext) + public StreamMergeContext Create(IQueryable queryable,DataSourceRoutingRuleContext ruleContext) { - return new StreamMergeContext(queryable, _routingRuleEngineFactory.Route(queryable,ruleContext), _shardingParallelDbContextFactory, _shardingScopeFactory); + return new StreamMergeContext(queryable, _dataSourceRoutingRuleEngineFactory, _routingRuleEngineFactory, _shardingParallelDbContextFactory, _shardingScopeFactory); + //return new StreamMergeContext(queryable, _routingRuleEngineFactory.Route(queryable,ruleContext), _shardingParallelDbContextFactory, _shardingScopeFactory); } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/Internal/Visitors/QueryableRouteShardingDataSourceDiscoverVisitor.cs b/src/ShardingCore/Core/Internal/Visitors/QueryableRouteShardingDataSourceDiscoverVisitor.cs index c0c2bc7e..d5e93969 100644 --- a/src/ShardingCore/Core/Internal/Visitors/QueryableRouteShardingDataSourceDiscoverVisitor.cs +++ b/src/ShardingCore/Core/Internal/Visitors/QueryableRouteShardingDataSourceDiscoverVisitor.cs @@ -2,7 +2,6 @@ using System; using System.Collections; using System.Linq; using System.Linq.Expressions; -using ShardingCore.Core.PhysicDataSources; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Exceptions; using ShardingCore.Extensions; @@ -19,17 +18,17 @@ namespace ShardingCore.Core.Internal.Visitors { private readonly ShardingEntityBaseType _shardingEntityBaseType; private readonly Func _shardingKeyConvert; - private readonly Func>> _keyToDataSourceWithFilter; - private Expression> _where = x => true; + private readonly Func>> _keyToDataSourceWithFilter; + private Expression> _where = x => true; - public QueryableRouteShardingDataSourceDiscoverVisitor(ShardingEntityBaseType shardingEntityBaseType, Func shardingKeyConvert, Func>> keyToDataSourceWithFilter) + public QueryableRouteShardingDataSourceDiscoverVisitor(ShardingEntityBaseType shardingEntityBaseType, Func shardingKeyConvert, Func>> keyToDataSourceWithFilter) { _shardingEntityBaseType = shardingEntityBaseType; _shardingKeyConvert = shardingKeyConvert; _keyToDataSourceWithFilter = keyToDataSourceWithFilter; } - public Func GetDataSourceFilter() + public Func GetDataSourceFilter() { return _where.Compile(); } @@ -104,7 +103,7 @@ namespace ShardingCore.Core.Internal.Visitors } - private Expression> Resolve(Expression expression) + private Expression> Resolve(Expression expression) { if (expression is LambdaExpression) { @@ -135,7 +134,7 @@ namespace ShardingCore.Core.Internal.Visitors return o => true; } - private Expression> ResolveInFunc(MethodCallExpression methodCallExpression, bool @in) + private Expression> ResolveInFunc(MethodCallExpression methodCallExpression, bool @in) { if (methodCallExpression.IsEnumerableContains(methodCallExpression.Method.Name) && IsMethodWrapShardingKey(methodCallExpression)) { @@ -163,7 +162,7 @@ namespace ShardingCore.Core.Internal.Visitors if (arrayObject != null) { var enumerable = (IEnumerable) arrayObject; - Expression> contains = x => false; + Expression> contains = x => false; if (!@in) contains = x => true; foreach (var item in enumerable) @@ -183,10 +182,10 @@ namespace ShardingCore.Core.Internal.Visitors return x => true; } - private Expression> ParseGetWhere(BinaryExpression binaryExpression) + private Expression> ParseGetWhere(BinaryExpression binaryExpression) { - Expression> left = x => true; - Expression> right = x => true; + Expression> left = x => true; + Expression> right = x => true; //递归获取 if (binaryExpression.Left is BinaryExpression) diff --git a/src/ShardingCore/Core/Internal/Visitors/Querys/QueryEntitiesVisitor.cs b/src/ShardingCore/Core/Internal/Visitors/Querys/QueryEntitiesVisitor.cs index 53db98e7..5031313e 100644 --- a/src/ShardingCore/Core/Internal/Visitors/Querys/QueryEntitiesVisitor.cs +++ b/src/ShardingCore/Core/Internal/Visitors/Querys/QueryEntitiesVisitor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query; using ShardingCore.Extensions; diff --git a/src/ShardingCore/Core/Internal/Visitors/ShardingEntitiesVisitor.cs b/src/ShardingCore/Core/Internal/Visitors/ShardingEntitiesVisitor.cs index 204ce28d..df22c54c 100644 --- a/src/ShardingCore/Core/Internal/Visitors/ShardingEntitiesVisitor.cs +++ b/src/ShardingCore/Core/Internal/Visitors/ShardingEntitiesVisitor.cs @@ -28,7 +28,7 @@ namespace ShardingCore.Core.Internal.Visitors } protected override Expression VisitConstant(ConstantExpression node) { - if (node.Value is IQueryable queryable&&queryable.ElementType.IsShardingEntity()) + if (node.Value is IQueryable queryable&&queryable.ElementType.IsShardingTable()) { _shardingEntities.Add(queryable.ElementType); } @@ -54,7 +54,7 @@ namespace ShardingCore.Core.Internal.Visitors protected override Expression VisitExtension(Expression node) { - if (node is QueryRootExpression queryRootExpression&&queryRootExpression.EntityType.ClrType.IsShardingEntity()) + if (node is QueryRootExpression queryRootExpression&&queryRootExpression.EntityType.ClrType.IsShardingTable()) { _shardingEntities.Add(queryRootExpression.EntityType.ClrType); } diff --git a/src/ShardingCore/Core/PhysicDataSources/IPhysicDataSource.cs b/src/ShardingCore/Core/PhysicDataSources/IPhysicDataSource.cs deleted file mode 100644 index 74bcecda..00000000 --- a/src/ShardingCore/Core/PhysicDataSources/IPhysicDataSource.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using ShardingCore.Core.Internal; - -namespace ShardingCore.Core.PhysicDataSources -{ -/* -* @Author: xjm -* @Description: -* @Date: Friday, 05 February 2021 13:05:28 -* @Email: 326308290@qq.com -*/ - /// - /// 物理表接口 - /// - public interface IPhysicDataSource - { - /// - /// 连接字符串 - /// - string GetConnectionString(); - - /// - /// 数据源类型 - /// - DataSourceEnum GetDataSourceType(); - - - /// - /// 添加分库实体 - /// - /// - void AddEntity(ShardingEntityBaseType entityBaseType); - - /// - /// 添加分库实体 - /// - /// - void AddEntity() where T : class, IShardingDataSource; - - /// - /// 添加分库实体 - /// - /// - void AddEntity(Type shardingEntity); - /// - /// 是否有对应的实体 - /// - /// - /// - bool HasEntity(Type shardingEntity); - /// - /// 是否有对应的实体 - /// - /// - bool HasEntity() where T : class, IShardingDataSource; - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/PhysicDataSources/PhysicDataSource.cs b/src/ShardingCore/Core/PhysicDataSources/PhysicDataSource.cs deleted file mode 100644 index aea72b12..00000000 --- a/src/ShardingCore/Core/PhysicDataSources/PhysicDataSource.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ShardingCore.Core.Internal; -using ShardingCore.Extensions; -using ShardingCore.Utils; - -namespace ShardingCore.Core.PhysicDataSources -{ -/* -* @Author: xjm -* @Description: -* @Date: Friday, 05 February 2021 13:47:49 -* @Email: 326308290@qq.com -*/ - public class PhysicDataSource:IPhysicDataSource - { - public string ConnectionString { get; } - private readonly DataSourceEnum _dataSourceType; - private readonly Dictionary _entities; - private readonly string _connectionString; - - public PhysicDataSource(string connectionString,DataSourceEnum dataSourceType) - { - _connectionString = connectionString; - _dataSourceType = dataSourceType; - _entities = new Dictionary(); - } - - public string GetConnectionString() - { - return _connectionString; - } - - public DataSourceEnum GetDataSourceType() - { - return _dataSourceType; - } - - public void AddEntity(ShardingEntityBaseType entityBaseType) - { - if(!_entities.ContainsKey(entityBaseType.EntityType)) - _entities.Add(entityBaseType.EntityType,entityBaseType); - } - - public void AddEntity() where T : class, IShardingDataSource - { - var entityType = typeof(T); - AddEntity(entityType); - } - - public void AddEntity(Type shardingEntity) - { - if (!shardingEntity.IsShardingDataSource()) - throw new InvalidOperationException($"entity:[{shardingEntity}] should from {nameof(IShardingDataSource)}"); - var entityBaseType = ShardingUtil.Parse(shardingEntity); - AddEntity(entityBaseType); - } - - public bool HasEntity(Type shardingEntity) - { - if (!shardingEntity.IsShardingDataSource()) - return false; - return _entities.ContainsKey(shardingEntity); - } - - public bool HasEntity() where T : class, IShardingDataSource - { - return HasEntity(typeof(T)); - } - - - } -} \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs b/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs index 1929f15b..19e6fc6c 100644 --- a/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs +++ b/src/ShardingCore/Core/ShardingAccessors/ShardingContext.cs @@ -13,8 +13,11 @@ namespace ShardingCore.Core.ShardingAccessors */ public class ShardingContext { - private ShardingContext(RouteResult routeResult) + public string ConnectKey { get; } + + private ShardingContext(string connectKey,RouteResult routeResult) { + ConnectKey = connectKey; foreach (var physicTable in routeResult.ReplaceTables) { _shardingTables.Add(physicTable.VirtualTable, new List(1){physicTable.Tail}); @@ -41,9 +44,9 @@ namespace ShardingCore.Core.ShardingAccessors /// 创建一个分表上下文 /// /// - public static ShardingContext Create(RouteResult routeResult) + public static ShardingContext Create(string connectKey, RouteResult routeResult) { - return new ShardingContext(routeResult); + return new ShardingContext(connectKey,routeResult); } /// diff --git a/src/ShardingCore/Core/ShardingDataSourceConfig.cs b/src/ShardingCore/Core/ShardingDataSourceConfig.cs new file mode 100644 index 00000000..cb93e89b --- /dev/null +++ b/src/ShardingCore/Core/ShardingDataSourceConfig.cs @@ -0,0 +1,53 @@ +//using System; +//using System.Collections.Generic; +//using System.Text; + +//namespace ShardingCore.Core +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: 2021/3/2 15:06:18 +// * @Ver: 1.0 +// * @Email: 326308290@qq.com +// */ +// public class ShardingDataSourceConfig +// { +// public ShardingDataSourceConfig(string connectKey, string connectionString) +// { +// ConnectKey = connectKey; +// ConnectionString = connectionString; +// Entities = new HashSet(); +// } + +// /// +// /// 连接标识 +// /// +// public string ConnectKey { get; } + +// /// +// /// 连接字符串 +// /// +// public string ConnectionString { get; } + +// public ISet Entities { get; } + +// public override int GetHashCode() +// { +// return this.ConnectKey.GetHashCode() ^ 31; +// } + +// public override bool Equals(object obj) +// { +// if (!(obj is ShardingDataSourceConfig)) +// return false; + +// if (ReferenceEquals(this, obj)) +// return true; + +// ShardingDataSourceConfig item = (ShardingDataSourceConfig)obj; + +// return item.ConnectKey == this.ConnectKey; +// } +// } +//} diff --git a/src/ShardingCore/Core/ShardingDataSourceKeyAttribute.cs b/src/ShardingCore/Core/ShardingDataSourceKeyAttribute.cs index 007ec8c5..59412fb5 100644 --- a/src/ShardingCore/Core/ShardingDataSourceKeyAttribute.cs +++ b/src/ShardingCore/Core/ShardingDataSourceKeyAttribute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Core /// 数据源分库规则字段 /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] - public class ShardingDataSourceKeyAttribute + public class ShardingDataSourceKeyAttribute: Attribute { } } \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingDataSources/IShardingDataSourceManager.cs b/src/ShardingCore/Core/ShardingDataSources/IShardingDataSourceManager.cs index 1f03d72c..0e86bf1c 100644 --- a/src/ShardingCore/Core/ShardingDataSources/IShardingDataSourceManager.cs +++ b/src/ShardingCore/Core/ShardingDataSources/IShardingDataSourceManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.EntityFrameworkCore; namespace ShardingCore.Core.ShardingDataSources @@ -32,5 +33,6 @@ namespace ShardingCore.Core.ShardingDataSources bool IsShardingDataSource(); public IEnumerable FilterDataSources(ISet queryEntities); + } } \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceEntry.cs b/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceEntry.cs index 804b7606..ad13235c 100644 --- a/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceEntry.cs +++ b/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceEntry.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; namespace ShardingCore.Core.ShardingDataSources { @@ -20,7 +21,7 @@ namespace ShardingCore.Core.ShardingDataSources /// /// /// - public ShardingDataSourceEntry(Type entityType,ShardingDataSourceDbEntry dataSourceDbEntry) + public ShardingDataSourceEntry(Type entityType, ShardingDataSourceDbEntry dataSourceDbEntry) { EntityType = entityType; DataSourceDbEntry = dataSourceDbEntry; @@ -35,5 +36,23 @@ namespace ShardingCore.Core.ShardingDataSources /// 分库对应的数据库对象 /// public ShardingDataSourceDbEntry DataSourceDbEntry { get; } + + public override int GetHashCode() + { + return this.EntityType.GetHashCode() ^ 31; + } + + public override bool Equals(object obj) + { + if (!(obj is ShardingDataSourceEntry)) + return false; + + if (ReferenceEquals(this, obj)) + return true; + + ShardingDataSourceEntry item = (ShardingDataSourceEntry) obj; + + return item.EntityType == this.EntityType; + } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceManager.cs b/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceManager.cs index 534b1f28..0a74da70 100644 --- a/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceManager.cs +++ b/src/ShardingCore/Core/ShardingDataSources/ShardingDataSourceManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; +using ShardingCore.Extensions; namespace ShardingCore.Core.ShardingDataSources { diff --git a/src/ShardingCore/Core/ShardingQueryable.cs b/src/ShardingCore/Core/ShardingQueryable.cs index 9a95600d..7dab9767 100644 --- a/src/ShardingCore/Core/ShardingQueryable.cs +++ b/src/ShardingCore/Core/ShardingQueryable.cs @@ -9,6 +9,7 @@ using ShardingCore.Core.Internal.RoutingRuleEngines; using ShardingCore.Core.Internal.StreamMerge; using ShardingCore.Core.Internal.StreamMerge.GenericMerges; using ShardingCore.Core.Internal.StreamMerge.GenericMerges.Proxies; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine; using ShardingCore.Core.VirtualTables; using ShardingCore.Extensions; #if EFCORE2 @@ -32,15 +33,18 @@ namespace ShardingCore.Core { private IQueryable _source; private readonly IStreamMergeContextFactory _streamMergeContextFactory; - private readonly RouteRuleContext _routeRuleContext; + //private readonly RouteRuleContext _routeRuleContext; + private readonly DataSourceRoutingRuleContext _dataSourceRoutingRuleContext; private ShardingQueryable(IQueryable source) { _source = source; _streamMergeContextFactory = ShardingContainer.Services.GetService(); - var routingRuleEngineFactory=ShardingContainer.Services.GetService(); - _routeRuleContext = routingRuleEngineFactory.CreateContext(source); + //var routingRuleEngineFactory=ShardingContainer.Services.GetService(); + var dataSourceRoutingRuleEngineFactory=ShardingContainer.Services.GetService(); + //_routeRuleContext = routingRuleEngineFactory.CreateContext(source); + _dataSourceRoutingRuleContext = dataSourceRoutingRuleEngineFactory.CreateContext(source); } public static ShardingQueryable Create(IQueryable source) @@ -51,33 +55,37 @@ namespace ShardingCore.Core public IShardingQueryable EnableAutoRouteParse() { - _routeRuleContext.EnableAutoRouteParse(); - return this; + throw new NotImplementedException(); + //_routeRuleContext.EnableAutoRouteParse(); + //return this; } public IShardingQueryable DisableAutoRouteParse() { - _routeRuleContext.DisableAutoRouteParse(); - return this; + throw new NotImplementedException(); + //_routeRuleContext.DisableAutoRouteParse(); + //return this; } public IShardingQueryable AddManualRoute(Expression> predicate) where TShardingEntity : class, IShardingEntity { - _routeRuleContext.AddRoute(predicate); - return this; + throw new NotImplementedException(); + //_routeRuleContext.AddRoute(predicate); + //return this; } public IShardingQueryable AddManualRoute( string tail) where TShardingEntity : class, IShardingEntity { - _routeRuleContext.AddRoute(tail); + throw new NotImplementedException(); + //_routeRuleContext.AddRoute(tail); - return this; + //return this; } private StreamMergeContext GetContext() { - return _streamMergeContextFactory.Create(_source,_routeRuleContext); + return _streamMergeContextFactory.Create(_source,_dataSourceRoutingRuleContext); } private async Task> GetGenericMergeEngine(Func> efQuery) { diff --git a/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSource.cs b/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSource.cs index ded944a7..2022f18c 100644 --- a/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSource.cs +++ b/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSource.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using ShardingCore.Core.PhysicDataSources; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; @@ -19,32 +18,21 @@ namespace ShardingCore.Core.VirtualDataSources public interface IVirtualDataSource { Type EntityType{get;} - /// - /// 获取所有的物理数据源 - /// - /// - List GetAllDataSources(); /// /// 路由到具体的物理数据源 /// /// - List RouteTo(VirutalDataSourceConfig routeConfig); - - /// - /// 添加物理表 add physic table - /// - /// - void AddDataSource(IPhysicDataSource physicTable); + List RouteTo(VirutalDataSourceRouteConfig routeRouteConfig); /// /// 获取当前数据源的路由 /// /// - IVirtualDataSourceRoute GetRoute(); + IDataSourceVirtualRoute GetRoute(); } public interface IVirtualDataSource : IVirtualDataSource where T : class, IShardingDataSource { - new IVirtualDataSourceRoute GetRoute(); + new IDataSourceVirtualRoute GetRoute(); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSourceManager.cs index b3244cde..3aa2901a 100644 --- a/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSourceManager.cs +++ b/src/ShardingCore/Core/VirtualDataSources/IVirtualDataSourceManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using ShardingCore.Core.PhysicDataSources; namespace ShardingCore.Core.VirtualDataSources { @@ -12,11 +11,37 @@ namespace ShardingCore.Core.VirtualDataSources */ public interface IVirtualDataSourceManager { + /// + /// 添加链接 + /// + /// + void AddShardingConnectKey(string connectKey); + /// + /// 获取所有的链接 + /// + /// + ISet GetAllShardingConnectKeys(); + + + /// + /// 添加虚拟数据源应用启动时 add virtual table when app start + /// + /// + void AddVirtualDataSource(IVirtualDataSource virtualDataSource); /// /// 获取所有的虚拟连接 get all virtual table /// /// List GetAllVirtualDataSources(); + + /// + /// 添加链接对应的对象 + /// + /// + /// + void AddConnectEntities(string connectKey,Type entityType); + + /// /// 获取虚拟表 get virtual table by sharding entity type /// @@ -29,23 +54,11 @@ namespace ShardingCore.Core.VirtualDataSources /// IVirtualDataSource GetVirtualDataSource() where T:class,IShardingDataSource; - - /// - /// 添加虚拟数据源应用启动时 add virtual table when app start - /// - /// - void AddVirtualDataSource(IVirtualDataSource virtualDataSource); - /// - /// 添加物理表 add physic table - /// - /// - /// - void AddPhysicDataSource(IVirtualDataSource virtualDataSource, IPhysicDataSource physicDataSource); - /// - /// 添加物理表 add physic table - /// - /// - /// - void AddPhysicDataSource(Type shardingEntityType, IPhysicDataSource physicDataSource); + string GetDefaultConnectKey(); + bool IsShardingDataSource(); + bool HasVirtualShardingDataSourceRoute(Type shardingEntityType); + + List GetEntityTypeLinkedConnectKeys(Type shardingEntityType); + } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDataSources/VirtualDataSource.cs b/src/ShardingCore/Core/VirtualDataSources/VirtualDataSource.cs index ead63982..d4760957 100644 --- a/src/ShardingCore/Core/VirtualDataSources/VirtualDataSource.cs +++ b/src/ShardingCore/Core/VirtualDataSources/VirtualDataSource.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using ShardingCore.Core.PhysicDataSources; +using System.Reflection; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; using Microsoft.Extensions.DependencyInjection; using ShardingCore.Core.Internal; @@ -20,62 +20,55 @@ namespace ShardingCore.Core.VirtualDataSources */ public class VirtualDataSource:IVirtualDataSource where T:class,IShardingDataSource { - private readonly List _physicDataSources; - private readonly IVirtualDataSourceRoute _virtualDataSourceRoute; + private readonly IServiceProvider _serviceProvider; + private readonly IDataSourceVirtualRoute _dataSourceVirtualRoute; public ShardingEntityBaseType ShardingEntityType { get; } public Type EntityType { get; } - public VirtualDataSource(IServiceProvider serviceProvider) + public VirtualDataSource(IServiceProvider serviceProvider, IDataSourceVirtualRoute virtualRoute) { - _physicDataSources = new List(); - _virtualDataSourceRoute = serviceProvider.GetService>() ?? throw new ArgumentNullException($"{typeof(T)}"); + _serviceProvider = serviceProvider; + _dataSourceVirtualRoute = virtualRoute; EntityType = typeof(T); ShardingEntityType = ShardingUtil.Parse(EntityType); } - public List GetAllDataSources() - { - return _physicDataSources; - } - public List RouteTo(VirutalDataSourceConfig routeConfig) + public List RouteTo(VirutalDataSourceRouteConfig routeRouteConfig) { - if (routeConfig.UseQueryable()) - return _virtualDataSourceRoute.RouteWithWhere(_physicDataSources, routeConfig.GetQueryable()); - if (routeConfig.UsePredicate()) - return _virtualDataSourceRoute.RouteWithWhere(_physicDataSources, new EnumerableQuery((Expression>) routeConfig.GetPredicate())); + //ȡеԴ + var virtualDataSourceManager = _serviceProvider.GetService(); + var allShardingDataSourceConfigs = virtualDataSourceManager.GetAllShardingConnectKeys(); + + if (routeRouteConfig.UseQueryable()) + return _dataSourceVirtualRoute.RouteWithWhere(allShardingDataSourceConfigs.ToList(), routeRouteConfig.GetQueryable()); + if (routeRouteConfig.UsePredicate()) + return _dataSourceVirtualRoute.RouteWithWhere(allShardingDataSourceConfigs.ToList(), new EnumerableQuery((Expression>) routeRouteConfig.GetPredicate())); object shardingKeyValue = null; - if (routeConfig.UseValue()) - shardingKeyValue = routeConfig.GetShardingKeyValue(); + if (routeRouteConfig.UseValue()) + shardingKeyValue = routeRouteConfig.GetShardingKeyValue(); - if (routeConfig.UseEntity()) - shardingKeyValue = routeConfig.GetShardingDataSource().GetPropertyValue(ShardingEntityType.ShardingDataSourceField); + if (routeRouteConfig.UseEntity()) + shardingKeyValue = routeRouteConfig.GetShardingDataSource().GetPropertyValue(ShardingEntityType.ShardingDataSourceField); if (shardingKeyValue != null) { - var routeWithValue = _virtualDataSourceRoute.RouteWithValue(_physicDataSources, shardingKeyValue); - return new List(1) {routeWithValue}; + var routeWithValue = _dataSourceVirtualRoute.RouteWithValue(allShardingDataSourceConfigs.ToList(), shardingKeyValue); + return new List(1) {routeWithValue}; } - throw new NotImplementedException(nameof(VirutalDataSourceConfig)); + throw new NotImplementedException(nameof(VirutalDataSourceRouteConfig)); } - public void AddDataSource(IPhysicDataSource physicTable) + IDataSourceVirtualRoute IVirtualDataSource.GetRoute() { - if (_physicDataSources.Any(o => o.GetConnectionString() == physicTable.GetConnectionString())) - return; - _physicDataSources.Add(physicTable); + return _dataSourceVirtualRoute; } - IVirtualDataSourceRoute IVirtualDataSource.GetRoute() + public IDataSourceVirtualRoute GetRoute() { - return _virtualDataSourceRoute; - } - - public IVirtualDataSourceRoute GetRoute() - { - return _virtualDataSourceRoute; + return _dataSourceVirtualRoute; } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDataSources/VirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDataSources/VirtualDataSourceManager.cs index 9f4fb682..0a803954 100644 --- a/src/ShardingCore/Core/VirtualDataSources/VirtualDataSourceManager.cs +++ b/src/ShardingCore/Core/VirtualDataSources/VirtualDataSourceManager.cs @@ -2,42 +2,76 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using ShardingCore.Core.PhysicDataSources; using ShardingCore.Exceptions; +using ShardingCore.Extensions; using ShardingCore.Helpers; namespace ShardingCore.Core.VirtualDataSources { -/* -* @Author: xjm -* @Description: -* @Date: Saturday, 06 February 2021 15:24:08 -* @Email: 326308290@qq.com -*/ - public class VirtualDataSourceManager:IVirtualDataSourceManager + /* + * @Author: xjm + * @Description: + * @Date: Saturday, 06 February 2021 15:24:08 + * @Email: 326308290@qq.com + */ + public class VirtualDataSourceManager : IVirtualDataSourceManager { + private readonly IServiceProvider _serviceProvider; private readonly ConcurrentDictionary _virtualDataSources = new ConcurrentDictionary(); + private readonly Dictionary> _shardingConnectKeys = new Dictionary>(); + private readonly Dictionary> _entityTypeConnectKeyIndex = new Dictionary>(); + public VirtualDataSourceManager(IServiceProvider 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); - } + _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 ISet GetAllShardingConnectKeys() + { + return _shardingConnectKeys.Keys.ToHashSet(); + } + + public List GetAllVirtualDataSources() { return _virtualDataSources.Select(o => o.Value).ToList(); } + public void AddConnectEntities(string connectKey, Type entityType) + { + if (!_shardingConnectKeys.ContainsKey(connectKey)) + throw new ShardingCoreException("connectKey not init"); + _shardingConnectKeys[connectKey].Add(entityType); + BuildIndex(connectKey, entityType); + } + + private void BuildIndex(string connectKey, Type entityType) + { + + if (_entityTypeConnectKeyIndex.ContainsKey(entityType)) + { + _entityTypeConnectKeyIndex[entityType].Add(connectKey); + } + else + { + _entityTypeConnectKeyIndex.Add(entityType,new HashSet(){ connectKey + }); + } + } + public IVirtualDataSource GetVirtualDataSource(Type shardingEntityType) { if (!_virtualDataSources.TryGetValue(shardingEntityType, out var virtualTable) || virtualTable == null) @@ -50,21 +84,37 @@ namespace ShardingCore.Core.VirtualDataSources return (IVirtualDataSource)GetVirtualDataSource(typeof(T)); } + public string GetDefaultConnectKey() + { + return _shardingConnectKeys.Keys.FirstOrDefault(); + } + + public bool IsShardingDataSource() + { + return _shardingConnectKeys.Count > 1; + } + + public bool HasVirtualShardingDataSourceRoute(Type shardingEntityType) + { + return _virtualDataSources.ContainsKey(shardingEntityType); + } + + public List GetEntityTypeLinkedConnectKeys(Type shardingEntityType) + { + if (!_entityTypeConnectKeyIndex.ContainsKey(shardingEntityType)) + throw new ShardingCoreException($"entity:[{shardingEntityType}] not found"); + return _entityTypeConnectKeyIndex[shardingEntityType].ToList(); + } + + public void AddShardingConnectKey(string connectKey) + { + if (!_shardingConnectKeys.ContainsKey(connectKey)) + _shardingConnectKeys.Add(connectKey,new HashSet()); + } + public void AddVirtualDataSource(IVirtualDataSource virtualDataSource) { _virtualDataSources.TryAdd(virtualDataSource.EntityType, virtualDataSource); } - - public void AddPhysicDataSource(IVirtualDataSource virtualDataSource, IPhysicDataSource physicDataSource) - { - AddPhysicDataSource(virtualDataSource.EntityType, physicDataSource); - } - - public void AddPhysicDataSource(Type shardingEntityType, IPhysicDataSource physicDataSource) - { - var virtualTable = GetVirtualDataSource(shardingEntityType); - virtualTable.AddDataSource(physicDataSource); - } - } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDataSources/VirutalDataSourceConfig.cs b/src/ShardingCore/Core/VirtualDataSources/VirutalDataSourceRouteConfig.cs similarity index 86% rename from src/ShardingCore/Core/VirtualDataSources/VirutalDataSourceConfig.cs rename to src/ShardingCore/Core/VirtualDataSources/VirutalDataSourceRouteConfig.cs index ac4c8bd6..a6b3a83e 100644 --- a/src/ShardingCore/Core/VirtualDataSources/VirutalDataSourceConfig.cs +++ b/src/ShardingCore/Core/VirtualDataSources/VirutalDataSourceRouteConfig.cs @@ -10,7 +10,7 @@ namespace ShardingCore.Core.VirtualDataSources * @Date: Saturday, 06 February 2021 11:28:33 * @Email: 326308290@qq.com */ - public class VirutalDataSourceConfig + public class VirutalDataSourceRouteConfig { private readonly IQueryable _queryable; @@ -19,7 +19,7 @@ namespace ShardingCore.Core.VirtualDataSources private readonly Expression _predicate; - public VirutalDataSourceConfig(IQueryable queryable=null,IShardingDataSource shardingDataSource=null,object shardingKeyValue=null,Expression predicate=null) + public VirutalDataSourceRouteConfig(IQueryable queryable=null,IShardingDataSource shardingDataSource=null,object shardingKeyValue=null,Expression predicate=null) { _queryable = queryable; _shardingDataSource = shardingDataSource; diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractDataSourceVirtualRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractDataSourceVirtualRoute.cs index dbe4daf2..30a383dc 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractDataSourceVirtualRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractDataSourceVirtualRoute.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using ShardingCore.Core.PhysicDataSources; namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes { @@ -11,10 +10,10 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes * @Date: Friday, 05 February 2021 17:06:49 * @Email: 326308290@qq.com */ - public abstract class AbstractDataSourceVirtualRoute:IVirtualDataSourceRoute where T:class,IShardingDataSource + public abstract class AbstractDataSourceVirtualRoute:IDataSourceVirtualRoute where T:class,IShardingDataSource { public Type ShardingEntityType => typeof(T); - public abstract IPhysicDataSource RouteWithValue(List allPhysicDataSources, object shardingKey); + public abstract string RouteWithValue(List allConnectKeys, object shardingKey); protected abstract TKey ConvertToShardingKey(object shardingKey); @@ -24,24 +23,24 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes /// /// /// - public List RouteWithWhere(List allPhysicDataSources, IQueryable queryable) + public List RouteWithWhere(List allPhysicDataSources, IQueryable queryable) { return AfterFilter(allPhysicDataSources,DoRouteWithWhere(allPhysicDataSources,queryable)); } /// /// 实际路由 /// - /// + /// /// /// - protected abstract List DoRouteWithWhere(List allPhysicDataSources, IQueryable queryable); + protected abstract List DoRouteWithWhere(List allShardingDataSourceConfigs, IQueryable queryable); /// /// 物理表过滤后 /// /// 所有的数据源 /// 过滤后的数据源 /// - public virtual List AfterFilter(List allPhysicDataSources,List filterPhysicDataSources) + public virtual List AfterFilter(List allPhysicDataSources,List filterPhysicDataSources) { return filterPhysicDataSources; } diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractShardingDataSourceOperatorVirtualRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractShardingDataSourceOperatorVirtualRoute.cs index 6c017b91..d6e06773 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractShardingDataSourceOperatorVirtualRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/AbstractShardingDataSourceOperatorVirtualRoute.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using ShardingCore.Core.PhysicDataSources; using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.Utils; @@ -23,18 +22,18 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes /// 分表的值 /// 操作 /// 如果返回true表示返回该表 第一个参数 tail 第二参数是否返回该物理表 - protected abstract Expression> GetRouteToFilter(TKey shardingKey, ShardingOperatorEnum shardingOperator); + protected abstract Expression> GetRouteToFilter(TKey shardingKey, ShardingOperatorEnum shardingOperator); /// /// 通过iqueryable来解析本次路由到的具体数据源 /// - /// + /// /// /// - protected override List DoRouteWithWhere(List allPhysicDataSources, IQueryable queryable) + protected override List DoRouteWithWhere(List allShardingDataSourceConfigs, IQueryable queryable) { //获取所有需要路由的表后缀 var filter = ShardingUtil.GetRouteDataSourceFilter(queryable, ShardingUtil.Parse(typeof(T)), ConvertToShardingKey, GetRouteToFilter); - var physicTables = allPhysicDataSources.Where(o => filter(o)).ToList(); + var physicTables = allShardingDataSourceConfigs.Where(o => filter(o)).ToList(); return physicTables; } /// @@ -45,7 +44,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes /// /// /// - public override IPhysicDataSource RouteWithValue(List allPhysicDataSources, object shardingKey) + public override string RouteWithValue(List allPhysicDataSources, object shardingKey) { var filter = GetRouteToFilter(ConvertToShardingKey(shardingKey), ShardingOperatorEnum.Equal).Compile(); @@ -57,7 +56,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes } if (physicDataSources.Count > 1) - throw new ShardingDataSourceRouteMatchMoreException($"data source :{string.Join(",", physicDataSources.Select(o => $"[{o.GetDataSourceType()}]"))}"); + throw new ShardingDataSourceRouteMatchMoreException($"data source :{string.Join(",", physicDataSources.Select(o => $"[{o}]"))}"); return physicDataSources[0]; } } diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/DataSourceRouteConfig.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/DataSourceRouteConfig.cs new file mode 100644 index 00000000..8f2fa36a --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/DataSourceRouteConfig.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/2 16:08:34 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DataSourceRouteConfig + { + private readonly IQueryable _queryable; + private readonly IShardingDataSource _shardingDataSource; + private readonly object _shardingKeyValue; + private readonly Expression _predicate; + + + public DataSourceRouteConfig(IQueryable queryable = null, IShardingDataSource shardingDataSource = null, object shardingKeyValue = null, Expression predicate = null) + { + _queryable = queryable; + _shardingDataSource = shardingDataSource; + _shardingKeyValue = shardingKeyValue; + _predicate = predicate; + } + + public IQueryable GetQueryable() + { + return _queryable; + } + public object GetShardingKeyValue() + { + return _shardingKeyValue; + } + + public IShardingDataSource GetShardingDataSource() + { + return _shardingDataSource; + } + + public Expression GetPredicate() + { + return _predicate; + } + + public bool UseQueryable() + { + return _queryable != null; + } + + public bool UseValue() + { + return _shardingKeyValue != null; + } + + public bool UseEntity() + { + return _shardingDataSource != null; + } + + public bool UsePredicate() + { + return _predicate != null; + } + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IDataSourceVirtualRoute.cs similarity index 64% rename from src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs rename to src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IDataSourceVirtualRoute.cs index b7d571b4..38383f22 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/IDataSourceVirtualRoute.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using ShardingCore.Core.PhysicDataSources; namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes { @@ -11,7 +10,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes * @Date: Friday, 05 February 2021 13:03:58 * @Email: 326308290@qq.com */ - public interface IVirtualDataSourceRoute + public interface IDataSourceVirtualRoute { Type ShardingEntityType { get; } @@ -21,7 +20,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes /// /// /// - List RouteWithWhere(List allPhysicDataSources,IQueryable queryable); + List RouteWithWhere(List allPhysicDataSources,IQueryable queryable); /// /// 根据值进行路由 @@ -29,11 +28,11 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes /// /// /// - IPhysicDataSource RouteWithValue(List allPhysicDataSources, object shardingKeyValue); + string RouteWithValue(List allPhysicDataSources, object shardingKeyValue); } - public interface IVirtualDataSourceRoute : IVirtualDataSourceRoute where T : class, IShardingDataSource + public interface IDataSourceVirtualRoute : IDataSourceVirtualRoute where T : class, IShardingDataSource { } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingResult.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingResult.cs new file mode 100644 index 00000000..c13893c8 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingResult.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/2 16:13:49 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DataSourceRoutingResult + { + public DataSourceRoutingResult(ISet intersectConfigs) + { + IntersectConfigs = intersectConfigs; + } + /// + /// 交集 + /// + public ISet IntersectConfigs { get; } + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleContext.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleContext.cs new file mode 100644 index 00000000..ff6c4053 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleContext.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ShardingCore.Core.VirtualDataSources; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/2 16:17:05 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DataSourceRoutingRuleContext + { + + public DataSourceRoutingRuleContext(IQueryable queryable) + { + Queryable = queryable; + } + /// + /// 查询条件 + /// + public IQueryable Queryable { get; } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleEngine.cs new file mode 100644 index 00000000..ecd0865a --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleEngine.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ShardingCore.Core.Internal.RoutingRuleEngines; +using ShardingCore.Core.PhysicTables; +using ShardingCore.Core.VirtualDataSources; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.Core.VirtualTables; +using ShardingCore.Extensions; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/2 16:20:37 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DataSourceRoutingRuleEngine: IDataSourceRoutingRuleEngine + { + private readonly IVirtualDataSourceManager _virtualDataSourceManager; + + public DataSourceRoutingRuleEngine(IVirtualDataSourceManager virtualDataSourceManager) + { + _virtualDataSourceManager = virtualDataSourceManager; + } + + public DataSourceRoutingResult Route(DataSourceRoutingRuleContext routingRuleContext) + { + var queryEntities = routingRuleContext.Queryable.ParseQueryableRoute().Where(o=>o.IsShardingDataSource()).ToList(); + if (queryEntities.IsEmpty()) + return new DataSourceRoutingResult(_virtualDataSourceManager.GetAllShardingConnectKeys()); + + var dataSourceMaps = new Dictionary>(); + foreach (var queryEntity in queryEntities) + { + var virtualDataSource = _virtualDataSourceManager.GetVirtualDataSource(queryEntity); + var dataSourceConfigs = virtualDataSource.RouteTo(new VirutalDataSourceRouteConfig(routingRuleContext.Queryable)); + if (!dataSourceMaps.ContainsKey(queryEntity)) + { + dataSourceMaps.Add(queryEntity, dataSourceConfigs.ToHashSet()); + } + else + { + foreach (var shardingDataSource in dataSourceConfigs) + { + dataSourceMaps[queryEntity].Add(shardingDataSource); + } + } + } + + if (dataSourceMaps.IsEmpty()) + return new DataSourceRoutingResult(new HashSet()); + if(dataSourceMaps.Count==1) + return new DataSourceRoutingResult(dataSourceMaps.FirstOrDefault().Value); + var intersect = dataSourceMaps.Select(o => o.Value).Aggregate((p, n) => p.Intersect(n).ToHashSet()); + return new DataSourceRoutingResult(intersect); + } + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleEngineFactory.cs new file mode 100644 index 00000000..6a1e0e98 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/DataSourceRoutingRuleEngineFactory.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ShardingCore.Core.VirtualDataSources; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/3 8:39:34 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class DataSourceRoutingRuleEngineFactory:IDataSourceRoutingRuleEngineFactory + + { + private readonly IDataSourceRoutingRuleEngine _routeRuleEngine; + + public DataSourceRoutingRuleEngineFactory(IDataSourceRoutingRuleEngine routeRuleEngine) + { + _routeRuleEngine = routeRuleEngine; + } + + public IDataSourceRoutingRuleEngine CreateEngine() + { + return _routeRuleEngine; + } + + public DataSourceRoutingRuleContext CreateContext(IQueryable queryable) + { + return new DataSourceRoutingRuleContext(queryable); + } + + public DataSourceRoutingResult Route(IQueryable queryable) + { + var engine = CreateEngine(); + var ruleContext = CreateContext(queryable); + return engine.Route(ruleContext); + } + + public DataSourceRoutingResult Route(IQueryable queryable, DataSourceRoutingRuleContext ruleContext) + { + var engine = CreateEngine(); + return engine.Route(ruleContext); + } + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/IDataSourceRoutingRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/IDataSourceRoutingRuleEngine.cs new file mode 100644 index 00000000..78204410 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/IDataSourceRoutingRuleEngine.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/2 16:13:12 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + /// + /// 分库路由引擎 + /// + public interface IDataSourceRoutingRuleEngine + { + DataSourceRoutingResult Route(DataSourceRoutingRuleContext routingRuleContext); + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/IDataSourceRoutingRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/IDataSourceRoutingRuleEngineFactory.cs new file mode 100644 index 00000000..b85653c4 --- /dev/null +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RoutingRuleEngine/IDataSourceRoutingRuleEngineFactory.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RoutingRuleEngine +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/3 8:32:30 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public interface IDataSourceRoutingRuleEngineFactory + { + IDataSourceRoutingRuleEngine CreateEngine(); + DataSourceRoutingRuleContext CreateContext(IQueryable queryable); + DataSourceRoutingResult Route(IQueryable queryable); + DataSourceRoutingResult Route(IQueryable queryable, DataSourceRoutingRuleContext ruleContext); + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/Abstractions/AbstractShardingOperatorVirtualRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/AbstractShardingOperatorVirtualRoute.cs similarity index 97% rename from src/ShardingCore/Core/VirtualRoutes/Abstractions/AbstractShardingOperatorVirtualRoute.cs rename to src/ShardingCore/Core/VirtualRoutes/TableRoutes/AbstractShardingOperatorVirtualRoute.cs index ca3325cf..42318380 100644 --- a/src/ShardingCore/Core/VirtualRoutes/Abstractions/AbstractShardingOperatorVirtualRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/AbstractShardingOperatorVirtualRoute.cs @@ -7,7 +7,7 @@ using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.Utils; -namespace ShardingCore.Core.VirtualRoutes.Abstractions +namespace ShardingCore.Core.VirtualRoutes.TableRoutes { /* * @Author: xjm diff --git a/src/ShardingCore/Core/VirtualRoutes/Abstractions/AbstractVirtualRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/AbstractVirtualRoute.cs similarity index 97% rename from src/ShardingCore/Core/VirtualRoutes/Abstractions/AbstractVirtualRoute.cs rename to src/ShardingCore/Core/VirtualRoutes/TableRoutes/AbstractVirtualRoute.cs index d8bf3464..611b6b63 100644 --- a/src/ShardingCore/Core/VirtualRoutes/Abstractions/AbstractVirtualRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/AbstractVirtualRoute.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using ShardingCore.Core.PhysicTables; -namespace ShardingCore.Core.VirtualRoutes.Abstractions +namespace ShardingCore.Core.VirtualRoutes.TableRoutes { /* * @Author: xjm diff --git a/src/ShardingCore/Core/VirtualRoutes/IVirtualRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualRoute.cs similarity index 96% rename from src/ShardingCore/Core/VirtualRoutes/IVirtualRoute.cs rename to src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualRoute.cs index 98f3083a..f28b4a0d 100644 --- a/src/ShardingCore/Core/VirtualRoutes/IVirtualRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualRoute.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using ShardingCore.Core.PhysicTables; -namespace ShardingCore.Core.VirtualRoutes +namespace ShardingCore.Core.VirtualRoutes.TableRoutes { /* * @Author: xjm diff --git a/src/ShardingCore/Core/VirtualRoutes/RouteConfig.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/TableRouteConfig.cs similarity index 84% rename from src/ShardingCore/Core/VirtualRoutes/RouteConfig.cs rename to src/ShardingCore/Core/VirtualRoutes/TableRoutes/TableRouteConfig.cs index 5ebd57b8..40f69564 100644 --- a/src/ShardingCore/Core/VirtualRoutes/RouteConfig.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/TableRouteConfig.cs @@ -1,7 +1,7 @@ using System.Linq; using System.Linq.Expressions; -namespace ShardingCore.Core.VirtualRoutes +namespace ShardingCore.Core.VirtualRoutes.TableRoutes { /* * @Author: xjm @@ -9,7 +9,7 @@ namespace ShardingCore.Core.VirtualRoutes * @Date: Friday, 18 December 2020 14:15:02 * @Email: 326308290@qq.com */ - public class RouteConfig + public class TableRouteConfig { private readonly IQueryable _queryable; private readonly IShardingEntity _shardingEntity; @@ -17,7 +17,7 @@ namespace ShardingCore.Core.VirtualRoutes private readonly Expression _predicate; - public RouteConfig(IQueryable queryable=null,IShardingEntity shardingEntity=null,object shardingKeyValue=null,Expression predicate=null) + public TableRouteConfig(IQueryable queryable=null,IShardingEntity shardingEntity=null,object shardingKeyValue=null,Expression predicate=null) { _queryable = queryable; _shardingEntity = shardingEntity; diff --git a/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs b/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs index 5c7fdf4a..c7fcf819 100644 --- a/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs +++ b/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; namespace ShardingCore.Core.VirtualTables { @@ -31,9 +32,9 @@ namespace ShardingCore.Core.VirtualTables /// /// 路由到具体的物理表 which physic table route /// - /// + /// /// - List RouteTo(RouteConfig routeConfig); + List RouteTo(TableRouteConfig tableRouteConfig); /// /// 添加物理表 add physic table diff --git a/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs b/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs index aa59baa3..15712768 100644 --- a/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs +++ b/src/ShardingCore/Core/VirtualTables/IVirtualTableManager.cs @@ -16,52 +16,80 @@ namespace ShardingCore.Core.VirtualTables public interface IVirtualTableManager { /// - /// 获取所有的虚拟表 get all virtual table + /// 添加虚拟表应用启动时 add virtual table when app start /// - /// - List GetAllVirtualTables(); + /// 链接 + /// 虚拟表 + void AddVirtualTable(string connectKey, IVirtualTable virtualTable); + /// /// 获取虚拟表 get virtual table by sharding entity type /// + /// /// /// - IVirtualTable GetVirtualTable(Type shardingEntityType); + IVirtualTable GetVirtualTable(string connectKey, Type shardingEntityType); + /// /// 获取虚拟表 get virtual table by sharding entity type /// + /// /// - IVirtualTable GetVirtualTable() where T:class,IShardingEntity; - + IVirtualTable GetVirtualTable(string connectKey) where T : class, IShardingEntity; /// /// 获取虚拟表 get virtual table by original table name /// + /// /// /// - IVirtualTable GetVirtualTable(string originalTableName); + IVirtualTable GetVirtualTable(string connectKey,string originalTableName); + + + /// - /// 添加虚拟表应用启动时 add virtual table when app start + /// 获取所有的虚拟表 get all virtual table /// - /// - void AddVirtualTable(IVirtualTable virtualTable); - /// - /// 添加物理表 add physic table - /// - /// - /// - void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable); - /// - /// 添加物理表 add physic table - /// - /// - /// - void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable); - /// - /// 判断是否是分表字段 - /// - /// - /// + /// /// - bool IsShardingKey(Type shardingEntityType, string shardingField); + List GetAllVirtualTables(string connectKey); + + + /// + /// 添加物理表 add physic table + /// + /// + /// + /// + void AddPhysicTable(string connectKey,IVirtualTable virtualTable, IPhysicTable physicTable); + + + /// + /// 添加物理表 add physic table + /// + /// + /// + /// + void AddPhysicTable(string connectKey, Type shardingEntityType, IPhysicTable physicTable); + + ///// + ///// 添加物理表 add physic table + ///// + ///// + ///// + //void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable); + ///// + ///// 添加物理表 add physic table + ///// + ///// + ///// + //void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable); + ///// + ///// 判断是否是分表字段 + ///// + ///// + ///// + ///// + //bool IsShardingKey(Type shardingEntityType, string shardingField); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs index 9ec1ddda..99b99a33 100644 --- a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs +++ b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using Microsoft.Extensions.DependencyInjection; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.Utils; @@ -29,9 +30,9 @@ namespace ShardingCore.Core.VirtualTables public ShardingEntityConfig ShardingConfig { get; } private readonly List _physicTables = new List(); - public OneDbVirtualTable(IServiceProvider serviceProvider) + public OneDbVirtualTable(IVirtualRoute virtualRoute) { - _virtualRoute = serviceProvider.GetService>() ?? throw new ShardingOwnerNotFoundException($"{EntityType}"); + _virtualRoute = virtualRoute; ShardingConfig = ShardingKeyUtil.Parse(EntityType); } @@ -40,19 +41,19 @@ namespace ShardingCore.Core.VirtualTables return _physicTables; } - public List RouteTo(RouteConfig routeConfig) + public List RouteTo(TableRouteConfig tableRouteConfig) { var route = _virtualRoute; - if (routeConfig.UseQueryable()) - return route.RouteWithWhere(_physicTables, routeConfig.GetQueryable()); - if (routeConfig.UsePredicate()) - return route.RouteWithWhere(_physicTables, new EnumerableQuery((Expression>) routeConfig.GetPredicate())); + if (tableRouteConfig.UseQueryable()) + return route.RouteWithWhere(_physicTables, tableRouteConfig.GetQueryable()); + if (tableRouteConfig.UsePredicate()) + return route.RouteWithWhere(_physicTables, new EnumerableQuery((Expression>) tableRouteConfig.GetPredicate())); object shardingKeyValue = null; - if (routeConfig.UseValue()) - shardingKeyValue = routeConfig.GetShardingKeyValue(); + if (tableRouteConfig.UseValue()) + shardingKeyValue = tableRouteConfig.GetShardingKeyValue(); - if (routeConfig.UseEntity()) - shardingKeyValue = routeConfig.GetShardingEntity().GetPropertyValue(ShardingConfig.ShardingField); + if (tableRouteConfig.UseEntity()) + shardingKeyValue = tableRouteConfig.GetShardingEntity().GetPropertyValue(ShardingConfig.ShardingField); if (shardingKeyValue != null) { @@ -60,7 +61,7 @@ namespace ShardingCore.Core.VirtualTables return new List(1) {routeWithValue}; } - throw new NotImplementedException(nameof(RouteConfig)); + throw new NotImplementedException(nameof(TableRouteConfig)); } diff --git a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs index e5cd63b2..2b43d8f6 100644 --- a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs +++ b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTableManager.cs @@ -19,91 +19,89 @@ namespace ShardingCore.Core.VirtualTables /// public class OneDbVirtualTableManager : IVirtualTableManager { - private readonly ConcurrentDictionary _virtualTables = new ConcurrentDictionary(); + private readonly ConcurrentDictionary> _shardingVirtualTables = new ConcurrentDictionary>(); public OneDbVirtualTableManager(IServiceProvider 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(IShardingEntity)==it) - ); - foreach (var shardingEntity in shardingEntities) + //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(IShardingEntity)==it) + // ); + //foreach (var shardingEntity in shardingEntities) + //{ + // Type genericType = typeof(IVirtualTable<>); + // Type interfaceType = genericType.MakeGenericType(shardingEntity); + // var virtualTable = (IVirtualTable)serviceProvider.GetService(interfaceType); + // _virtualTables.TryAdd(virtualTable.EntityType, virtualTable); + //} + } + + public void AddVirtualTable(string connectKey, IVirtualTable virtualTable) + { + if (!_shardingVirtualTables.ContainsKey(connectKey)) { - Type genericType = typeof(IVirtualTable<>); - Type interfaceType = genericType.MakeGenericType(shardingEntity); - var virtualTable = (IVirtualTable)serviceProvider.GetService(interfaceType); - _virtualTables.TryAdd(virtualTable.EntityType, virtualTable); + _shardingVirtualTables.TryAdd(connectKey, new ConcurrentDictionary()); } + + var shardingVirtualTable = _shardingVirtualTables[connectKey]; + shardingVirtualTable.TryAdd(virtualTable.EntityType, virtualTable); } - public List GetAllVirtualTables() + public IVirtualTable GetVirtualTable(string connectKey, Type shardingEntityType) { - return _virtualTables.Select(o=>o.Value).ToList(); - } - - /// - /// 获取指定类型的虚拟表 - /// - /// - /// - /// - public IVirtualTable GetVirtualTable(Type shardingEntityType) - { - if (!_virtualTables.TryGetValue(shardingEntityType, out var virtualTable) || virtualTable == null) - throw new VirtualTableNotFoundException($"{shardingEntityType}"); + if (!_shardingVirtualTables.TryGetValue(connectKey, out var tableKv)) + throw new ShardingVirtualTableNotFoundException(connectKey); + if (!tableKv.TryGetValue(shardingEntityType, out var virtualTable)) + throw new ShardingVirtualTableNotFoundException($"[{connectKey}]-[{shardingEntityType}]"); return virtualTable; } - public IVirtualTable GetVirtualTable() where T : class, IShardingEntity + public IVirtualTable GetVirtualTable(string connectKey) where T : class, IShardingEntity { - var shardingEntityType = typeof(T); - return (IVirtualTable)GetVirtualTable(shardingEntityType); + return (IVirtualTable)GetVirtualTable(connectKey, typeof(T)); } - public IVirtualTable GetVirtualTable(string originalTableName) + public IVirtualTable GetVirtualTable(string connectKey, string originalTableName) { - return _virtualTables.Values.FirstOrDefault(o => o.GetOriginalTableName() == originalTableName) ?? throw new CreateSqlVirtualTableNotFoundException(originalTableName); + if (!_shardingVirtualTables.TryGetValue(connectKey, out var tableKv)) + throw new ShardingVirtualTableNotFoundException(connectKey); + var virtualTable = tableKv.Where(o => o.Value.GetOriginalTableName() == originalTableName).Select(o=>o.Value).FirstOrDefault(); + if (virtualTable==null) + throw new ShardingVirtualTableNotFoundException($"[{connectKey}]-[{originalTableName}]"); + return virtualTable; } - /// - /// 添加虚拟表 - /// - /// - public void AddVirtualTable(IVirtualTable virtualTable) + public List GetAllVirtualTables(string connectKey) { - _virtualTables.TryAdd(virtualTable.EntityType, virtualTable); + if (!_shardingVirtualTables.ContainsKey(connectKey)) + return new List(0); + return _shardingVirtualTables[connectKey].Select(o => o.Value).ToList(); } - /// - /// 添加物理表 - /// - /// - /// - public void AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable) + public void AddPhysicTable(string connectKey, IVirtualTable virtualTable, IPhysicTable physicTable) { - AddPhysicTable(virtualTable.EntityType, physicTable); + AddPhysicTable(connectKey, virtualTable.EntityType, physicTable); } - /// - /// 添加物理表 - /// - /// - /// - public void AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable) + public void AddPhysicTable(string connectKey, Type shardingEntityType, IPhysicTable physicTable) { - var virtualTable = GetVirtualTable(shardingEntityType); + if (!_shardingVirtualTables.ContainsKey(connectKey)) + throw new ShardingConnectKeyNotFoundException(connectKey); + var virtualTable = GetVirtualTable(connectKey,shardingEntityType); virtualTable.AddPhysicTable(physicTable); } - /// - /// 是否是分表字段 - /// - /// - /// - /// - public bool IsShardingKey(Type shardingEntityType, string shardingField) - { - return _virtualTables.TryGetValue(shardingEntityType, out var virtualTable) && virtualTable.ShardingConfig.ShardingField == shardingField; - } + + + ///// + ///// 是否是分表字段 + ///// + ///// + ///// + ///// + //public bool IsShardingKey(Type shardingEntityType, string shardingField) + //{ + // return _virtualTables.TryGetValue(shardingEntityType, out var virtualTable) && virtualTable.ShardingConfig.ShardingField == shardingField; + //} } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs index 3bbbaac3..39668251 100644 --- a/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/IShardingDbContextFactory.cs @@ -1,4 +1,5 @@ -using ShardingCore.DbContexts.ShardingTableDbContexts; +using Microsoft.EntityFrameworkCore; +using ShardingCore.DbContexts.ShardingDbContexts; namespace ShardingCore.DbContexts { @@ -10,6 +11,6 @@ namespace ShardingCore.DbContexts */ public interface IShardingDbContextFactory { - ShardingTableDbContext Create(ShardingTableDbContextOptions shardingDbContextOptions); + DbContext Create(string connectKey,ShardingDbContextOptions shardingDbContextOptions); } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs b/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs index 69bbf038..6f251f0d 100644 --- a/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/IShardingParallelDbContextFactory.cs @@ -10,6 +10,6 @@ namespace ShardingCore.DbContexts */ public interface IShardingParallelDbContextFactory { - DbContext Create(string tail); + DbContext Create(string connectKey, string tail); } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs index 90af178e..65fd6366 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs @@ -1,5 +1,5 @@ +using Microsoft.EntityFrameworkCore; using ShardingCore.DbContexts.ShardingDbContexts; -using ShardingCore.DbContexts.ShardingTableDbContexts; namespace ShardingCore.DbContexts { @@ -11,9 +11,16 @@ namespace ShardingCore.DbContexts */ public class ShardingDbContextFactory:IShardingDbContextFactory { - public ShardingTableDbContext Create(ShardingTableDbContextOptions shardingDbContextOptions) + private readonly IShardingCoreOptions _shardingCoreOptions; + + public ShardingDbContextFactory(IShardingCoreOptions shardingCoreOptions) { - return new ShardingDbContext(shardingDbContextOptions); + _shardingCoreOptions = shardingCoreOptions; + } + public DbContext Create(string connectKey, ShardingDbContextOptions shardingDbContextOptions) + { + var shardingConfigEntry = _shardingCoreOptions.GetShardingConfig(connectKey); + return shardingConfigEntry.Creator(shardingDbContextOptions); } } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingTableDbContexts/ShardingTableDbContext.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/AbstractShardingDbContext.cs similarity index 66% rename from src/ShardingCore/DbContexts/ShardingTableDbContexts/ShardingTableDbContext.cs rename to src/ShardingCore/DbContexts/ShardingDbContexts/AbstractShardingDbContext.cs index 4febd9b3..b18be158 100644 --- a/src/ShardingCore/DbContexts/ShardingTableDbContexts/ShardingTableDbContext.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContexts/AbstractShardingDbContext.cs @@ -1,43 +1,43 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Text; using Microsoft.EntityFrameworkCore; -namespace ShardingCore.DbContexts.ShardingTableDbContexts +namespace ShardingCore.DbContexts.ShardingDbContexts { -/* -* @Author: xjm -* @Description: 用于分表使用 分表比较特殊必须使用规定的dbcontext -* @Date: Thursday, 18 February 2021 15:06:46 -* @Email: 326308290@qq.com -*/ - /// - /// - /// - public abstract class ShardingTableDbContext:DbContext + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/4 16:11:18 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public abstract class AbstractShardingDbContext : DbContext { public string Tail { get; } - public Dictionary VirtualTableConfigs { get; } - public bool RemoveRemoveShardingEntity { get; } - - public ShardingTableDbContext(ShardingTableDbContextOptions options) + public Dictionary VirtualTableConfigs { get; } + + protected AbstractShardingDbContext(ShardingDbContextOptions options) { Tail = options.Tail; - VirtualTableConfigs = options.VirtualTableDbContextConfigs.ToDictionary(o=>o.ShardingEntityType,o=>o); - RemoveRemoveShardingEntity = options.RemoveShardingEntity; + VirtualTableConfigs = options.VirtualTableDbContextConfigs.ToDictionary(o => o.ShardingEntityType, o => o); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); + OnShardingModelCreating(modelBuilder); OnModelCreatingAfter(modelBuilder); } + protected abstract void OnShardingModelCreating(ModelBuilder modelBuilder); + protected virtual void OnModelCreatingAfter(ModelBuilder modelBuilder) { if (!string.IsNullOrWhiteSpace(Tail)) { - var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o=>VirtualTableConfigs.ContainsKey(o.ClrType)); + var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => VirtualTableConfigs.ContainsKey(o.ClrType)); foreach (var entityType in mutableEntityTypes) { var virtualTableConfig = VirtualTableConfigs[entityType.ClrType]; diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContext.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContext.cs deleted file mode 100644 index 9565af8b..00000000 --- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContext.cs +++ /dev/null @@ -1,147 +0,0 @@ -// using System; -// using System.Collections.Concurrent; -// using System.Collections.Generic; -// using System.Linq; -// using Microsoft.EntityFrameworkCore; -// using ShardingCore.Extensions; -// using ShardingCore.Helpers; -// -// namespace ShardingCore.DbContexts.ShardingDbContexts -// { -// /* -// * @Author: xjm -// * @Description: -// * @Date: Wednesday, 16 December 2020 15:28:12 -// * @Email: 326308290@qq.com -// */ -// public class ShardingDbContext : DbContext -// { -// public string Tail { get; } -// public List VirtualTableConfigs { get; } -// public bool RemoveRemoveShardingEntity { get; } -// private static readonly ConcurrentDictionary _entityTypeConfigurationTypeCaches = new ConcurrentDictionary(); -// private static readonly object buildEntityTypeConfigurationLock = new object(); -// -// public ShardingDbContext(ShardingDbContextOptions shardingDbContextOptions) : base(shardingDbContextOptions.DbContextOptions) -// { -// Tail = shardingDbContextOptions.Tail; -// VirtualTableConfigs = shardingDbContextOptions.VirtualTableDbContextConfigs; -// RemoveRemoveShardingEntity = shardingDbContextOptions.RemoveShardingEntity; -// } -// -// /// -// /// 模型构建 -// /// -// /// -// protected override void OnModelCreating(ModelBuilder modelBuilder) -// { -// if (!string.IsNullOrWhiteSpace(Tail)) -// { -// //支持IEntityTypeConfiguration配置 -// VirtualTableConfigs.ForEach(virtualTable => -// { -// var shardingEntityType = virtualTable.ShardingEntityType; -// if (!_entityTypeConfigurationTypeCaches.TryGetValue(shardingEntityType, out var entityTypeConfigurationType)) -// throw new Exception($"未找到对应的类型无法进行IEntityTypeConfiguration配置:[{shardingEntityType.Name}]"); -// if (entityTypeConfigurationType == null) -// throw new NotSupportedException($"{shardingEntityType}的[IBaseEntityTypeConfiguration]未找到"); -// var method = modelBuilder.GetType() -// .GetMethods() -// .FirstOrDefault(x => x.Name == nameof(ModelBuilder.ApplyConfiguration) -// && x.GetParameters().Count() == 1 -// && x.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)); -// method.MakeGenericMethod(shardingEntityType).Invoke(modelBuilder, new object[] {Activator.CreateInstance(entityTypeConfigurationType)}); -// }); -// -// VirtualTableConfigs.ForEach(virtualTableConfig => -// { -// var shardingEntity = virtualTableConfig.ShardingEntityType; -// var tailPrefix = virtualTableConfig.TailPrefix; -// var entity = modelBuilder.Entity(shardingEntity); -// var tableName = virtualTableConfig.OriginalTableName; -// if (string.IsNullOrWhiteSpace(tableName)) -// throw new ArgumentNullException($"{shardingEntity}:无法找到对应的原始表名。"); -// #if DEBUG -// Console.WriteLine($"映射表:[tableName]-->[{tableName}{tailPrefix}{Tail}]"); -// #endif -// entity.ToTable($"{tableName}{tailPrefix}{Tail}"); -// }); -// } -// else -// { -// BuildEntityTypeConfigurationCaches(); -// //支持IEntityTypeConfiguration配置 -// foreach (var entityTypeConfigurationType in _entityTypeConfigurationTypeCaches) -// { -// var shardingEntityType = entityTypeConfigurationType.Key; -// if (RemoveRemoveShardingEntity && shardingEntityType.IsShardingEntity()) -// continue; -// var method = modelBuilder.GetType() -// .GetMethods() -// .FirstOrDefault(x => x.Name == nameof(ModelBuilder.ApplyConfiguration) -// && x.GetParameters().Count() == 1 -// && x.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)); -// method.MakeGenericMethod(shardingEntityType).Invoke(modelBuilder, new object[] {Activator.CreateInstance(entityTypeConfigurationType.Value)}); -// } -// } -// -// ////字段注释,需要开启程序集XML文档 -// -// //foreach (var entityType in modelBuilder.Model.GetEntityTypes()) -// //{ -// // var comments = XmlHelper.GetPropertyCommentBySummary(entityType.ClrType) ?? new Dictionary(); -// // foreach (var property in entityType.GetProperties()) -// // { -// // if (comments.ContainsKey(property.Name)) -// // { -// // property.SetComment(comments[property.Name]); -// // } -// // } -// //} -// // -// #if !EFCORE2 -// //字段注释,需要开启程序集XML文档 -// foreach (var entityType in modelBuilder.Model.GetEntityTypes()) -// { -// var comments = XmlHelper.GetProperyCommentBySummary(entityType.ClrType) ?? new Dictionary(); -// foreach (var property in entityType.GetProperties()) -// { -// if (comments.ContainsKey(property.Name)) -// { -// property.SetComment(comments[property.Name]); -// } -// } -// } -// #endif -// } -// -// /// -// /// 构建类型 -// /// -// public void BuildEntityTypeConfigurationCaches() -// { -// if (!_entityTypeConfigurationTypeCaches.Any()) -// { -// lock (buildEntityTypeConfigurationLock) -// { -// if (!_entityTypeConfigurationTypeCaches.Any()) -// { -// var typesToRegister = AssemblyHelper.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes()) -// .Where(type => !String.IsNullOrEmpty(type.Namespace)) -// //获取类型namespce不是空的所有接口是范型的当前范型是IEntityTypeConfiguration<>的进行fluent api 映射 -// .Where(type => !type.IsAbstract && type.GetInterfaces() -// .Any(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>) -// && it.GetGenericArguments().Any()) -// ).ToDictionary(o => o.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>) -// && it.GetGenericArguments().Any()) -// ?.GetGenericArguments()[0], o => o); -// foreach (var type in typesToRegister) -// { -// _entityTypeConfigurationTypeCaches.TryAdd(type.Key, type.Value); -// } -// } -// } -// } -// } -// } -// } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs index 508e13ff..2db46a13 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingDbContextOptions.cs @@ -1,28 +1,26 @@ -// using System.Collections.Generic; -// using Microsoft.EntityFrameworkCore; -// -// namespace ShardingCore.DbContexts.ShardingDbContexts -// { -// /* -// * @Author: xjm -// * @Description: -// * @Date: Wednesday, 16 December 2020 16:15:43 -// * @Email: 326308290@qq.com -// */ -// public class ShardingDbContextOptions -// { -// -// public ShardingDbContextOptions(DbContextOptions dbContextOptions, string tail, List virtualTableDbContextConfigs, bool removeShardingEntity=false) -// { -// DbContextOptions = dbContextOptions; -// Tail = tail; -// VirtualTableDbContextConfigs = virtualTableDbContextConfigs; -// RemoveShardingEntity = removeShardingEntity; -// } -// -// public DbContextOptions DbContextOptions { get; } -// public string Tail { get; } -// public List VirtualTableDbContextConfigs { get; } -// public bool RemoveShardingEntity { get;} -// } -// } \ No newline at end of file +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace ShardingCore.DbContexts.ShardingDbContexts +{ + /* + * @Author: xjm + * @Description: + * @Date: Wednesday, 16 December 2020 16:15:43 + * @Email: 326308290@qq.com + */ + public class ShardingDbContextOptions + { + + public ShardingDbContextOptions(DbContextOptions dbContextOptions, string tail, List virtualTableDbContextConfigs) + { + DbContextOptions = dbContextOptions; + Tail = tail; + VirtualTableDbContextConfigs = virtualTableDbContextConfigs; + } + + public DbContextOptions DbContextOptions { get; } + public string Tail { get; } + public List VirtualTableDbContextConfigs { get; } + } +} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/VirtualTableDbContextConfig.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/VirtualTableDbContextConfig.cs index f340c880..55661779 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContexts/VirtualTableDbContextConfig.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContexts/VirtualTableDbContextConfig.cs @@ -1,34 +1,34 @@ -// using System; -// -// namespace ShardingCore.DbContexts.ShardingDbContexts -// { -// /* -// * @Author: xjm -// * @Description: -// * @Date: Friday, 01 January 2021 16:24:57 -// * @Email: 326308290@qq.com -// */ -// public class VirtualTableDbContextConfig -// { -// public VirtualTableDbContextConfig(Type shardingEntityType, string originalTableName, string tailPrefix) -// { -// ShardingEntityType = shardingEntityType; -// OriginalTableName = originalTableName; -// TailPrefix = tailPrefix; -// } -// -// /// -// /// 分表实体类型 -// /// -// public Type ShardingEntityType { get; } -// -// /// -// /// 原始表名不带后缀 -// /// -// public string OriginalTableName { get; } -// /// -// /// 表尾巴前缀 -// /// -// public string TailPrefix { get; } -// } -// } \ No newline at end of file +using System; + +namespace ShardingCore.DbContexts.ShardingDbContexts +{ +/* +* @Author: xjm +* @Description: +* @Date: Friday, 01 January 2021 16:24:57 +* @Email: 326308290@qq.com +*/ + public class VirtualTableDbContextConfig + { + public VirtualTableDbContextConfig(Type shardingEntityType, string originalTableName, string tailPrefix) + { + ShardingEntityType = shardingEntityType; + OriginalTableName = originalTableName; + TailPrefix = tailPrefix; + } + + /// + /// 分表实体类型 + /// + public Type ShardingEntityType { get; } + + /// + /// 原始表名不带后缀 + /// + public string OriginalTableName { get; } + /// + /// 表尾巴前缀 + /// + public string TailPrefix { get; } + } +} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingParallelDbContextFactoryManager.cs b/src/ShardingCore/DbContexts/ShardingParallelDbContextFactoryManager.cs deleted file mode 100644 index cc49c07f..00000000 --- a/src/ShardingCore/DbContexts/ShardingParallelDbContextFactoryManager.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; - -namespace ShardingCore.DbContexts -{ -/* -* @Author: xjm -* @Description: -* @Date: Monday, 22 February 2021 16:45:11 -* @Email: 326308290@qq.com -*/ - public class ShardingParallelDbContextFactoryManager:IShardingParallelDbContextFactoryManager - { - private readonly Dictionary<> - public DbContext CreateDbContext(string connectKey, string tail) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingTableDbContexts/ShardingTableDbContextOptions.cs b/src/ShardingCore/DbContexts/ShardingTableDbContexts/ShardingTableDbContextOptions.cs deleted file mode 100644 index 8812b980..00000000 --- a/src/ShardingCore/DbContexts/ShardingTableDbContexts/ShardingTableDbContextOptions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; - -namespace ShardingCore.DbContexts.ShardingTableDbContexts -{ -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 18 February 2021 15:22:46 -* @Email: 326308290@qq.com -*/ - public class ShardingTableDbContextOptions - { - - public ShardingTableDbContextOptions(DbContextOptions dbContextOptions, string tail, List virtualTableDbContextConfigs, bool removeShardingEntity=false) - { - DbContextOptions = dbContextOptions; - Tail = tail; - VirtualTableDbContextConfigs = virtualTableDbContextConfigs; - RemoveShardingEntity = removeShardingEntity; - } - - public DbContextOptions DbContextOptions { get; } - public string Tail { get; } - public List VirtualTableDbContextConfigs { get; } - public bool RemoveShardingEntity { get;} - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/ShardingTableDbContexts/VirtualTableDbContextConfig.cs b/src/ShardingCore/DbContexts/ShardingTableDbContexts/VirtualTableDbContextConfig.cs deleted file mode 100644 index dd8f2291..00000000 --- a/src/ShardingCore/DbContexts/ShardingTableDbContexts/VirtualTableDbContextConfig.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; - -namespace ShardingCore.DbContexts.ShardingTableDbContexts -{ -/* -* @Author: xjm -* @Description: -* @Date: Friday, 01 January 2021 16:24:57 -* @Email: 326308290@qq.com -*/ - public class VirtualTableDbContextConfig - { - public VirtualTableDbContextConfig(Type shardingEntityType, string originalTableName, string tailPrefix) - { - ShardingEntityType = shardingEntityType; - OriginalTableName = originalTableName; - TailPrefix = tailPrefix; - } - - /// - /// 分表实体类型 - /// - public Type ShardingEntityType { get; } - - /// - /// 原始表名不带后缀 - /// - public string OriginalTableName { get; } - /// - /// 表尾巴前缀 - /// - public string TailPrefix { get; } - } -} \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs b/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs index e6a758b9..4318d633 100644 --- a/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs +++ b/src/ShardingCore/DbContexts/VirtualDbContexts/IDbContextOptionsProvider.cs @@ -11,6 +11,6 @@ namespace ShardingCore.DbContexts.VirtualDbContexts */ public interface IDbContextOptionsProvider:IDisposable { - DbContextOptions GetDbContextOptions(); + DbContextOptions GetDbContextOptions(string connectKey); } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchDeleteEntry.cs b/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchDeleteEntry.cs index 162804b8..bc971f56 100644 --- a/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchDeleteEntry.cs +++ b/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchDeleteEntry.cs @@ -13,13 +13,13 @@ namespace ShardingCore.DbContexts.VirtualDbContexts */ public class ShardingBatchDeleteEntrywhere T:class { - public ShardingBatchDeleteEntry(Expression> @where, List dbContexts) + public ShardingBatchDeleteEntry(Expression> @where, List<(string connectKey,List)> dbContextGroups) { Where = @where; - DbContexts = dbContexts; + DbContextGroups = dbContextGroups; } public Expression> Where{ get; } - public List DbContexts { get; } + public List<(string connectKey, List)> DbContextGroups { get; } } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchUpdateEntry.cs b/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchUpdateEntry.cs index 2d047b21..8bee8940 100644 --- a/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchUpdateEntry.cs +++ b/src/ShardingCore/DbContexts/VirtualDbContexts/ShardingBatchUpdateEntry.cs @@ -13,15 +13,15 @@ namespace ShardingCore.DbContexts.VirtualDbContexts */ public class ShardingBatchUpdateEntry where T:class { - public ShardingBatchUpdateEntry(Expression> @where, Expression> updateExp, List dbContexts) + public ShardingBatchUpdateEntry(Expression> @where, Expression> updateExp, List<(string connectKey, List dbContexts)> dbContextGroups) { Where = @where; UpdateExp = updateExp; - DbContexts = dbContexts; + DbContextGroups = dbContextGroups; } public Expression> Where {get;} public Expression> UpdateExp{get;} - public List DbContexts { get; } + public List<(string connectKey, List dbContexts)> DbContextGroups { get; } } } \ No newline at end of file diff --git a/src/ShardingCore/DbContexts/VirtualDbContexts/ShareDbContextOptionsProviders/ShareDbContextWrapItem.cs b/src/ShardingCore/DbContexts/VirtualDbContexts/ShareDbContextOptionsProviders/ShareDbContextWrapItem.cs new file mode 100644 index 00000000..5719ceb5 --- /dev/null +++ b/src/ShardingCore/DbContexts/VirtualDbContexts/ShareDbContextOptionsProviders/ShareDbContextWrapItem.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Text; +using Microsoft.EntityFrameworkCore; + +namespace ShardingCore.DbContexts.VirtualDbContexts.ShareDbContextOptionsProviders +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 9:04:12 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShareDbContextWrapItem + { + public ShareDbContextWrapItem(DbConnection connection, DbContextOptions contextOptions) + { + Connection = connection; + ContextOptions = contextOptions; + } + + public string ConnectKey { get; } + public DbConnection Connection { get; } + public DbContextOptions ContextOptions { get; } + } +} diff --git a/src/ShardingCore/DbContexts/VirtualDbContexts/VirtualDbContext.cs b/src/ShardingCore/DbContexts/VirtualDbContexts/VirtualDbContext.cs index b6f27e8d..09936a65 100644 --- a/src/ShardingCore/DbContexts/VirtualDbContexts/VirtualDbContext.cs +++ b/src/ShardingCore/DbContexts/VirtualDbContexts/VirtualDbContext.cs @@ -6,35 +6,39 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using ShardingCore.Core; +using ShardingCore.Core.VirtualDataSources; using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualTables; -using ShardingCore.DbContexts.ShardingTableDbContexts; +using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.Transactions; using ShardingCore.Exceptions; using ShardingCore.Extensions; namespace ShardingCore.DbContexts.VirtualDbContexts { -/* -* @Author: xjm -* @Description: -* @Date: Thursday, 17 December 2020 21:50:49 -* @Email: 326308290@qq.com -*/ + /* + * @Author: xjm + * @Description: + * @Date: Thursday, 17 December 2020 21:50:49 + * @Email: 326308290@qq.com + */ public class VirtualDbContext : AbstractInjectVirtualDbContext, IVirtualDbContext { private readonly string EMPTY_SHARDING_TAIL_ID = Guid.NewGuid().ToString("n"); private readonly IServiceProvider _serviceProvider; + private readonly IVirtualDataSourceManager _virtualDataSourceManager; private readonly IVirtualTableManager _virtualTableManager; private readonly IShardingDbContextFactory _shardingDbContextFactory; - private readonly ConcurrentDictionary _dbContextCaches = new ConcurrentDictionary(); + private readonly ConcurrentDictionary> _dbContextCaches = new ConcurrentDictionary>(); private IShardingTransaction _dbTransaction = new ShardingTransaction(); - public VirtualDbContext(IServiceProvider serviceProvider, + public VirtualDbContext(IServiceProvider serviceProvider, IVirtualDataSourceManager virtualDataSourceManager, IVirtualTableManager virtualTableManager, IShardingDbContextFactory shardingDbContextFactory) : base(serviceProvider) { _serviceProvider = serviceProvider; + _virtualDataSourceManager = virtualDataSourceManager; _virtualTableManager = virtualTableManager; _shardingDbContextFactory = shardingDbContextFactory; } @@ -45,7 +49,13 @@ namespace ShardingCore.DbContexts.VirtualDbContexts public IShardingTransaction BeginTransaction() { _dbTransaction.Open(); - _dbContextCaches.ForEach(kv => { _dbTransaction.Use(kv.Value); }); + _dbContextCaches.ForEach(kv => + { + kv.Value.ForEach(d => + { + _dbTransaction.Use(d.Value); + }); + }); return _dbTransaction; } @@ -62,7 +72,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts public IQueryable Set() where T : class { - return GetOrCreateShardingDbContext(EMPTY_SHARDING_TAIL_ID).Set().AsNoTracking(); + return GetOrCreateShardingDbContext(_virtualDataSourceManager.GetDefaultConnectKey(),EMPTY_SHARDING_TAIL_ID).Set().AsNoTracking(); } public async Task InsertAsync(T entity) where T : class @@ -85,7 +95,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts foreach (var group in groups) { - await group.Key.AddRangeAsync(group.Select(o=>o.Entity)); + await group.Key.AddRangeAsync(group.Select(o => o.Entity)); } return entities.Count; @@ -111,7 +121,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts foreach (var group in groups) { - group.Key.UpdateRange(group.Select(o=>o.Entity)); + group.Key.UpdateRange(group.Select(o => o.Entity)); } return Task.FromResult(entities.Count); @@ -137,7 +147,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts foreach (var group in groups) { - group.Key.RemoveRange(group.Select(o=>o.Entity)); + group.Key.RemoveRange(group.Select(o => o.Entity)); } return Task.FromResult(entities.Count); @@ -145,7 +155,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts public async Task SaveChangesAsync() { - var transOpenNow = !_dbTransaction.IsOpened&&_dbContextCaches.Count>1; + var transOpenNow = !_dbTransaction.IsOpened && _dbContextCaches.Count > 1; if (transOpenNow) { BeginTransaction(); @@ -153,7 +163,10 @@ namespace ShardingCore.DbContexts.VirtualDbContexts var effects = 0; foreach (var dbContextCache in _dbContextCaches) { - effects += await dbContextCache.Value.SaveChangesAsync(); + foreach (var dbContext in dbContextCache.Value) + { + effects += await dbContext.Value.SaveChangesAsync(); + } } if (transOpenNow) @@ -182,7 +195,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts foreach (var group in groups) { - group.Key.AddRange(group.Select(o=>o.Entity)); + group.Key.AddRange(group.Select(o => o.Entity)); } return entities.Count; @@ -208,7 +221,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts foreach (var group in groups) { - group.Key.UpdateRange(group.Select(o=>o.Entity)); + group.Key.UpdateRange(group.Select(o => o.Entity)); } return entities.Count; @@ -234,7 +247,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts foreach (var group in groups) { - group.Key.RemoveRange(group.Select(o=>o.Entity)); + group.Key.RemoveRange(group.Select(o => o.Entity)); } return entities.Count; @@ -242,7 +255,7 @@ namespace ShardingCore.DbContexts.VirtualDbContexts public int SaveChanges() { - var transOpenNow = !_dbTransaction.IsOpened&&_dbContextCaches.Count>1; + var transOpenNow = !_dbTransaction.IsOpened && _dbContextCaches.Count > 1; if (transOpenNow) { BeginTransaction(); @@ -250,10 +263,13 @@ namespace ShardingCore.DbContexts.VirtualDbContexts var effects = 0; foreach (var dbContextCache in _dbContextCaches) { - effects += dbContextCache.Value.SaveChanges(); + foreach (var dbContext in dbContextCache.Value) + { + effects += dbContext.Value.SaveChanges(); + } } if (transOpenNow) - _dbTransaction.Commit(); + _dbTransaction.Commit(); return effects; } @@ -269,93 +285,127 @@ namespace ShardingCore.DbContexts.VirtualDbContexts Entity = o }; }).GroupBy(g => g.DbContext) - .ToDictionary(o => (DbContext) o.Key, o => o.Select(item => item.Entity).ToList()); + .ToDictionary(o => (DbContext)o.Key, o => o.Select(item => item.Entity).ToList()); return new ShardingBatchInsertEntry(groups); } public ShardingBatchUpdateEntry BulkUpdate(Expression> where, Expression> updateExp) where T : class { - List dbContexts = null; - if (typeof(T).IsShardingEntity()) + List<(string connectKey, List dbContexts)> dbContexts = null; + var connectKeys = _virtualDataSourceManager.GetConnectKeys(where); + + if (typeof(T).IsShardingTable()) { - var shardingDbContexts = CreateShardingDbContexts(new EnumerableQuery(where).AsQueryable()); - dbContexts = shardingDbContexts.Select(o => (DbContext) o).ToList(); + dbContexts = CreateShardingDbContexts(connectKeys, new EnumerableQuery(where).AsQueryable()); } else { - dbContexts = new List(1) + dbContexts = connectKeys.Select(connectKey => { - GetOrCreateShardingDbContext(EMPTY_SHARDING_TAIL_ID) - }; + return (connectKey, new List(1) + { + GetOrCreateShardingDbContext(connectKey, EMPTY_SHARDING_TAIL_ID) + }); + }).ToList(); } - return new ShardingBatchUpdateEntry(where,updateExp,dbContexts); + return new ShardingBatchUpdateEntry(where, updateExp, dbContexts); } public ShardingBatchDeleteEntry BulkDelete(Expression> where) where T : class { - List dbContexts = null; - if (typeof(T).IsShardingEntity()) + List<(string connectKey,List dbContexts)> dbContexts = null; + var connectKeys = _virtualDataSourceManager.GetConnectKeys(where); + + if (typeof(T).IsShardingTable()) { - var shardingDbContexts = CreateShardingDbContexts(new EnumerableQuery(where).AsQueryable()); - dbContexts = shardingDbContexts.Select(o => (DbContext) o).ToList(); + dbContexts = CreateShardingDbContexts(connectKeys, new EnumerableQuery(where).AsQueryable()); } else { - dbContexts = new List(1) + dbContexts = connectKeys.Select(connectKey => { - GetOrCreateShardingDbContext(EMPTY_SHARDING_TAIL_ID) - }; + return (connectKey, new List(1) + { + GetOrCreateShardingDbContext(connectKey, EMPTY_SHARDING_TAIL_ID) + }); + }).ToList(); } - return new ShardingBatchDeleteEntry(where,dbContexts); + return new ShardingBatchDeleteEntry(where, dbContexts); } private DbContext CreateGenericDbContext(T entity) where T : class { var tail = EMPTY_SHARDING_TAIL_ID; - if (entity.IsShardingEntity()) + var connectKey = _virtualDataSourceManager.GetConnectKey(entity); + if (entity.IsShardingTable()) { - var physicTable = _virtualTableManager.GetVirtualTable(entity.GetType()).RouteTo(new RouteConfig(null, entity as IShardingEntity, null))[0]; + var physicTable = _virtualTableManager.GetVirtualTable(connectKey, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingEntity, null))[0]; tail = physicTable.Tail; } - return GetOrCreateShardingDbContext(tail); + return GetOrCreateShardingDbContext(connectKey,tail); } - private List CreateShardingDbContexts(IQueryable queryable) where T : class, IShardingEntity + private List<(string connectKey, List dbContexts)> CreateShardingDbContexts(List connectKeys,IQueryable queryable) where T : class, IShardingEntity { - var physicTables = _virtualTableManager.GetVirtualTable(typeof(T)).RouteTo(new RouteConfig(queryable, null, null)); - if (physicTables.Any()) + var results = + new List<(string connectKey, List dbContexts)>(); + foreach (var connectKey in connectKeys) { - var shardingDbContexts = new List(physicTables.Count); - foreach (var physicTable in physicTables) + var physicTables = _virtualTableManager.GetVirtualTable(connectKey,typeof(T)).RouteTo(new TableRouteConfig(queryable, null, null)); + if (physicTables.Any()) { - var shardingDbContext = GetOrCreateShardingDbContext(physicTable.Tail); + var dbContexts = new List(physicTables.Count); + foreach (var physicTable in physicTables) + { + var dbContext = GetOrCreateShardingDbContext(connectKey,physicTable.Tail); - shardingDbContexts.Add(shardingDbContext); + dbContexts.Add(dbContext); + } + results.Add((connectKey, dbContexts)); } - - return shardingDbContexts; } + if (results.Any()) + return results; + throw new QueryableRouteNotMatchException($"{typeof(T)} -> {nameof(queryable)}"); } - private DbContext GetOrCreateShardingDbContext(string tail) + private DbContext GetOrCreateShardingDbContext(string connectKey,string tail) { - if (!_dbContextCaches.TryGetValue(tail, out var shardingDbContext)) + if (!_dbContextCaches.TryGetValue(connectKey, out var dbContexts)) { - var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables().GetVirtualTableDbContextConfigs(); - shardingDbContext = _shardingDbContextFactory.Create(new ShardingTableDbContextOptions(DbContextOptionsProvider.GetDbContextOptions(), tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail, virtualTableConfigs)); - _dbContextCaches.TryAdd(tail, shardingDbContext); + dbContexts = new ConcurrentDictionary(); + _dbContextCaches.TryAdd(connectKey, dbContexts); + } + if(!dbContexts.TryGetValue(tail,out var dbContext)) + { + var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables(connectKey).GetVirtualTableDbContextConfigs(); + dbContext = _shardingDbContextFactory.Create(connectKey, new ShardingDbContextOptions(DbContextOptionsProvider.GetDbContextOptions(connectKey), tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail, virtualTableConfigs)); + dbContexts.TryAdd(tail, dbContext); } if (IsOpenTransaction) { - _dbTransaction.Use(shardingDbContext); + _dbTransaction.Use(dbContext); } - return shardingDbContext; + return dbContext; + //if (!_dbContextCaches.TryGetValue(tail, out var dbContext)) + //{ + // var virtualTableConfigs = _virtualTableManager.GetAllVirtualTables().GetVirtualTableDbContextConfigs(); + // dbContext = _shardingDbContextFactory.Create(new ShardingDbContextOptions(DbContextOptionsProvider.GetDbContextOptions(), tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail, virtualTableConfigs)); + // _dbContextCaches.TryAdd(tail, dbContext); + //} + + //if (IsOpenTransaction) + //{ + // _dbTransaction.Use(dbContext); + //} + + //return dbContext; } @@ -365,14 +415,17 @@ namespace ShardingCore.DbContexts.VirtualDbContexts { _dbContextCaches.ForEach(o => { - try + o.Value.ForEach(v => { - o.Value.Dispose(); - } - catch (Exception e) - { - Console.WriteLine(e); - } + try + { + v.Value.Dispose(); + } + catch (Exception e) + { + Console.WriteLine(e); + } + }); }); _dbContextCaches.Clear(); } diff --git a/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs b/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs index 398ca4c9..13509776 100644 --- a/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs +++ b/src/ShardingCore/EFCores/ShardingModelCacheKeyFactory.cs @@ -15,14 +15,13 @@ namespace ShardingCore.EFCores { public object Create(DbContext context) { - if (context is ShardingDbContext shardingDbContext) + if (context is AbstractShardingDbContext shardingDbContext) { //当出现尾巴不一样,本次映射的数据库实体数目不一样就需要重建ef model var tail = shardingDbContext.Tail; - var removeSharding = shardingDbContext.RemoveRemoveShardingEntity; - var allEntities = string.Join(",",shardingDbContext.VirtualTableConfigs.Select(o=>o.ShardingEntityType.FullName).OrderBy(o=>o).ToList()); + var allEntities = string.Join(",",shardingDbContext.VirtualTableConfigs.Values.Select(o=>o.ShardingEntityType.FullName).OrderBy(o=>o).ToList()); - return $"{context.GetType()}_{allEntities}_{tail}_{removeSharding}"; + return $"{context.GetType()}_{allEntities}_{tail}"; } else { diff --git a/src/ShardingCore/EFCores/ShardingQueryCompiler.cs b/src/ShardingCore/EFCores/ShardingQueryCompiler.cs index b35011a5..608466e0 100644 --- a/src/ShardingCore/EFCores/ShardingQueryCompiler.cs +++ b/src/ShardingCore/EFCores/ShardingQueryCompiler.cs @@ -263,7 +263,7 @@ namespace ShardingCore.EFCores return database.CompileAsyncQuery(queryModel); } private static async Task ExecuteSingletonAsyncQuery( - QueryContext queryContext, + QueryContext queryContext, Func> compiledQuery, IDiagnosticsLogger logger, Type contextType) diff --git a/src/ShardingCore/Exceptions/ShardingConfigNotFoundException.cs b/src/ShardingCore/Exceptions/ShardingConfigNotFoundException.cs new file mode 100644 index 00000000..f2070b3c --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingConfigNotFoundException.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace ShardingCore.Exceptions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 8:11:30 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingConfigNotFoundException:Exception + { + public ShardingConfigNotFoundException() + { + } + + protected ShardingConfigNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + public ShardingConfigNotFoundException(string message) : base(message) + { + } + + public ShardingConfigNotFoundException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/Exceptions/ShardingConnectKeyNotFoundException.cs b/src/ShardingCore/Exceptions/ShardingConnectKeyNotFoundException.cs new file mode 100644 index 00000000..b657c951 --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingConnectKeyNotFoundException.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace ShardingCore.Exceptions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 13:25:51 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingConnectKeyNotFoundException: Exception + { + public ShardingConnectKeyNotFoundException() + { + } + + protected ShardingConnectKeyNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + public ShardingConnectKeyNotFoundException(string message) : base(message) + { + } + + public ShardingConnectKeyNotFoundException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/Exceptions/ShardingCoreException.cs b/src/ShardingCore/Exceptions/ShardingCoreException.cs new file mode 100644 index 00000000..3e0e9a26 --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingCoreException.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace ShardingCore.Exceptions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 15:18:55 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingCoreException: Exception + { + public ShardingCoreException() + { + } + + protected ShardingCoreException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + public ShardingCoreException(string message) : base(message) + { + } + + public ShardingCoreException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/Exceptions/ShardingVirtualTableNotFoundException.cs b/src/ShardingCore/Exceptions/ShardingVirtualTableNotFoundException.cs new file mode 100644 index 00000000..df7174ee --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingVirtualTableNotFoundException.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace ShardingCore.Exceptions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 13:06:39 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingVirtualTableNotFoundException: Exception + { + public ShardingVirtualTableNotFoundException() + { + } + + protected ShardingVirtualTableNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + public ShardingVirtualTableNotFoundException(string message) : base(message) + { + } + + public ShardingVirtualTableNotFoundException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/Extensions/CommonExtension.cs b/src/ShardingCore/Extensions/CommonExtension.cs index ba05e65f..9cd562be 100644 --- a/src/ShardingCore/Extensions/CommonExtension.cs +++ b/src/ShardingCore/Extensions/CommonExtension.cs @@ -30,11 +30,29 @@ namespace ShardingCore.Extensions return typeof(IShardingDataSource).IsAssignableFrom(entityType); } /// + /// 是否基继承至IShardingDataSource + /// + /// + /// + public static bool IsShardingDataSource(this object entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity)); + return typeof(IShardingDataSource).IsAssignableFrom(entity.GetType()); + } + + public static bool IsShardingDbContext(this Type entityType) + { + if (entityType == null) + throw new ArgumentNullException(nameof(entityType)); + return typeof(AbstractShardingDbContext).IsAssignableFrom(entityType); + } + /// /// 是否基继承至IShardingEntity /// /// /// - public static bool IsShardingEntity(this Type entityType) + public static bool IsShardingTable(this Type entityType) { if (entityType == null) throw new ArgumentNullException(nameof(entityType)); @@ -46,7 +64,7 @@ namespace ShardingCore.Extensions /// /// /// - public static bool IsShardingEntity(this object entity) + public static bool IsShardingTable(this object entity) { if (entity == null) throw new ArgumentNullException(nameof(entity)); @@ -71,6 +89,7 @@ namespace ShardingCore.Extensions { return express.Method.DeclaringType.Namespace.IsIn("System.Linq", "System.Collections.Generic") && methodName == nameof(IList.Contains); } + public static ISet ParseQueryableRoute(this IQueryable queryable) { return ShardingKeyUtil.GetQueryEntitiesFilter(queryable); diff --git a/src/ShardingCore/Extensions/LinqExtension.cs b/src/ShardingCore/Extensions/LinqExtension.cs index 66d02b61..d8301075 100644 --- a/src/ShardingCore/Extensions/LinqExtension.cs +++ b/src/ShardingCore/Extensions/LinqExtension.cs @@ -52,11 +52,11 @@ namespace ShardingCore.Extensions /// 给IEnumerable拓展ForEach方法 /// /// 模型类 - /// 数据源 + /// 数据源 /// 方法 - public static void ForEach(this IEnumerable iEnumberable, Action func) + public static void ForEach(this IEnumerable enumberable, Action func) { - foreach (var item in iEnumberable) + foreach (var item in enumberable) { func(item); } diff --git a/src/ShardingCore/Extensions/VirtualDbContextExtension.cs b/src/ShardingCore/Extensions/VirtualDbContextExtension.cs new file mode 100644 index 00000000..8d2125d4 --- /dev/null +++ b/src/ShardingCore/Extensions/VirtualDbContextExtension.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using ShardingCore.Core; +using ShardingCore.Core.VirtualDataSources; +using ShardingCore.Exceptions; + +namespace ShardingCore.Extensions +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/5 15:43:09 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public static class VirtualDbContextExtension + { + public static string GetConnectKey(this IVirtualDataSourceManager virtualDataSourceManager, T entity) where T : class + { + var type = entity.GetType(); + var connectKeys = virtualDataSourceManager.GetEntityTypeLinkedConnectKeys(type); + if (connectKeys.IsEmpty()) + throw new ShardingCoreException($"entity:[{type}] connect not found"); + if (connectKeys.Count == 1) + return connectKeys[0]; + if (!entity.IsShardingDataSource()) + throw new ShardingCoreException($"entity:[{type}] is not sharding data source and not found connect"); + return virtualDataSourceManager.GetVirtualDataSource(type) + .RouteTo(new VirutalDataSourceRouteConfig(shardingDataSource: entity as IShardingDataSource))[0]; + } + public static List GetConnectKeys(this IVirtualDataSourceManager virtualDataSourceManager, Expression> where) where T : class + { + var type = typeof(T); + var connectKeys = virtualDataSourceManager.GetEntityTypeLinkedConnectKeys(type); + if (connectKeys.IsEmpty()) + throw new ShardingCoreException($"entity:[{type}] connect not found"); + + if (!type.IsShardingDataSource()) + throw new ShardingCoreException($"entity:[{type}] is not sharding data source and not found connect"); + return virtualDataSourceManager.GetVirtualDataSource(type) + .RouteTo(new VirutalDataSourceRouteConfig(predicate: where)); + } + public static List GetConnectKeys(this IVirtualDataSourceManager virtualDataSourceManager, IQueryable queryable) where T : class + { + var type = typeof(T); + var connectKeys = virtualDataSourceManager.GetEntityTypeLinkedConnectKeys(type); + if (connectKeys.IsEmpty()) + throw new ShardingCoreException($"entity:[{type}] connect not found"); + + if (!type.IsShardingDataSource()) + throw new ShardingCoreException($"entity:[{type}] is not sharding data source and not found connect"); + return virtualDataSourceManager.GetVirtualDataSource(type) + .RouteTo(new VirutalDataSourceRouteConfig(queryable: queryable)); + } + } +} diff --git a/src/ShardingCore/IShardingCoreOptions.cs b/src/ShardingCore/IShardingCoreOptions.cs new file mode 100644 index 00000000..90b00f00 --- /dev/null +++ b/src/ShardingCore/IShardingCoreOptions.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/4 13:11:16 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public interface IShardingCoreOptions + { + void AddShardingDbContext(string connectKey, string connectString, Action func) where T : DbContext; + + void AddShardingDbContext(string connectKey, string connectString) where T : DbContext; + + + void AddDataSourceVirtualRoute() where TRoute : IDataSourceVirtualRoute; + + + ISet GetShardingConfigs(); + ShardingConfigEntry GetShardingConfig(string connectKey); + ISet GetVirtualRoutes(); + Type GetVirtualRoute(Type entityType); + + } +} diff --git a/src/ShardingCore/ShardingBootstrapper.cs b/src/ShardingCore/ShardingBootstrapper.cs index 54b5ee24..567637cc 100644 --- a/src/ShardingCore/ShardingBootstrapper.cs +++ b/src/ShardingCore/ShardingBootstrapper.cs @@ -1,39 +1,49 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using ShardingCore.Core.PhysicTables; +using ShardingCore.Core.VirtualDataSources; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualTables; using ShardingCore.DbContexts; -using ShardingCore.DbContexts.ShardingTableDbContexts; +using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.VirtualDbContexts; +using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.TableCreator; namespace ShardingCore { -/* -* @Author: xjm -* @Description: -* @Date: Monday, 21 December 2020 09:10:07 -* @Email: 326308290@qq.com -*/ - public class ShardingBootstrapper:IShardingBootstrapper + /* + * @Author: xjm + * @Description: + * @Date: Monday, 21 December 2020 09:10:07 + * @Email: 326308290@qq.com + */ + public class ShardingBootstrapper : IShardingBootstrapper { private readonly IServiceProvider _serviceProvider; + private readonly IShardingCoreOptions _shardingCoreOptions; + private readonly IVirtualDataSourceManager _virtualDataSourceManager; private readonly IVirtualTableManager _virtualTableManager; private readonly IShardingTableCreator _tableCreator; private readonly ILogger _logger; private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly ShardingCoreConfig _shardingCoreConfig; - public ShardingBootstrapper(IServiceProvider serviceProvider, IVirtualTableManager virtualTableManager + public ShardingBootstrapper(IServiceProvider serviceProvider, IShardingCoreOptions shardingCoreOptions, IVirtualDataSourceManager virtualDataSourceManager, IVirtualTableManager virtualTableManager , IShardingTableCreator tableCreator, ILogger logger, IShardingDbContextFactory shardingDbContextFactory, ShardingCoreConfig shardingCoreConfig) { ShardingContainer.SetServices(serviceProvider); _serviceProvider = serviceProvider; + _shardingCoreOptions = shardingCoreOptions; + _virtualDataSourceManager = virtualDataSourceManager; _virtualTableManager = virtualTableManager; _tableCreator = tableCreator; _logger = logger; @@ -43,36 +53,120 @@ namespace ShardingCore public void Start() { - EnsureCreated(); - var virtualTables = _virtualTableManager.GetAllVirtualTables(); - using var scope = _serviceProvider.CreateScope(); - var dbContextOptionsProvider = scope.ServiceProvider.GetService(); - using var context = _shardingDbContextFactory.Create(new ShardingTableDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(), string.Empty, virtualTables.GetVirtualTableDbContextConfigs())); - - foreach (var virtualTable in virtualTables) + //EnsureCreated(); + //_shardingCoreOptions.GetShardingConfigs().Select(o=>o.ConnectKey).ForEach(connectKey=> _virtualDataSourceManager.AddShardingConnectKey(connectKey)); + var isShardingDataSource = _shardingCoreOptions.GetShardingConfigs().Count > 1; + foreach (var virtualRouteType in _shardingCoreOptions.GetVirtualRoutes()) { - //获取ShardingEntity的实际表名 -#if !EFCORE2 - var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName(); -#endif -#if EFCORE2 - var tableName = context.Model.FindEntityType(virtualTable.EntityType).Relational().TableName; -#endif - virtualTable.SetOriginalTableName(tableName); - CreateDataTable(virtualTable); + var virtualRoute = CreateDataSourceVirtualRoute(virtualRouteType); + var virtualDataSource = CreateDataSourceVirtualTable(virtualRoute.ShardingEntityType, virtualRoute); + _virtualDataSourceManager.AddVirtualDataSource(virtualDataSource); } - } - - private void EnsureCreated() - { - if (_shardingCoreConfig.EnsureCreated) + foreach (var shardingConfig in _shardingCoreOptions.GetShardingConfigs()) { + var connectKey = shardingConfig.ConnectKey; + _virtualDataSourceManager.AddShardingConnectKey(connectKey); + using var scope = _serviceProvider.CreateScope(); var dbContextOptionsProvider = scope.ServiceProvider.GetService(); - using var context = _shardingDbContextFactory.Create(new ShardingTableDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(), string.Empty, new List(), true)); - context.Database.EnsureCreated(); + using var context = _shardingDbContextFactory.Create(connectKey, new ShardingDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(connectKey), string.Empty, new List())); + foreach (var entity in context.Model.GetEntityTypes()) + { + + _virtualDataSourceManager.AddConnectEntities(connectKey,entity.ClrType); + if (entity.IsShardingTable()) + { + var routeType = shardingConfig.DbConfigOptions.GetVirtualRoute(entity.ClrType); + var virtualRoute = CreateVirtualRoute(routeType); + var virtualTable = CreateVirtualTable(entity.ClrType, virtualRoute); + + //获取ShardingEntity的实际表名 +#if !EFCORE2 + var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName(); +#endif +#if EFCORE2 + var tableName = context.Model.FindEntityType(virtualTable.EntityType).Relational().TableName; +#endif + virtualTable.SetOriginalTableName(tableName); + _virtualTableManager.AddVirtualTable(connectKey, virtualTable); + CreateDataTable(connectKey,virtualTable); + } + } + } + + } + private IDataSourceVirtualRoute CreateDataSourceVirtualRoute(Type virtualRouteType) + { + var constructors + = virtualRouteType.GetTypeInfo().DeclaredConstructors + .Where(c => !c.IsStatic && c.IsPublic) + .ToArray(); + if (constructors.IsEmpty()) + { + object o = Activator.CreateInstance(virtualRouteType); + return (IDataSourceVirtualRoute)o; + } + else + { + if (constructors.Length > 1) + { + throw new ArgumentException( + $"data source 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 (IDataSourceVirtualRoute)o; } } + private IVirtualDataSource CreateDataSourceVirtualTable(Type entityType, IDataSourceVirtualRoute virtualRoute) + { + Type type = typeof(VirtualDataSource<>); + type = type.MakeGenericType(entityType); + object o = Activator.CreateInstance(type,_serviceProvider, virtualRoute); + return (IVirtualDataSource)o; + } + private IVirtualRoute CreateVirtualRoute(Type virtualRouteType) + { + var constructors + = virtualRouteType.GetTypeInfo().DeclaredConstructors + .Where(c => !c.IsStatic && c.IsPublic) + .ToArray(); + if (constructors.IsEmpty()) + { + object o = Activator.CreateInstance(virtualRouteType); + return (IVirtualRoute)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 (IVirtualRoute)o; + } + } + + private IVirtualTable CreateVirtualTable(Type entityType, IVirtualRoute virtualRoute) + { + Type type = typeof(OneDbVirtualTable<>); + type = type.MakeGenericType(entityType); + object o = Activator.CreateInstance(type, virtualRoute); + return (IVirtualTable)o; + } + + //private void EnsureCreated() + //{ + // if (_shardingCoreConfig.EnsureCreated) + // { + // using var scope = _serviceProvider.CreateScope(); + // var dbContextOptionsProvider = scope.ServiceProvider.GetService(); + // using var context = _shardingDbContextFactory.Create(new ShardingTableDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(), string.Empty, new List(), true)); + // context.Database.EnsureCreated(); + // } + //} private bool NeedCreateTable(ShardingEntityConfig config) { @@ -82,7 +176,7 @@ namespace ShardingCore } return _shardingCoreConfig.CreateShardingTableOnStart.GetValueOrDefault(); } - private void CreateDataTable(IVirtualTable virtualTable) + private void CreateDataTable(string connectKey,IVirtualTable virtualTable) { var shardingConfig = virtualTable.ShardingConfig; foreach (var tail in virtualTable.GetTaleAllTails()) @@ -91,7 +185,7 @@ namespace ShardingCore { try { - _tableCreator.CreateTable(virtualTable.EntityType, tail); + _tableCreator.CreateTable(connectKey,virtualTable.EntityType, tail); } catch (Exception) { diff --git a/src/ShardingCore/ShardingConfigEntry.cs b/src/ShardingCore/ShardingConfigEntry.cs new file mode 100644 index 00000000..46f45821 --- /dev/null +++ b/src/ShardingCore/ShardingConfigEntry.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core; +using ShardingCore.DbContexts.ShardingDbContexts; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/3 16:30:21 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingConfigEntry + { + public ShardingConfigEntry(string connectKey,string connectionString, Func creator, Type dbContextType, Action shardingDbConfigConfigure) + { + ConnectKey = connectKey; + ConnectionString = connectionString; + Creator = creator; + DbContextType = dbContextType; + DbConfigOptions = new ShardingDbConfigOptions(); + shardingDbConfigConfigure?.Invoke(DbConfigOptions); + } + + public Type DbContextType { get; } + public Func Creator { get; } + public ShardingDbConfigOptions DbConfigOptions { get; } + + /// + /// 连接标识 + /// + public string ConnectKey { get; } + + /// + /// 连接字符串 + /// + public string ConnectionString { get; } + + public override int GetHashCode() + { + return this.ConnectKey.GetHashCode() ^ 31; + } + + public override bool Equals(object obj) + { + if (!(obj is ShardingConfigEntry)) + return false; + + if (ReferenceEquals(this, obj)) + return true; + + ShardingConfigEntry item = (ShardingConfigEntry)obj; + + return item.ConnectKey == this.ConnectKey; + } + } +} diff --git a/src/ShardingCore/ShardingDbConfigOptions.cs b/src/ShardingCore/ShardingDbConfigOptions.cs new file mode 100644 index 00000000..c67ea7ed --- /dev/null +++ b/src/ShardingCore/ShardingDbConfigOptions.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.Extensions; + +namespace ShardingCore +{ + /* + * @Author: xjm + * @Description: + * @Date: 2021/3/3 16:15:11 + * @Ver: 1.0 + * @Email: 326308290@qq.com + */ + public class ShardingDbConfigOptions + { + + + private readonly Dictionary _virtualRoutes = new Dictionary(); + public void AddShardingTableRoute() where TRoute : IVirtualRoute + { + var routeType = typeof(TRoute); + //获取类型 + var shardingEntityType = routeType.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IVirtualRoute<>"); + if (!_virtualRoutes.ContainsKey(shardingEntityType)) + { + _virtualRoutes.Add(shardingEntityType, routeType); + } + } + + public Type GetVirtualRoute(Type entityType) + { + if (!_virtualRoutes.ContainsKey(entityType)) + throw new ArgumentException("not found IVirtualRoute"); + return _virtualRoutes[entityType]; + } + } +} diff --git a/src/ShardingCore/TableCreator/IShardingTableCreator.cs b/src/ShardingCore/TableCreator/IShardingTableCreator.cs index fee5ec64..e07406fe 100644 --- a/src/ShardingCore/TableCreator/IShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/IShardingTableCreator.cs @@ -1,5 +1,6 @@ using System; using ShardingCore.Core; +using ShardingCore.Exceptions; namespace ShardingCore.TableCreator { @@ -17,15 +18,17 @@ namespace ShardingCore.TableCreator /// /// 创建表 /// + /// /// /// - void CreateTable(string tail) where T : class, IShardingEntity; + void CreateTable(string connectKey,string tail) where T : class, IShardingEntity; /// /// 创建表 /// + /// /// /// /// - void CreateTable(Type shardingEntityType,string tail); + void CreateTable(string connectKey, 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 e817d1a8..29dc62c2 100644 --- a/src/ShardingCore/TableCreator/ShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/ShardingTableCreator.cs @@ -34,24 +34,25 @@ namespace ShardingCore.TableCreator _serviceProvider = serviceProvider; } - public void CreateTable(string tail) where T : class, IShardingEntity + public void CreateTable(string connectKey,string tail) where T : class, IShardingEntity { - CreateTable(typeof(T), tail); + CreateTable(connectKey,typeof(T), tail); } /// /// /// + /// /// /// /// - public void CreateTable(Type shardingEntityType, string tail) + public void CreateTable(string connectKey, Type shardingEntityType, string tail) { using (var serviceScope = _serviceProvider.CreateScope()) { var dbContextOptionsProvider = serviceScope.ServiceProvider.GetService(); - var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType); + var virtualTable = _virtualTableManager.GetVirtualTable(connectKey,shardingEntityType); - using (var dbContext = _shardingDbContextFactory.Create(new ShardingDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(), tail, + using (var dbContext = _shardingDbContextFactory.Create(connectKey,new ShardingDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(connectKey), tail, new List() {new VirtualTableDbContextConfig(shardingEntityType, virtualTable.GetOriginalTableName(), virtualTable.ShardingConfig.TailPrefix)}))) { var databaseCreator = dbContext.Database.GetService() as RelationalDatabaseCreator; diff --git a/src/ShardingCore/Utils/ShardingUtil.cs b/src/ShardingCore/Utils/ShardingUtil.cs index b124d49a..b0f66b4b 100644 --- a/src/ShardingCore/Utils/ShardingUtil.cs +++ b/src/ShardingCore/Utils/ShardingUtil.cs @@ -6,9 +6,7 @@ using System.Reflection; using ShardingCore.Core; using ShardingCore.Core.Internal; using ShardingCore.Core.Internal.Visitors; -using ShardingCore.Core.PhysicDataSources; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualTables; using ShardingCore.Extensions; namespace ShardingCore.Utils @@ -35,7 +33,7 @@ namespace ShardingCore.Utils } var isShardingDataSource = entityType.IsShardingDataSource(); - var isShardingTable = entityType.IsShardingEntity(); + var isShardingTable = entityType.IsShardingTable(); baseType = new ShardingEntityBaseType() { EntityType = entityType, @@ -95,7 +93,7 @@ namespace ShardingCore.Utils } - public static Func GetRouteDataSourceFilter(IQueryable queryable, ShardingEntityBaseType shardingEntityBaseType, Func shardingKeyConvert, Func>> keyToTailExpression) + public static Func GetRouteDataSourceFilter(IQueryable queryable, ShardingEntityBaseType shardingEntityBaseType, Func shardingKeyConvert, Func>> keyToTailExpression) { QueryableRouteShardingDataSourceDiscoverVisitor visitor = new QueryableRouteShardingDataSourceDiscoverVisitor(shardingEntityBaseType, shardingKeyConvert, keyToTailExpression); diff --git a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyDateTimeVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyDateTimeVirtualRoute.cs index ede546ec..b36790fd 100644 --- a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyDateTimeVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyDateTimeVirtualRoute.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes; namespace ShardingCore.VirtualRoutes.Abstractions { diff --git a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyLongVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyLongVirtualRoute.cs index 1fa5f691..b0948bce 100644 --- a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyLongVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingTimeKeyLongVirtualRoute.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes; namespace ShardingCore.VirtualRoutes.Abstractions { diff --git a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualRoute.cs index a4fb4189..3f19ac48 100644 --- a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualRoute.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.VirtualRoutes.Abstractions; namespace ShardingCore.VirtualRoutes.Days diff --git a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualRoute.cs index 83306986..189e009c 100644 --- a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualRoute.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Helpers; using ShardingCore.VirtualRoutes.Abstractions; diff --git a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualRoute.cs index cf730b13..1fcedb31 100644 --- a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualRoute.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes; namespace ShardingCore.VirtualRoutes.Mods { diff --git a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualRoute.cs index 60f71e19..d6e609fd 100644 --- a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualRoute.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Helpers; namespace ShardingCore.VirtualRoutes.Mods diff --git a/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualRoute.cs b/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualRoute.cs index df7e81a8..36e49d3d 100644 --- a/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualRoute.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Helpers; using ShardingCore.VirtualRoutes.Abstractions; diff --git a/src2x/ShardingCore.2x/ShardingCore.2x.csproj b/src2x/ShardingCore.2x/ShardingCore.2x.csproj index cc4b2488..74f0df2a 100644 --- a/src2x/ShardingCore.2x/ShardingCore.2x.csproj +++ b/src2x/ShardingCore.2x/ShardingCore.2x.csproj @@ -20,9 +20,6 @@ - - Core\Internal\StreamMerge\StreamMergeExtension.cs - diff --git a/src3x/ShardingCore.3x/ShardingCore.3x.csproj b/src3x/ShardingCore.3x/ShardingCore.3x.csproj index 66e8e173..4de4b67a 100644 --- a/src3x/ShardingCore.3x/ShardingCore.3x.csproj +++ b/src3x/ShardingCore.3x/ShardingCore.3x.csproj @@ -22,6 +22,11 @@ + + + + + diff --git a/test/ShardingCore.Test50.MySql/ShardingTest.cs b/test/ShardingCore.Test50.MySql/ShardingTest.cs index 1a2a2e56..dd85a009 100644 --- a/test/ShardingCore.Test50.MySql/ShardingTest.cs +++ b/test/ShardingCore.Test50.MySql/ShardingTest.cs @@ -25,23 +25,23 @@ namespace ShardingCore.Test50.MySql _routingRuleEngineFactory = routingRuleEngineFactory; } - [Fact] - public async Task Route_TEST() - { - var queryable1 = _virtualDbContext.Set().Where(o=>o.Id=="339"); - var routeResults1 = _routingRuleEngineFactory.Route(queryable1); - Assert.Equal(1,routeResults1.Count()); - Assert.Equal(1,routeResults1.FirstOrDefault().ReplaceTables.Count()); - Assert.Equal("0",routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().Tail); - Assert.Equal(nameof(SysUserMod),routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().OriginalName); - var ids = new[] {"339", "124","142"}; - var queryable2= _virtualDbContext.Set().Where(o=>ids.Contains(o.Id)); - var routeResult2s = _routingRuleEngineFactory.Route(queryable2); - Assert.Equal(2,routeResult2s.Count()); - Assert.Equal(1,routeResult2s.FirstOrDefault().ReplaceTables.Count()); - Assert.Equal(2,routeResult2s.SelectMany(o=>o.ReplaceTables).Count()); - Assert.Equal(true,routeResult2s.SelectMany(o=>o.ReplaceTables).All(o=>new[]{"0","1"}.Contains(o.Tail))); - } + //[Fact] + //public async Task Route_TEST() + //{ + // var queryable1 = _virtualDbContext.Set().Where(o=>o.Id=="339"); + // var routeResults1 = _routingRuleEngineFactory.Route(queryable1); + // Assert.Equal(1,routeResults1.Count()); + // Assert.Equal(1,routeResults1.FirstOrDefault().ReplaceTables.Count()); + // Assert.Equal("0",routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().Tail); + // Assert.Equal(nameof(SysUserMod),routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().OriginalName); + // var ids = new[] {"339", "124","142"}; + // var queryable2= _virtualDbContext.Set().Where(o=>ids.Contains(o.Id)); + // var routeResult2s = _routingRuleEngineFactory.Route(queryable2); + // Assert.Equal(2,routeResult2s.Count()); + // Assert.Equal(1,routeResult2s.FirstOrDefault().ReplaceTables.Count()); + // Assert.Equal(2,routeResult2s.SelectMany(o=>o.ReplaceTables).Count()); + // Assert.Equal(true,routeResult2s.SelectMany(o=>o.ReplaceTables).All(o=>new[]{"0","1"}.Contains(o.Tail))); + //} [Fact] public async Task ToList_All_Test() diff --git a/test/ShardingCore.Test50.MySql/Shardings/SysUserSalaryVirtualRoute.cs b/test/ShardingCore.Test50.MySql/Shardings/SysUserSalaryVirtualRoute.cs index de1600d4..90a21585 100644 --- a/test/ShardingCore.Test50.MySql/Shardings/SysUserSalaryVirtualRoute.cs +++ b/test/ShardingCore.Test50.MySql/Shardings/SysUserSalaryVirtualRoute.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Test50.MySql.Domain.Entities; namespace ShardingCore.Test50.MySql.Shardings diff --git a/test/ShardingCore.Test50.MySql/Startup.cs b/test/ShardingCore.Test50.MySql/Startup.cs index 96ea04f0..7f09525b 100644 --- a/test/ShardingCore.Test50.MySql/Startup.cs +++ b/test/ShardingCore.Test50.MySql/Startup.cs @@ -39,18 +39,18 @@ namespace ShardingCore.Test50.MySql // ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) { - services.AddShardingMySql(o => - { - o.ConnectionString = hostBuilderContext.Configuration.GetSection("MySql")["ConnectionString"]; - o.ServerVersion = new MySqlServerVersion(new Version()); - o.AddSharding(); - o.AddSharding(); - o.CreateIfNotExists((provider, config) => - { - config.EnsureCreated = true; - config.CreateShardingTableOnStart = true; - }); - }); + //services.AddShardingMySql(o => + //{ + // o.ConnectionString = hostBuilderContext.Configuration.GetSection("MySql")["ConnectionString"]; + // o.ServerVersion = new MySqlServerVersion(new Version()); + // o.AddSharding(); + // o.AddSharding(); + // o.CreateIfNotExists((provider, config) => + // { + // config.EnsureCreated = true; + // config.CreateShardingTableOnStart = true; + // }); + //}); } // 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法 diff --git a/test/ShardingCore.Test50/ShardingTest.cs b/test/ShardingCore.Test50/ShardingTest.cs index 5e682d29..7b174866 100644 --- a/test/ShardingCore.Test50/ShardingTest.cs +++ b/test/ShardingCore.Test50/ShardingTest.cs @@ -25,23 +25,23 @@ namespace ShardingCore.Test50 _routingRuleEngineFactory = routingRuleEngineFactory; } - [Fact] - public async Task Route_TEST() - { - var queryable1 = _virtualDbContext.Set().Where(o=>o.Id=="339"); - var routeResults1 = _routingRuleEngineFactory.Route(queryable1); - Assert.Equal(1,routeResults1.Count()); - Assert.Equal(1,routeResults1.FirstOrDefault().ReplaceTables.Count()); - Assert.Equal("0",routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().Tail); - Assert.Equal(nameof(SysUserMod),routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().OriginalName); - var ids = new[] {"339", "124","142"}; - var queryable2= _virtualDbContext.Set().Where(o=>ids.Contains(o.Id)); - var routeResult2s = _routingRuleEngineFactory.Route(queryable2); - Assert.Equal(2,routeResult2s.Count()); - Assert.Equal(1,routeResult2s.FirstOrDefault().ReplaceTables.Count()); - Assert.Equal(2,routeResult2s.SelectMany(o=>o.ReplaceTables).Count()); - Assert.Equal(true,routeResult2s.SelectMany(o=>o.ReplaceTables).All(o=>new[]{"0","1"}.Contains(o.Tail))); - } + //[Fact] + //public async Task Route_TEST() + //{ + // var queryable1 = _virtualDbContext.Set().Where(o=>o.Id=="339"); + // var routeResults1 = _routingRuleEngineFactory.Route(queryable1); + // Assert.Equal(1,routeResults1.Count()); + // Assert.Equal(1,routeResults1.FirstOrDefault().ReplaceTables.Count()); + // Assert.Equal("0",routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().Tail); + // Assert.Equal(nameof(SysUserMod),routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().OriginalName); + // var ids = new[] {"339", "124","142"}; + // var queryable2= _virtualDbContext.Set().Where(o=>ids.Contains(o.Id)); + // var routeResult2s = _routingRuleEngineFactory.Route(queryable2); + // Assert.Equal(2,routeResult2s.Count()); + // Assert.Equal(1,routeResult2s.FirstOrDefault().ReplaceTables.Count()); + // Assert.Equal(2,routeResult2s.SelectMany(o=>o.ReplaceTables).Count()); + // Assert.Equal(true,routeResult2s.SelectMany(o=>o.ReplaceTables).All(o=>new[]{"0","1"}.Contains(o.Tail))); + //} [Fact] public async Task ToList_All_Test() { diff --git a/test/ShardingCore.Test50/Shardings/SysUserSalaryVirtualRoute.cs b/test/ShardingCore.Test50/Shardings/SysUserSalaryVirtualRoute.cs index d804189d..cecf0999 100644 --- a/test/ShardingCore.Test50/Shardings/SysUserSalaryVirtualRoute.cs +++ b/test/ShardingCore.Test50/Shardings/SysUserSalaryVirtualRoute.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; using ShardingCore.Core.VirtualRoutes; -using ShardingCore.Core.VirtualRoutes.Abstractions; +using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Test50.Domain.Entities; namespace ShardingCore.Test50.Shardings diff --git a/test/ShardingCore.Test50/Startup.cs b/test/ShardingCore.Test50/Startup.cs index dc80dd3e..739eba76 100644 --- a/test/ShardingCore.Test50/Startup.cs +++ b/test/ShardingCore.Test50/Startup.cs @@ -45,17 +45,17 @@ namespace ShardingCore.Test50 // ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) { - services.AddShardingSqlServer(o => - { - o.ConnectionString = hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]; - o.AddSharding(); - o.AddSharding(); - o.UseShardingCoreConfig((provider, config) => - { - config.EnsureCreated = true; - config.CreateShardingTableOnStart = true; - }); - }); + //services.AddShardingSqlServer(o => + //{ + // o.ConnectionString = hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]; + // o.AddSharding(); + // o.AddSharding(); + // o.UseShardingCoreConfig((provider, config) => + // { + // config.EnsureCreated = true; + // config.CreateShardingTableOnStart = true; + // }); + //}); } // 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法