diff --git a/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs b/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs index 99c95475..37593d48 100644 --- a/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs +++ b/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs @@ -129,7 +129,7 @@ namespace ShardingCore6x _streamMergeContextFactory = ShardingContainer.GetService>(); _actualConnectionStringManager = new ActualConnectionStringManager(); - _virtualDataSource = ShardingContainer.GetService>(); + _virtualDataSource = ShardingContainer.GetRequiredVirtualDataSourceManager().GetVirtualDataSource(); _dataSourceRouteRuleEngineFactory = ShardingContainer.GetService>(); _tableRouteRuleEngineFactory = ShardingContainer.GetService>(); diff --git a/samples/Sample.SqlServer/Controllers/CreateTableController.cs b/samples/Sample.SqlServer/Controllers/CreateTableController.cs index 70a92d8b..27eca44a 100644 --- a/samples/Sample.SqlServer/Controllers/CreateTableController.cs +++ b/samples/Sample.SqlServer/Controllers/CreateTableController.cs @@ -8,6 +8,7 @@ using Sample.SqlServer.Domain.Entities; using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualTables; using ShardingCore.Extensions; @@ -20,17 +21,17 @@ namespace Sample.SqlServer.Controllers public class CreateTableController : ControllerBase { private readonly IShardingTableCreator _tableCreator; - private readonly IVirtualDataSource _virtualDataSource; + private readonly IVirtualDataSourceManager _virtualDataSourceManager; private readonly IVirtualTableManager _virtualTableManager; private readonly IEntityMetadataManager _entityMetadataManager; public CreateTableController(IShardingTableCreator tableCreator, - IVirtualDataSource virtualDataSource, + IVirtualDataSourceManager virtualDataSourceManager, IVirtualTableManager virtualTableManager, IEntityMetadataManager entityMetadataManager) { _tableCreator = tableCreator; - _virtualDataSource = virtualDataSource; + _virtualDataSourceManager = virtualDataSourceManager; _virtualTableManager = virtualTableManager; _entityMetadataManager = entityMetadataManager; } @@ -41,7 +42,7 @@ namespace Sample.SqlServer.Controllers if (isShardingTable) { #region 完全可以用脚本实现这段代码 - var defaultDataSourceName = _virtualDataSource.DefaultDataSourceName; + var defaultDataSourceName = _virtualDataSourceManager.GetVirtualDataSource().DefaultDataSourceName; try { _tableCreator.CreateTable(defaultDataSourceName, "09"); diff --git a/samples/Sample.SqlServerShardingAll/Controllers/TestController.cs b/samples/Sample.SqlServerShardingAll/Controllers/TestController.cs index 94139206..f92541f5 100644 --- a/samples/Sample.SqlServerShardingAll/Controllers/TestController.cs +++ b/samples/Sample.SqlServerShardingAll/Controllers/TestController.cs @@ -23,7 +23,8 @@ namespace Sample.SqlServerShardingAll.Controllers public async Task Query() { #region 动态数据源 - var virtualDataSource = ShardingContainer.GetService>(); + + var virtualDataSource = ShardingContainer.GetRequiredVirtualDataSource(); var virtualDataSourceRoute1 = virtualDataSource.GetRoute(typeof(Order)); virtualDataSourceRoute1.AddDataSourceName("D"); diff --git a/samples/Sample.SqlServerShardingDataSource/DbContextHelper.cs b/samples/Sample.SqlServerShardingDataSource/DbContextHelper.cs index 02e675a3..e857d78c 100644 --- a/samples/Sample.SqlServerShardingDataSource/DbContextHelper.cs +++ b/samples/Sample.SqlServerShardingDataSource/DbContextHelper.cs @@ -22,7 +22,7 @@ namespace Sample.SqlServerShardingDataSource public static void CreateSubDb(string dataSourceName, string connectionString) { var _entityMetadataManager = ShardingContainer.GetService>(); - var _virtualDataSource = ShardingContainer.GetService>(); + var _virtualDataSource = ShardingContainer.GetRequiredVirtualDataSource(); var _virtualTableManager = ShardingContainer.GetService>(); var _tableCreator = ShardingContainer.GetService>(); diff --git a/samples/Sample.SqlServerShardingTable/Startup.cs b/samples/Sample.SqlServerShardingTable/Startup.cs index 6a21c9c9..cfa48464 100644 --- a/samples/Sample.SqlServerShardingTable/Startup.cs +++ b/samples/Sample.SqlServerShardingTable/Startup.cs @@ -36,28 +36,64 @@ namespace Sample.SqlServerShardingTable { services.AddControllers(); - services.AddShardingDbContext((conStr, builder) => + //services.AddShardingDbContext((conStr, builder) => + // { + // builder.UseSqlServer(conStr).UseLoggerFactory(efLogger); + // }).Begin(op => + // { + // //ʹcode-firstѡfalse + // op.CreateShardingTableOnStart = true; + // //ʹcode-first޸Ϊfsle + // op.EnsureCreatedWithOutShardingTable = true; + // //޷ȡ·ʱ᷵ĬֵDZ + // op.ThrowIfQueryRouteNotMatch = true; + // }).AddShardingTransaction((connection, builder) => + // { + // builder.UseSqlServer(connection).UseLoggerFactory(efLogger); + // }).AddDefaultDataSource("ds0", + // "Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;") + // .AddShardingTableRoute(op => + // { + // op.AddShardingTableRoute(); + // op.AddShardingTableRoute(); + // op.AddShardingTableRoute(); + // }).AddReadWriteSeparation(sp => + // { + // return new Dictionary>() + // { + // { + // "ds0", new List() + // { + // "Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;" + // } + // } + // }; + // },ReadStrategyEnum.Loop,defaultEnable:true).End(); + services.AddShardingDbContext().AddEntityConfig(op => + { + //ʹcode-firstѡfalse + op.CreateShardingTableOnStart = true; + //ʹcode-first޸Ϊfsle + op.EnsureCreatedWithOutShardingTable = true; + //޷ȡ·ʱ᷵ĬֵDZ + op.ThrowIfQueryRouteNotMatch = true; + op.AddShardingTableRoute(); + op.AddShardingTableRoute(); + op.AddShardingTableRoute(); + }).AddConfig(op => + { + op.ConfigId = "a"; + op.UseShardingQuery((conStr, builder) => { builder.UseSqlServer(conStr).UseLoggerFactory(efLogger); - }).Begin(op => - { - //ʹcode-firstѡfalse - op.CreateShardingTableOnStart = true; - //ʹcode-first޸Ϊfsle - op.EnsureCreatedWithOutShardingTable = true; - //޷ȡ·ʱ᷵ĬֵDZ - op.ThrowIfQueryRouteNotMatch = true; - }).AddShardingTransaction((connection, builder) => + }); + op.UseShardingTransaction((connection, builder) => { builder.UseSqlServer(connection).UseLoggerFactory(efLogger); - }).AddDefaultDataSource("ds0", - "Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;") - .AddShardingTableRoute(op => - { - op.AddShardingTableRoute(); - op.AddShardingTableRoute(); - op.AddShardingTableRoute(); - }).AddReadWriteSeparation(sp => + }); + op.AddDefaultDataSource("ds0", + "Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;"); + op.AddReadWriteSeparation(sp => { return new Dictionary>() { @@ -68,7 +104,8 @@ namespace Sample.SqlServerShardingTable } } }; - },ReadStrategyEnum.Loop,defaultEnable:true).End(); + }, ReadStrategyEnum.Loop, defaultEnable: true); + }).EnsureConfig(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/ShardingCore/Bootstrapers/EntityMetadataInitializer.cs b/src/ShardingCore/Bootstrapers/EntityMetadataInitializer.cs index 2d2d926b..4616bcc1 100644 --- a/src/ShardingCore/Bootstrapers/EntityMetadataInitializer.cs +++ b/src/ShardingCore/Bootstrapers/EntityMetadataInitializer.cs @@ -21,6 +21,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Infrastructure; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; /* * @Author: xjm @@ -42,14 +43,17 @@ namespace ShardingCore.Bootstrapers private readonly string _virtualTableName; private readonly Expression> _queryFilterExpression; private readonly IShardingConfigOption _shardingConfigOption; - private readonly IVirtualDataSource _virtualDataSource; + private readonly IVirtualDataSourceManager _virtualDataSourceManager; + private readonly IVirtualDataSourceRouteManager _virtualDataSourceRouteManager; private readonly IVirtualTableManager _virtualTableManager; private readonly IEntityMetadataManager _entityMetadataManager; private readonly ILogger> _logger; public EntityMetadataInitializer(EntityMetadataEnsureParams entityMetadataEnsureParams , IShardingConfigOption shardingConfigOption, - IVirtualDataSource virtualDataSource,IVirtualTableManager virtualTableManager, + IVirtualDataSourceManager virtualDataSourceManager, + IVirtualDataSourceRouteManager virtualDataSourceRouteManager, + IVirtualTableManager virtualTableManager, IEntityMetadataManager entityMetadataManager, ILogger> logger ) @@ -58,7 +62,8 @@ namespace ShardingCore.Bootstrapers _virtualTableName = entityMetadataEnsureParams.VirtualTableName; _queryFilterExpression = entityMetadataEnsureParams.EntityType.GetAnnotations().FirstOrDefault(o=>o.Name== QueryFilter)?.Value as Expression>; _shardingConfigOption = shardingConfigOption; - _virtualDataSource = virtualDataSource; + _virtualDataSourceManager = virtualDataSourceManager; + _virtualDataSourceRouteManager = virtualDataSourceRouteManager; _virtualTableManager = virtualTableManager; _entityMetadataManager = entityMetadataManager; _logger = logger; @@ -92,8 +97,7 @@ namespace ShardingCore.Bootstrapers { entityMetadataDataSourceConfiguration.Configure(creatEntityMetadataDataSourceBuilder); } - - _virtualDataSource.AddVirtualDataSourceRoute(dataSourceRoute); + _virtualDataSourceRouteManager.AddVirtualDataSourceRoute(dataSourceRoute); entityMetadata.CheckShardingDataSourceMetadata(); } diff --git a/src/ShardingCore/Bootstrapers/ShardingDbContextBootstrapper.cs b/src/ShardingCore/Bootstrapers/ShardingDbContextBootstrapper.cs index e7bad4f7..7adc86a7 100644 --- a/src/ShardingCore/Bootstrapers/ShardingDbContextBootstrapper.cs +++ b/src/ShardingCore/Bootstrapers/ShardingDbContextBootstrapper.cs @@ -10,9 +10,12 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.PhysicTables; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.ShardingConfigurations.Abstractions; using ShardingCore.Core.TrackerManagers; using ShardingCore.Core.VirtualDatabase; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; @@ -54,25 +57,26 @@ namespace ShardingCore.Bootstrapers /// public class ShardingDbContextBootstrapper : IShardingDbContextBootstrapper where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IShardingConfigOption _shardingConfigOption; - private readonly IVirtualDataSource _virtualDataSource; + private readonly IVirtualDataSourceManager _virtualDataSourceManager; + private readonly IShardingEntityConfigOptions _entityConfigOptions; private readonly IEntityMetadataManager _entityMetadataManager; private readonly IParallelTableManager _parallelTableManager; private readonly IDataSourceInitializer _dataSourceInitializer; private readonly ITrackerManager _trackerManager; private readonly Type _shardingDbContextType; - public ShardingDbContextBootstrapper(IShardingConfigOption shardingConfigOption, + public ShardingDbContextBootstrapper( + IVirtualDataSourceManager virtualDataSourceManager, + IShardingEntityConfigOptions entityConfigOptions, IEntityMetadataManager entityMetadataManager, - IVirtualDataSource virtualDataSource, IParallelTableManager parallelTableManager, IDataSourceInitializer dataSourceInitializer, ITrackerManager trackerManager) { - _shardingConfigOption = shardingConfigOption; _shardingDbContextType = typeof(TShardingDbContext); + _virtualDataSourceManager = virtualDataSourceManager; + _entityConfigOptions = entityConfigOptions; _entityMetadataManager = entityMetadataManager; - _virtualDataSource= virtualDataSource; _parallelTableManager = parallelTableManager; _dataSourceInitializer = dataSourceInitializer; _trackerManager = trackerManager; @@ -82,11 +86,9 @@ namespace ShardingCore.Bootstrapers /// public void Init() { - _virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(_shardingConfigOption.DefaultDataSourceName, _shardingConfigOption.DefaultConnectionString, true)); InitializeEntityMetadata(); InitializeParallelTables(); InitializeConfigure(); - _virtualDataSource.CheckVirtualDataSource(); } private void InitializeEntityMetadata() @@ -102,8 +104,8 @@ namespace ShardingCore.Bootstrapers var entityType = entity.ClrType; _trackerManager.AddDbContextModel(entityType); //entity.GetAnnotation("") - if (_shardingConfigOption.HasVirtualDataSourceRoute(entityType) || - _shardingConfigOption.HasVirtualTableRoute(entityType)) + if (_entityConfigOptions.HasVirtualDataSourceRoute(entityType) || + _entityConfigOptions.HasVirtualTableRoute(entityType)) { var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(_shardingDbContextType, entityType); @@ -119,7 +121,7 @@ namespace ShardingCore.Bootstrapers private void InitializeParallelTables() { - foreach (var parallelTableGroupNode in _shardingConfigOption.GetParallelTableGroupNodes()) + foreach (var parallelTableGroupNode in _entityConfigOptions.GetParallelTableGroupNodes()) { var parallelTableComparerType = parallelTableGroupNode.GetEntities().FirstOrDefault(o => !_entityMetadataManager.IsShardingTable(o.Type)); if (parallelTableComparerType != null) @@ -133,12 +135,16 @@ namespace ShardingCore.Bootstrapers private void InitializeConfigure() { - var dataSources = _shardingConfigOption.GetDataSources(); - foreach (var dataSourceKv in dataSources) + var allVirtualDataSources = _virtualDataSourceManager.GetAllVirtualDataSources(); + foreach (var virtualDataSource in allVirtualDataSources) { - var dataSourceName = dataSourceKv.Key; - var connectionString = dataSourceKv.Value; - _dataSourceInitializer.InitConfigure(dataSourceName, connectionString, true); + var dataSources = virtualDataSource.GetDataSources(); + foreach (var dataSourceKv in dataSources) + { + var dataSourceName = dataSourceKv.Key; + var connectionString = dataSourceKv.Value; + _dataSourceInitializer.InitConfigure(virtualDataSource,dataSourceName, connectionString, true); + } } } } diff --git a/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs b/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs index 763508d4..8053a314 100644 --- a/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs +++ b/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs @@ -13,8 +13,7 @@ namespace ShardingCore.Core.EntityMetadatas /// public class DefaultEntityMetadataManager : IEntityMetadataManager where TShardingDbContext : DbContext, IShardingDbContext { - private readonly ConcurrentDictionary _caches = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _caches =new (); public bool AddEntityMetadata(EntityMetadata entityMetadata) { return _caches.TryAdd(entityMetadata.EntityType, entityMetadata); diff --git a/src/ShardingCore/Core/Internal/PriorityQueues/PriorityQueue.cs b/src/ShardingCore/Core/Internal/PriorityQueues/PriorityQueue.cs index 88590611..8b7beb46 100644 --- a/src/ShardingCore/Core/Internal/PriorityQueues/PriorityQueue.cs +++ b/src/ShardingCore/Core/Internal/PriorityQueues/PriorityQueue.cs @@ -25,7 +25,7 @@ namespace ShardingCore.Core.Internal.PriorityQueues { } public T Top() { - if (heapLength == 0) throw new OverflowException("queu is empty no element can return"); + if (heapLength == 0) throw new OverflowException("queue is empty no element can return"); return buffer[0]; } @@ -38,7 +38,7 @@ namespace ShardingCore.Core.Internal.PriorityQueues { } public void Pop() { - if (heapLength == 0) throw new OverflowException("优先队列为空时无法执行出队操作"); + if (heapLength == 0) throw new OverflowException("queue is empty no element can return"); --heapLength; swap(0, heapLength); Heap.heapAdjustFromTop(buffer, 0, heapLength, descending,this.comparer); diff --git a/src/ShardingCore/Core/ShardingConfigurations/Abstractions/IShardingConfigurationOptions.cs b/src/ShardingCore/Core/ShardingConfigurations/Abstractions/IShardingConfigurationOptions.cs new file mode 100644 index 00000000..c5912837 --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/Abstractions/IShardingConfigurationOptions.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Core.ShardingConfigurations.Abstractions +{ + public interface IShardingConfigurationOptions + { + public void AddShardingGlobalConfigOptions(ShardingGlobalConfigOptions shardingGlobalConfigOptions); + + public ShardingGlobalConfigOptions[] GetAllShardingGlobalConfigOptions(); + } + + public interface IShardingConfigurationOptions : IShardingConfigurationOptions where TShardingDbContext:DbContext,IShardingDbContext + { + + } +} diff --git a/src/ShardingCore/Core/ShardingConfigurations/ConfigBuilders/ShardingEntityConfigBuilder.cs b/src/ShardingCore/Core/ShardingConfigurations/ConfigBuilders/ShardingEntityConfigBuilder.cs new file mode 100644 index 00000000..9d83f6f2 --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/ConfigBuilders/ShardingEntityConfigBuilder.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using ShardingCore.Core.ShardingConfigurations.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common; +using ShardingCore.DIExtensions; +using ShardingCore.Exceptions; +using ShardingCore.Extensions; +using ShardingCore.Sharding; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ShardingComparision.Abstractions; + +namespace ShardingCore.Core.ShardingConfigurations.ConfigBuilders +{ + public class ShardingEntityConfigBuilder + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingCoreConfigBuilder _shardingCoreConfigBuilder; + + public ShardingEntityConfigBuilder(ShardingCoreConfigBuilder shardingCoreConfigBuilder) + { + _shardingCoreConfigBuilder = shardingCoreConfigBuilder; + } + + public ShardingEntityConfigBuilder AddConfig(Action shardingGlobalConfigOptionsConfigure) + { + var shardingGlobalConfigOptions = new ShardingGlobalConfigOptions(); + shardingGlobalConfigOptionsConfigure?.Invoke(shardingGlobalConfigOptions); + if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.ConfigId)) + throw new ArgumentNullException(nameof(shardingGlobalConfigOptions.ConfigId)); + if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.DefaultDataSourceName)) + throw new ArgumentNullException( + $"{nameof(shardingGlobalConfigOptions.DefaultDataSourceName)} plz call {nameof(ShardingGlobalConfigOptions.AddDefaultDataSource)}"); + + if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.DefaultConnectionString)) + throw new ArgumentNullException( + $"{nameof(shardingGlobalConfigOptions.DefaultConnectionString)} plz call {nameof(ShardingGlobalConfigOptions.AddDefaultDataSource)}"); + + if (shardingGlobalConfigOptions.ConnectionStringConfigure is null) + throw new ArgumentNullException($"plz call {nameof(shardingGlobalConfigOptions.UseShardingQuery)}"); + if (shardingGlobalConfigOptions.ConnectionConfigure is null) + throw new ArgumentNullException( + $"plz call {nameof(shardingGlobalConfigOptions.UseShardingTransaction)}"); + + if (shardingGlobalConfigOptions.ReplaceShardingComparerFactory == null) + { + throw new ShardingCoreConfigException($"{nameof(shardingGlobalConfigOptions.ReplaceShardingComparerFactory)} is null"); + } + if (shardingGlobalConfigOptions.MaxQueryConnectionsLimit <= 0) + throw new ArgumentException( + $"{nameof(shardingGlobalConfigOptions.MaxQueryConnectionsLimit)} should greater than and equal 1"); + _shardingCoreConfigBuilder.ShardingGlobalConfigOptions.Add(shardingGlobalConfigOptions); + return this; + } + + public IServiceCollection EnsureConfig() + { + return DoEnsureConfig(false, ShardingConfigurationStrategyEnum.ThrowIfNull); + } + + public IServiceCollection EnsureMultiConfig(ShardingConfigurationStrategyEnum configurationStrategy= ShardingConfigurationStrategyEnum.ThrowIfNull) + { + return DoEnsureConfig(true, configurationStrategy); + } + + private IServiceCollection DoEnsureConfig(bool isMultiConfig, + ShardingConfigurationStrategyEnum configurationStrategy) + { + if (_shardingCoreConfigBuilder.ShardingGlobalConfigOptions.IsEmpty()) + throw new ArgumentException($"plz call {nameof(AddConfig)} at least once "); + if (!isMultiConfig) + { + if (_shardingCoreConfigBuilder.ShardingGlobalConfigOptions.Count > 1) + { + throw new ArgumentException($"call {nameof(AddConfig)} at most once "); + } + } + + var services = _shardingCoreConfigBuilder.Services; + services.AddSingleton(sp => new DbContextTypeCollector()); + services.AddSingleton>(sp => _shardingCoreConfigBuilder.ShardingEntityConfigOptions); + services.AddSingleton(sp => _shardingCoreConfigBuilder.ShardingEntityConfigOptions); + if (!isMultiConfig) + { + services.AddSingleton>(sp => + { + var shardingSingleConfigurationOptions = new ShardingSingleConfigurationOptions(); + shardingSingleConfigurationOptions.ShardingConfigurationStrategy = configurationStrategy; + shardingSingleConfigurationOptions.AddShardingGlobalConfigOptions(_shardingCoreConfigBuilder + .ShardingGlobalConfigOptions.First()); + return shardingSingleConfigurationOptions; + }); + } + else + { + services.AddSingleton>(sp => + { + var shardingMultiConfigurationOptions = new ShardingMultiConfigurationOptions(); + shardingMultiConfigurationOptions.ShardingConfigurationStrategy = configurationStrategy; + foreach (var shardingGlobalConfigOptions in _shardingCoreConfigBuilder + .ShardingGlobalConfigOptions) + { + shardingMultiConfigurationOptions.AddShardingGlobalConfigOptions(shardingGlobalConfigOptions); + } + + return shardingMultiConfigurationOptions; + }); + } + + services.AddInternalShardingCore(); + return services; + } + } +} diff --git a/src/ShardingCore/Core/ShardingConfigurations/ShardingEntityConfigOptions.cs b/src/ShardingCore/Core/ShardingConfigurations/ShardingEntityConfigOptions.cs new file mode 100644 index 00000000..f8f75a02 --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/ShardingEntityConfigOptions.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Core.VirtualRoutes.TableRoutes; +using ShardingCore.Exceptions; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ParallelTables; + +namespace ShardingCore.Core.ShardingConfigurations +{ + public interface IShardingEntityConfigOptions + { + /// + /// 如果数据库不存在就创建并且创建表除了分表的 + /// + bool EnsureCreatedWithOutShardingTable { get; set; } + + /// + /// 是否需要在启动时创建分表 + /// + bool? CreateShardingTableOnStart { get; set; } + /// + /// 当查询遇到没有路由被命中时是否抛出错误 + /// + bool ThrowIfQueryRouteNotMatch { get; set; } + /// + /// 忽略建表时的错误 + /// + bool? IgnoreCreateTableError { get; set; } + bool? EnableTableRouteCompileCache { get; set; } + bool? EnableDataSourceRouteCompileCache { get; set; } + /// + /// 添加分表路由 + /// + /// + void AddShardingDataSourceRoute() where TRoute : IVirtualDataSourceRoute; + void AddShardingDataSourceRoute(Type routeType); + /// + /// 添加分表路由 + /// + /// + void AddShardingTableRoute() where TRoute : IVirtualTableRoute; + void AddShardingTableRoute(Type routeType); + + bool HasVirtualTableRoute(Type entityType); + + Type GetVirtualTableRouteType(Type entityType); + + bool HasVirtualDataSourceRoute(Type entityType); + + Type GetVirtualDataSourceRouteType(Type entityType); + + ISet GetShardingTableRouteTypes(); + + ISet GetShardingDataSourceRouteTypes(); + + /// + /// 平行表 + /// + bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode); + ISet GetParallelTableGroupNodes(); + } + public interface IShardingEntityConfigOptions: IShardingEntityConfigOptions where TShardingDbContext : DbContext, IShardingDbContext + { + } + public class ShardingEntityConfigOptions : IShardingEntityConfigOptions where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly Dictionary _virtualDataSourceRoutes = new Dictionary(); + private readonly Dictionary _virtualTableRoutes = new Dictionary(); + public readonly ISet _parallelTables = new HashSet(); + + /// + /// 如果数据库不存在就创建并且创建表除了分表的 + /// + public bool EnsureCreatedWithOutShardingTable { get; set; } + + /// + /// 是否需要在启动时创建分表 + /// + public bool? CreateShardingTableOnStart { get; set; } + /// + /// 当查询遇到没有路由被命中时是否抛出错误 + /// + public bool ThrowIfQueryRouteNotMatch { get; set; } = true; + public bool? EnableTableRouteCompileCache { get; set; } + public bool? EnableDataSourceRouteCompileCache { get; set; } + /// + /// 忽略建表时的错误 + /// + public bool? IgnoreCreateTableError { get; set; } = true; + /// + /// 添加分表路由 + /// + /// + public void AddShardingDataSourceRoute() where TRoute : IVirtualDataSourceRoute + { + var routeType = typeof(TRoute); + AddShardingDataSourceRoute(routeType); + } + public void AddShardingDataSourceRoute(Type routeType) + { + if (!routeType.IsVirtualDataSourceRoute()) + throw new ShardingCoreInvalidOperationException(routeType.FullName); + //获取类型 + var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualDataSourceRoute<>) + && it.GetGenericArguments().Any()); + if (genericVirtualRoute == null) + throw new ArgumentException("add sharding route type error not assignable from IVirtualDataSourceRoute<>."); + + var shardingEntityType = genericVirtualRoute.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IVirtualDataSourceRoute<>"); + if (!_virtualDataSourceRoutes.ContainsKey(shardingEntityType)) + { + _virtualDataSourceRoutes.Add(shardingEntityType, routeType); + } + } + /// + /// 添加分表路由 + /// + /// + public void AddShardingTableRoute() where TRoute : IVirtualTableRoute + { + var routeType = typeof(TRoute); + AddShardingTableRoute(routeType); + } + public void AddShardingTableRoute(Type routeType) + { + if (!routeType.IsIVirtualTableRoute()) + throw new ShardingCoreInvalidOperationException(routeType.FullName); + //获取类型 + var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualTableRoute<>) + && it.GetGenericArguments().Any()); + if (genericVirtualRoute == null) + throw new ArgumentException("add sharding route type error not assignable from IVirtualTableRoute<>."); + + var shardingEntityType = genericVirtualRoute.GetGenericArguments()[0]; + if (shardingEntityType == null) + throw new ArgumentException("add sharding table route type error not assignable from IVirtualTableRoute<>"); + if (!_virtualTableRoutes.ContainsKey(shardingEntityType)) + { + _virtualTableRoutes.Add(shardingEntityType, routeType); + } + } + + public bool HasVirtualTableRoute(Type entityType) + { + return _virtualTableRoutes.ContainsKey(entityType); + } + + public Type GetVirtualTableRouteType(Type entityType) + { + if (!_virtualTableRoutes.ContainsKey(entityType)) + throw new ArgumentException($"{entityType} not found IVirtualTableRoute"); + return _virtualTableRoutes[entityType]; + } + + public bool HasVirtualDataSourceRoute(Type entityType) + { + return _virtualDataSourceRoutes.ContainsKey(entityType); + } + + public Type GetVirtualDataSourceRouteType(Type entityType) + { + if (!_virtualDataSourceRoutes.ContainsKey(entityType)) + throw new ArgumentException($"{entityType} not found IVirtualDataSourceRoute"); + return _virtualDataSourceRoutes[entityType]; + } + + public ISet GetShardingTableRouteTypes() + { + return _virtualTableRoutes.Keys.ToHashSet(); + } + + public ISet GetShardingDataSourceRouteTypes() + { + return _virtualDataSourceRoutes.Keys.ToHashSet(); + } + public bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode) + { + Check.NotNull(parallelTableGroupNode, $"{nameof(parallelTableGroupNode)}"); + return _parallelTables.Add(parallelTableGroupNode); + } + public ISet GetParallelTableGroupNodes() + { + return _parallelTables; + } + } +} diff --git a/src/ShardingCore/Core/ShardingConfigurations/ShardingGlobalConfigOptions.cs b/src/ShardingCore/Core/ShardingConfigurations/ShardingGlobalConfigOptions.cs new file mode 100644 index 00000000..47269353 --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/ShardingGlobalConfigOptions.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ParallelTables; +using ShardingCore.Sharding.ReadWriteConfigurations; +using ShardingCore.Sharding.ShardingComparision; +using ShardingCore.Sharding.ShardingComparision.Abstractions; + +namespace ShardingCore.Core.ShardingConfigurations +{ + public class ShardingGlobalConfigOptions + { + /// + /// 配置id + /// + public string ConfigId { get; set; } + /// + /// 优先级 + /// + public int Priority { get; set; } + + public int MaxQueryConnectionsLimit { get; set; } = Environment.ProcessorCount; + public ConnectionModeEnum ConnectionMode { get; set; } = ConnectionModeEnum.SYSTEM_AUTO; + /// + /// 读写分离配置 + /// + public ShardingReadWriteSeparationOptions ShardingReadWriteSeparationOptions { get; private set; } + /// + /// 默认数据源 + /// + public string DefaultDataSourceName { get; private set; } + /// + /// 默认数据源链接字符串 + /// + public string DefaultConnectionString { get; private set; } + /// + /// 添加默认数据源 + /// + /// + /// + /// + public void AddDefaultDataSource(string dataSourceName, string connectionString) + { + DefaultDataSourceName= dataSourceName?? throw new ArgumentNullException(nameof(dataSourceName)); + DefaultConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString)); + } + public Func> DataSourcesConfigure { get; private set; } + /// + /// 添加额外数据源 + /// + /// + /// + public void AddExtraDataSource(Func> extraDataSourceConfigure) + { + DataSourcesConfigure= extraDataSourceConfigure ?? throw new ArgumentNullException(nameof(extraDataSourceConfigure)); + } + /// + /// 添加读写分离配置 + /// + /// + /// + /// + /// + /// + /// + public void AddReadWriteSeparation( + Func>> readWriteSeparationConfigure, + ReadStrategyEnum readStrategyEnum, + bool defaultEnable = false, + int defaultPriority = 10, + ReadConnStringGetStrategyEnum readConnStringGetStrategy = ReadConnStringGetStrategyEnum.LatestFirstTime) + { + ShardingReadWriteSeparationOptions = new ShardingReadWriteSeparationOptions(); + ShardingReadWriteSeparationOptions.ReadWriteSeparationConfigure= readWriteSeparationConfigure ?? throw new ArgumentNullException(nameof(readWriteSeparationConfigure)); + ShardingReadWriteSeparationOptions.ReadStrategy = readStrategyEnum; + ShardingReadWriteSeparationOptions.DefaultEnable=defaultEnable; + ShardingReadWriteSeparationOptions.DefaultPriority= defaultPriority; + ShardingReadWriteSeparationOptions.ReadConnStringGetStrategy= readConnStringGetStrategy; + } + + + public Action ConnectionConfigure { get; private set; } + public Action ConnectionStringConfigure { get; private set; } + + + public void UseShardingQuery(Action queryConfigure) + { + ConnectionStringConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure)); + } + public void UseShardingTransaction(Action transactionConfigure) + { + ConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure)); + } + + public Func ReplaceShardingComparerFactory { get; private set; } = sp => new CSharpLanguageShardingComparer(); + /// + /// 替换默认的比较器 + /// + /// + /// + public void ReplaceShardingComparer(Func newShardingComparerFactory) + { + ReplaceShardingComparerFactory = newShardingComparerFactory ?? throw new ArgumentNullException(nameof(newShardingComparerFactory)); + } + + + } +} diff --git a/src/ShardingCore/Core/ShardingConfigurations/ShardingMultiConfigurationOptions.cs b/src/ShardingCore/Core/ShardingConfigurations/ShardingMultiConfigurationOptions.cs new file mode 100644 index 00000000..60a6adaf --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/ShardingMultiConfigurationOptions.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.ShardingConfigurations.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common; +using ShardingCore.Exceptions; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Core.ShardingConfigurations +{ + public class ShardingMultiConfigurationOptions : IShardingConfigurationOptions where TShardingDbContext : DbContext, IShardingDbContext + { + public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; set; } = + ShardingConfigurationStrategyEnum.ThrowIfNull; + + private Dictionary _shardingGlobalConfigOptions = new (); + + public void AddShardingGlobalConfigOptions(ShardingGlobalConfigOptions shardingGlobalConfigOptions) + { + if (_shardingGlobalConfigOptions.ContainsKey(shardingGlobalConfigOptions.ConfigId)) + throw new ShardingCoreInvalidOperationException($"repeat add config id:[{shardingGlobalConfigOptions.ConfigId}]"); + + _shardingGlobalConfigOptions.Add(shardingGlobalConfigOptions.ConfigId, shardingGlobalConfigOptions); + } + + public ShardingGlobalConfigOptions[] GetAllShardingGlobalConfigOptions() + { + return _shardingGlobalConfigOptions.Values.ToArray(); + } + + } +} diff --git a/src/ShardingCore/Core/ShardingConfigurations/ShardingReadWriteSeparationOptions.cs b/src/ShardingCore/Core/ShardingConfigurations/ShardingReadWriteSeparationOptions.cs new file mode 100644 index 00000000..e824ea7e --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/ShardingReadWriteSeparationOptions.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using ShardingCore.Sharding.ReadWriteConfigurations; + +namespace ShardingCore.Core.ShardingConfigurations +{ + public class ShardingReadWriteSeparationOptions + { + public Func>> ReadWriteSeparationConfigure { get; set; } + + public ReadStrategyEnum ReadStrategy { get; set; } = ReadStrategyEnum.Loop; + public bool DefaultEnable { get; set; } = false; + public int DefaultPriority { get; set; } = 10; + + public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; set; } = + ReadConnStringGetStrategyEnum.LatestFirstTime; + } +} diff --git a/src/ShardingCore/Core/ShardingConfigurations/ShardingSingleConfigurationOptions.cs b/src/ShardingCore/Core/ShardingConfigurations/ShardingSingleConfigurationOptions.cs new file mode 100644 index 00000000..bf49267e --- /dev/null +++ b/src/ShardingCore/Core/ShardingConfigurations/ShardingSingleConfigurationOptions.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.ShardingConfigurations.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common; +using ShardingCore.Exceptions; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Core.ShardingConfigurations +{ + public class ShardingSingleConfigurationOptions : IShardingConfigurationOptions where TShardingDbContext : DbContext, IShardingDbContext + { + + private ShardingGlobalConfigOptions _shardingGlobalConfigOptions; + public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; set; } = + ShardingConfigurationStrategyEnum.ThrowIfNull; + + public void AddShardingGlobalConfigOptions(ShardingGlobalConfigOptions shardingGlobalConfigOptions) + { + if (_shardingGlobalConfigOptions != null) + throw new ShardingCoreInvalidOperationException($"repeat add {nameof(ShardingGlobalConfigOptions)}"); + _shardingGlobalConfigOptions= shardingGlobalConfigOptions; + } + + public ShardingGlobalConfigOptions[] GetAllShardingGlobalConfigOptions() + { + return new[] { _shardingGlobalConfigOptions }; + } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/AbstractVirtualDataSourceConfigurationParams.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/AbstractVirtualDataSourceConfigurationParams.cs new file mode 100644 index 00000000..3e37a8bd --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/AbstractVirtualDataSourceConfigurationParams.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ParallelTables; +using ShardingCore.Sharding.ReadWriteConfigurations; +using ShardingCore.Sharding.ShardingComparision.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions +{ + public abstract class AbstractVirtualDataSourceConfigurationParams:IVirtualDataSourceConfigurationParams + where TShardingDbContext : DbContext, IShardingDbContext + { + public abstract string ConfigId { get; } + public abstract int Priority { get; } + public abstract int MaxQueryConnectionsLimit { get; } + public abstract ConnectionModeEnum ConnectionMode { get; } + public abstract string DefaultDataSourceName { get; } + public abstract string DefaultConnectionString { get; } + public abstract IDictionary ExtraDataSources { get; } + public abstract IDictionary> ReadWriteSeparationConfigs { get; } + public abstract ReadStrategyEnum? ReadStrategy { get; } + public abstract bool? ReadWriteDefaultEnable { get; } + public abstract int? ReadWriteDefaultPriority { get; } + public abstract ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; } + public abstract IShardingComparer ShardingComparer { get; } + + + public abstract DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, + DbContextOptionsBuilder dbContextOptionsBuilder); + + public abstract DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, + DbContextOptionsBuilder dbContextOptionsBuilder); + + public virtual bool UseReadWriteSeparation() + { + return ReadWriteSeparationConfigs.IsNotEmpty(); + } + + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IPhysicDataSourcePool.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IPhysicDataSourcePool.cs index 183c1f60..cf7f1356 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IPhysicDataSourcePool.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IPhysicDataSourcePool.cs @@ -29,5 +29,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions /// /// List GetAllDataSourceNames(); + + IDictionary GetDataSources(); } } diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceAccessor.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceAccessor.cs new file mode 100644 index 00000000..d5644c07 --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceAccessor.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions +{ + public interface IVirtualDataSourceAccessor + { + VirtualDataSourceContext DataSourceContext { get; set; } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceConfigurationParams.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceConfigurationParams.cs new file mode 100644 index 00000000..827933ee --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceConfigurationParams.cs @@ -0,0 +1,65 @@ +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ReadWriteConfigurations; +using ShardingCore.Sharding.ShardingComparision.Abstractions; +using System.Collections.Generic; +using System.Data.Common; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions +{ + public interface IVirtualDataSourceConfigurationParams + { + /// + /// 配置id + /// + string ConfigId { get; } + /// + /// 优先级 + /// + int Priority { get; } + int MaxQueryConnectionsLimit { get; } + ConnectionModeEnum ConnectionMode { get; } + + /// + /// 默认数据源 + /// + string DefaultDataSourceName { get; } + /// + /// 默认数据源链接字符串 + /// + string DefaultConnectionString { get; } + IDictionary ExtraDataSources { get; } + IDictionary> ReadWriteSeparationConfigs { get; } + + ReadStrategyEnum? ReadStrategy { get; } + bool? ReadWriteDefaultEnable { get; } + int? ReadWriteDefaultPriority { get; } + /// + /// 读写分离链接字符串获取 + /// + ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; } + IShardingComparer ShardingComparer { get; } + /// + /// 如何根据connectionString 配置 DbContextOptionsBuilder + /// + /// + /// + /// + DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder); + /// + /// 如何根据dbConnection 配置DbContextOptionsBuilder + /// + /// + /// + /// + DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder); + + bool UseReadWriteSeparation(); + } + + public interface IVirtualDataSourceConfigurationParams : IVirtualDataSourceConfigurationParams + where TShardingDbContext : DbContext, IShardingDbContext + { + + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceManager.cs new file mode 100644 index 00000000..8b231f1d --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceManager.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.ShardingConfigurations.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions +{ + public interface IVirtualDataSourceManager + { + bool IsMultiShardingConfiguration { get; } + ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; } + IVirtualDataSource GetVirtualDataSource(); + List GetAllVirtualDataSources(); + + /// + /// 创建分片配置scope + /// + /// + /// + VirtualDataSourceScope CreateScope(string configId); + + } + + public interface IVirtualDataSourceManager : IVirtualDataSourceManager + where TShardingDbContext : DbContext, IShardingDbContext + { + IVirtualDataSource GetVirtualDataSource(); + List> GetAllVirtualDataSources(); + void AddVirtualDataSource(IVirtualDataSourceConfigurationParams configurationParams); + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceRouteManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceRouteManager.cs new file mode 100644 index 00000000..45268f96 --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Abstractions/IVirtualDataSourceRouteManager.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Exceptions; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions +{ + public interface IVirtualDataSourceRouteManager + { + + /// + /// 获取当前数据源的路由 + /// + /// + IVirtualDataSourceRoute GetRoute(Type entityType); + /// + /// 添加分库路由 + /// + /// + /// + /// 对象未配置分库 + bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute); + } + + public interface IVirtualDataSourceRouteManager : IVirtualDataSourceRouteManager + where TShardingDbContext : DbContext, IShardingDbContext + { + IVirtualDataSourceRoute GetRoute() where TEntity:class; + + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Common/ShardingConfigurationStrategyEnum.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Common/ShardingConfigurationStrategyEnum.cs new file mode 100644 index 00000000..3f2b5eae --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/Common/ShardingConfigurationStrategyEnum.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common +{ + public enum ShardingConfigurationStrategyEnum + { + /// + /// 返回空 + /// + ReturnNull = 1, + /// + /// 抛出异常 + /// + ThrowIfNull = 1 << 1, + /// + /// 返回优先级最高的 + /// + ReturnHighPriority = 1 << 2 + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs index ac5ba5d8..0d1a1337 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSource.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Data.Common; using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; @@ -19,10 +22,18 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources public interface IVirtualDataSource { + + string ConfigId { get; } + int Priority { get; } + IVirtualDataSourceConfigurationParams ConfigurationParams { get; } + IConnectionStringManager ConnectionStringManager { get; } + bool UseReadWriteSeparation { get; } /// /// 默认的数据源名称 /// string DefaultDataSourceName { get; } + string DefaultConnectionString { get;} + IVirtualDataSourceRoute GetRoute(Type entityType); /// /// 路由到具体的物理数据源 /// @@ -31,12 +42,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources /// data source names List RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig); - /// - /// 获取当前数据源的路由 - /// - /// - IVirtualDataSourceRoute GetRoute(Type entityType); - /// /// 获取默认的数据源信息 /// @@ -74,13 +79,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources /// 重复添加默认数据源 bool AddPhysicDataSource(IPhysicDataSource physicDataSource); - /// - /// 添加分库路由 - /// - /// - /// - /// 对象未配置分库 - bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute); /// /// 是否默认数据源 /// @@ -92,6 +90,22 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources /// /// void CheckVirtualDataSource(); + /// + /// 如何根据connectionString 配置 DbContextOptionsBuilder + /// + /// + /// + /// + DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder); + /// + /// 如何根据dbConnection 配置DbContextOptionsBuilder + /// + /// + /// + /// + DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder); + + IDictionary GetDataSources(); } /// /// 虚拟数据源 连接所有的实际数据源 @@ -99,5 +113,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources public interface IVirtualDataSource : IVirtualDataSource where TShardingDbContext : DbContext, IShardingDbContext { + IVirtualDataSourceRoute GetRoute() where TEntity:class; } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs deleted file mode 100644 index 4680baea..00000000 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/IVirtualDataSourceManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using Microsoft.EntityFrameworkCore; -//using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; -//using ShardingCore.Core.VirtualRoutes; -//using ShardingCore.Sharding.Abstractions; - -//namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources -//{ -// /* -// * @Author: xjm -// * @Description: -// * @Date: Saturday, 06 February 2021 14:24:01 -// * @Email: 326308290@qq.com -// */ -// public interface IVirtualDataSourceManager -// { -// /// -// /// 添加链接 -// /// -// /// -// bool AddPhysicDataSource(IPhysicDataSource physicDataSource); -// IVirtualDataSource GetVirtualDataSource(); -// IPhysicDataSource GetDefaultDataSource(); -// string GetDefaultDataSourceName(); -// IPhysicDataSource GetPhysicDataSource(string dataSourceName); -// } -// public interface IVirtualDataSourceManager : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext -// { - - - - -// } -//} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/PhysicDataSourcePool.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/PhysicDataSourcePool.cs index 3462bb30..265ce132 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/PhysicDataSourcePool.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/PhysicDataSourcePool.cs @@ -30,5 +30,10 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources { return _physicDataSources.Keys.ToList(); } + + public IDictionary GetDataSources() + { + return _physicDataSources.ToDictionary(k => k.Key, k => k.Value.ConnectionString); + } } } diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/SimpleVirtualDataSourceConfigurationParams.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/SimpleVirtualDataSourceConfigurationParams.cs new file mode 100644 index 00000000..e34c7bed --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/SimpleVirtualDataSourceConfigurationParams.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ParallelTables; +using ShardingCore.Sharding.ReadWriteConfigurations; +using ShardingCore.Sharding.ShardingComparision; +using ShardingCore.Sharding.ShardingComparision.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +{ + public class SimpleVirtualDataSourceConfigurationParams: AbstractVirtualDataSourceConfigurationParams + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly ShardingGlobalConfigOptions _options; + public override string ConfigId { get; } + public override int Priority { get; } + public override int MaxQueryConnectionsLimit { get; } + public override ConnectionModeEnum ConnectionMode { get; } + public override string DefaultDataSourceName { get; } + public override string DefaultConnectionString { get; } + public override IDictionary ExtraDataSources { get; } + public override IDictionary> ReadWriteSeparationConfigs { get; } + public override ReadStrategyEnum? ReadStrategy { get; } + public override bool? ReadWriteDefaultEnable { get; } + public override int? ReadWriteDefaultPriority { get; } + public override ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; } + public override IShardingComparer ShardingComparer { get; } + + public SimpleVirtualDataSourceConfigurationParams(IServiceProvider serviceProvider,ShardingGlobalConfigOptions options) + { + _options = options; + ConfigId = options.ConfigId; + Priority = options.Priority; + MaxQueryConnectionsLimit = options.MaxQueryConnectionsLimit; + ConnectionMode = options.ConnectionMode; + DefaultDataSourceName = options.DefaultDataSourceName; + DefaultConnectionString = options.DefaultConnectionString; + ExtraDataSources = options.DataSourcesConfigure?.Invoke(serviceProvider)??new ConcurrentDictionary(); + ShardingComparer = options.ReplaceShardingComparerFactory?.Invoke(serviceProvider) ?? + new CSharpLanguageShardingComparer(); + if (options.ShardingReadWriteSeparationOptions != null) + { + ReadWriteSeparationConfigs = options.ShardingReadWriteSeparationOptions.ReadWriteSeparationConfigure?.Invoke(serviceProvider); + ReadStrategy = options.ShardingReadWriteSeparationOptions.ReadStrategy; + ReadWriteDefaultEnable = options.ShardingReadWriteSeparationOptions.DefaultEnable; + ReadWriteDefaultPriority = options.ShardingReadWriteSeparationOptions.DefaultPriority; + ReadConnStringGetStrategy = options.ShardingReadWriteSeparationOptions.ReadConnStringGetStrategy; + } + } + + public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, + DbContextOptionsBuilder dbContextOptionsBuilder) + { + _options.ConnectionStringConfigure.Invoke(connectionString, dbContextOptionsBuilder); + return dbContextOptionsBuilder; + } + + public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, + DbContextOptionsBuilder dbContextOptionsBuilder) + { + _options.ConnectionConfigure.Invoke(dbConnection, dbContextOptionsBuilder); + return dbContextOptionsBuilder; + } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs index 4549fc65..9748a447 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSource.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Core.ShardingEnumerableQueries; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; @@ -13,7 +15,9 @@ using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; using ShardingCore.Core.VirtualTables; using ShardingCore.Exceptions; using ShardingCore.Extensions; +using ShardingCore.Sharding; using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ReadWriteConfigurations; using ShardingCore.Utils; namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources @@ -26,26 +30,80 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources */ public class VirtualDataSource : IVirtualDataSource where TShardingDbContext : DbContext, IShardingDbContext { + public IVirtualDataSourceConfigurationParams ConfigurationParams { get; } + public IConnectionStringManager ConnectionStringManager { get; } + private readonly IEntityMetadataManager _entityMetadataManager; - private readonly ConcurrentDictionary _dataSourceVirtualRoutes = new ConcurrentDictionary(); + private readonly IVirtualDataSourceRouteManager _dataSourceRouteManager; private readonly IPhysicDataSourcePool _physicDataSourcePool; + public string ConfigId => ConfigurationParams.ConfigId; + public int Priority => ConfigurationParams.Priority; public string DefaultDataSourceName { get; private set; } public string DefaultConnectionString { get; private set; } + public bool UseReadWriteSeparation { get; } - public VirtualDataSource(IEntityMetadataManager entityMetadataManager) + public VirtualDataSource(IEntityMetadataManager entityMetadataManager, IVirtualDataSourceRouteManager dataSourceRouteManager, IVirtualDataSourceConfigurationParams configurationParams) { - _entityMetadataManager = entityMetadataManager; + ConfigurationParams = configurationParams; _physicDataSourcePool = new PhysicDataSourcePool(); + //Դ + AddPhysicDataSource(new DefaultPhysicDataSource(ConfigurationParams.DefaultDataSourceName, ConfigurationParams.DefaultConnectionString, true)); + foreach (var extraDataSource in ConfigurationParams.ExtraDataSources) + { + AddPhysicDataSource(new DefaultPhysicDataSource(extraDataSource.Key, extraDataSource.Value, false)); + } + _entityMetadataManager = entityMetadataManager; + _dataSourceRouteManager = dataSourceRouteManager; + UseReadWriteSeparation = ConfigurationParams.UseReadWriteSeparation(); + if (UseReadWriteSeparation) + { + CheckReadWriteSeparation(); + ConnectionStringManager = new ReadWriteConnectionStringManager(this); + } + else + { + ConnectionStringManager = new DefaultConnectionStringManager(this); + + } } + private void CheckReadWriteSeparation() + { + if (!ConfigurationParams.ReadStrategy.HasValue) + { + throw new ArgumentException(nameof(ConfigurationParams.ReadStrategy)); + } + if (!ConfigurationParams.ReadConnStringGetStrategy.HasValue) + { + throw new ArgumentException(nameof(ConfigurationParams.ReadConnStringGetStrategy)); + } + if (!ConfigurationParams.ReadWriteDefaultEnable.HasValue) + { + throw new ArgumentException(nameof(ConfigurationParams.ReadWriteDefaultEnable)); + } + if (!ConfigurationParams.ReadWriteDefaultPriority.HasValue) + { + throw new ArgumentException(nameof(ConfigurationParams.ReadWriteDefaultPriority)); + } + } - public List RouteTo(Type entityType,ShardingDataSourceRouteConfig routeRouteConfig) + public IVirtualDataSourceRoute GetRoute(Type entityType) + { + return _dataSourceRouteManager.GetRoute(entityType); + } + + public IVirtualDataSourceRoute GetRoute() where TEntity : class + { + return _dataSourceRouteManager.GetRoute(); + } + + public List RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig) { if (!_entityMetadataManager.IsShardingDataSource(entityType)) return new List(1) { DefaultDataSourceName }; - var virtualDataSourceRoute = GetRoute( entityType); + var virtualDataSourceRoute = _dataSourceRouteManager.GetRoute(entityType); if (routeRouteConfig.UseQueryable()) return virtualDataSourceRoute.RouteWithPredicate(routeRouteConfig.GetQueryable(), true); @@ -72,17 +130,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources throw new NotImplementedException(nameof(ShardingDataSourceRouteConfig)); } - public IVirtualDataSourceRoute GetRoute(Type entityType) - { - if(!_entityMetadataManager.IsShardingDataSource(entityType)) - throw new ShardingCoreInvalidOperationException( - $"entity type :[{entityType.FullName}] not configure sharding data source"); - - if (!_dataSourceVirtualRoutes.TryGetValue(entityType, out var dataSourceVirtualRoute)) - throw new ShardingCoreInvalidOperationException( - $"entity type :[{entityType.FullName}] not found virtual data source route"); - return dataSourceVirtualRoute; - } /// /// ȡĬϵԴϢ /// @@ -101,7 +148,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources { Check.NotNull(dataSourceName, "data source name is null,plz confirm IShardingBootstrapper.Star()"); var dataSource = _physicDataSourcePool.TryGet(dataSourceName); - if (null== dataSource) + if (null == dataSource) throw new ShardingCoreNotFoundException($"data source:[{dataSourceName}]"); return dataSource; @@ -127,6 +174,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources return DefaultConnectionString; return GetPhysicDataSource(dataSourceName).ConnectionString; } + /// /// Դ /// @@ -148,19 +196,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources return _physicDataSourcePool.TryAdd(physicDataSource); } /// - /// ӷֿ· - /// - /// - /// - /// δ÷ֿ - public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute) - { - if (!virtualDataSourceRoute.EntityMetadata.IsShardingDataSource()) - throw new ShardingCoreInvalidOperationException($"{virtualDataSourceRoute.EntityMetadata.EntityType.FullName} should configure sharding data source"); - - return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.EntityMetadata.EntityType, virtualDataSourceRoute); - } - /// /// ǷĬԴ /// /// @@ -182,5 +217,26 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources throw new ShardingCoreInvalidOperationException( $"virtual data source not inited {nameof(DefaultConnectionString)} in IShardingDbContext null"); } + + public DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, + DbContextOptionsBuilder dbContextOptionsBuilder) + { + var doUseDbContextOptionsBuilder = ConfigurationParams.UseDbContextOptionsBuilder(connectionString, dbContextOptionsBuilder); + doUseDbContextOptionsBuilder.UseInnerDbContextSharding(); + return doUseDbContextOptionsBuilder; + } + + public DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, + DbContextOptionsBuilder dbContextOptionsBuilder) + { + var doUseDbContextOptionsBuilder = ConfigurationParams.UseDbContextOptionsBuilder(dbConnection, dbContextOptionsBuilder); + doUseDbContextOptionsBuilder.UseInnerDbContextSharding(); + return doUseDbContextOptionsBuilder; + } + + public IDictionary GetDataSources() + { + return _physicDataSourcePool.GetDataSources(); + } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceAccessor.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceAccessor.cs new file mode 100644 index 00000000..7604d966 --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceAccessor.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +{ + public class VirtualDataSourceAccessor: IVirtualDataSourceAccessor + { + private static AsyncLocal _shardingConfigurationContext = new AsyncLocal(); + + /// + /// sharding route context use in using code block + /// + public VirtualDataSourceContext DataSourceContext + { + get => _shardingConfigurationContext.Value; + set => _shardingConfigurationContext.Value = value; + } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceContext.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceContext.cs new file mode 100644 index 00000000..54f96fe0 --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceContext.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +{ + public class VirtualDataSourceContext + { + public string ConfigId { get; } + + public VirtualDataSourceContext(string configId) + { + ConfigId = configId; + } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs index b23a1580..a3e412ce 100644 --- a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceManager.cs @@ -1,74 +1,140 @@ -//using System; -//using System.Collections.Concurrent; -//using System.Collections.Generic; -//using System.Linq; -//using Microsoft.EntityFrameworkCore; -//using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; -//using ShardingCore.Core.VirtualRoutes; -//using ShardingCore.Sharding.Abstractions; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.ShardingConfigurations.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common; +using ShardingCore.Exceptions; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; -//namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources -//{ -// /* -// * @Author: xjm -// * @Description: -// * @Date: Saturday, 06 February 2021 15:24:08 -// * @Email: 326308290@qq.com -// */ -// public class VirtualDataSourceManager : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext -// { -// private readonly IServiceProvider _serviceProvider; -// /// -// /// {sharding db context type :{entity type:virtual data source}} -// /// -// private readonly ConcurrentDictionary _virtualDataSources = new ConcurrentDictionary(); +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +{ + public class VirtualDataSourceManager : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly IShardingConfigurationOptions _options; + private readonly IEntityMetadataManager _entityMetadataManager; + private readonly IVirtualDataSourceRouteManager _virtualDataSourceRouteManager; + private readonly IVirtualDataSourceAccessor _virtualDataSourceAccessor; + private readonly ConcurrentDictionary _virtualDataSources = new(); + private string _defaultConfigId; + private IVirtualDataSource _defaultVirtualDataSource; + public VirtualDataSourceManager(IServiceProvider serviceProvider,IShardingConfigurationOptions options,IEntityMetadataManager entityMetadataManager,IVirtualDataSourceRouteManager virtualDataSourceRouteManager, IVirtualDataSourceAccessor virtualDataSourceAccessor) + { -// public VirtualDataSourceManager(IServiceProvider serviceProvider) -// { -// _serviceProvider = serviceProvider; -// //var shardingEntities = AssemblyHelper.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes()) -// // .Where(type => !String.IsNullOrEmpty(type.Namespace)) -// // .Where(type => !type.IsAbstract&&type.GetInterfaces() -// // .Any(it => it.IsInterface &&typeof(IShardingDataSource)==it) -// // ); -// //foreach (var shardingEntity in shardingEntities) -// //{ -// // Type genericType = typeof(IVirtualDataSource<>); -// // Type interfaceType = genericType.MakeGenericType(shardingEntity); -// // var virtualDataSource = (IVirtualDataSource)serviceProvider.GetService(interfaceType); -// // _virtualDataSources.TryAdd(virtualDataSource.EntityType, virtualDataSource); -// //} -// } + _options = options; + _entityMetadataManager = entityMetadataManager; + _virtualDataSourceRouteManager = virtualDataSourceRouteManager; + var allShardingGlobalConfigOptions = options.GetAllShardingGlobalConfigOptions(); + if (allShardingGlobalConfigOptions.IsEmpty()) + throw new ArgumentException($"sharding virtual data source is empty"); + _virtualDataSourceAccessor = virtualDataSourceAccessor; + if (options is ShardingMultiConfigurationOptions shardingMultiConfigurationOptions) + { + IsMultiShardingConfiguration = true; + ShardingConfigurationStrategy = shardingMultiConfigurationOptions.ShardingConfigurationStrategy; + } + else if (options is ShardingSingleConfigurationOptions shardingSingleConfigurationOptions) + { + IsMultiShardingConfiguration = false; + ShardingConfigurationStrategy = shardingSingleConfigurationOptions.ShardingConfigurationStrategy; + } + foreach (var shardingGlobalConfigOption in allShardingGlobalConfigOptions) + { + var simpleVirtualDataSourceConfigurationParams = new SimpleVirtualDataSourceConfigurationParams(serviceProvider,shardingGlobalConfigOption); + var dataSource = new VirtualDataSource(_entityMetadataManager,_virtualDataSourceRouteManager, simpleVirtualDataSourceConfigurationParams); + dataSource.CheckVirtualDataSource(); + if (!IsMultiShardingConfiguration) + { + if (_defaultVirtualDataSource != null || _defaultConfigId != null) + throw new ShardingCoreInvalidOperationException("set sharding configuration error"); + _defaultVirtualDataSource = dataSource; + _defaultConfigId = dataSource.ConfigId; + } + _virtualDataSources.TryAdd(dataSource.ConfigId, dataSource); + } -// public bool AddPhysicDataSource(IPhysicDataSource physicDataSource) -// { -// throw new NotImplementedException(); -// } + if (IsMultiShardingConfiguration) + { + var maxShardingConfiguration = _virtualDataSources.Values.OrderByDescending(o => o.Priority).FirstOrDefault(); + _defaultVirtualDataSource = maxShardingConfiguration; + _defaultConfigId = maxShardingConfiguration.ConfigId; + } + } + public bool IsMultiShardingConfiguration { get; } + public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; } + public IVirtualDataSource GetVirtualDataSource() + { + if (!IsMultiShardingConfiguration) + return _defaultVirtualDataSource; + var configId = _virtualDataSourceAccessor.DataSourceContext?.ConfigId; + if (!string.IsNullOrWhiteSpace(configId)) + { + var hasValue = _virtualDataSources.TryGetValue(configId, out var virtualDataSource); + if (hasValue) + { + return virtualDataSource; + } + } -// public IVirtualDataSource GetVirtualDataSource() -// { -// if (!_virtualDataSources.TryGetValue(shardingDbContextType, out var virtualDataSource)) -// throw new ShardingCoreInvalidOperationException($"not found virtual data source sharding db context type:[{shardingDbContextType.FullName}]"); -// return virtualDataSource; -// } + switch (ShardingConfigurationStrategy) + { + case ShardingConfigurationStrategyEnum.ReturnNull: return null; + case ShardingConfigurationStrategyEnum.ReturnHighPriority: return _defaultVirtualDataSource; + case ShardingConfigurationStrategyEnum.ThrowIfNull: throw new ShardingCoreNotFoundException($"no configuration,config id:[{configId}]"); + default: + throw new ShardingCoreException( + $"unknown {nameof(ShardingConfigurationStrategyEnum)}:[{ShardingConfigurationStrategy}]"); + } + } -// public IPhysicDataSource GetDefaultDataSource() -// { -// var virtualDataSource = GetVirtualDataSource(shardingDbContextType); -// return virtualDataSource.GetDefaultDataSource(); -// } + List> IVirtualDataSourceManager.GetAllVirtualDataSources() + { + return GetAllVirtualDataSources().Select(o => (IVirtualDataSource)o).ToList(); + } -// public string GetDefaultDataSourceName() -// { -// var virtualDataSource = GetVirtualDataSource(shardingDbContextType); -// return virtualDataSource.DefaultDataSourceName; -// } + public void AddVirtualDataSource(IVirtualDataSourceConfigurationParams configurationParams) + { + if (!IsMultiShardingConfiguration) + throw new NotSupportedException("not support multi sharding configuration"); + var dataSource = new VirtualDataSource(_entityMetadataManager, _virtualDataSourceRouteManager, configurationParams); + dataSource.CheckVirtualDataSource(); + if(_virtualDataSources.TryAdd(dataSource.ConfigId, dataSource)) + { + if (IsMultiShardingConfiguration) + { + var maxShardingConfiguration = _virtualDataSources.Values.OrderByDescending(o => o.Priority).FirstOrDefault(); + _defaultVirtualDataSource = maxShardingConfiguration; + _defaultConfigId = maxShardingConfiguration.ConfigId; + } + } + } -// public IPhysicDataSource GetPhysicDataSource(string dataSourceName) -// { -// throw new NotImplementedException(); -// } -// } -//} \ No newline at end of file + IVirtualDataSource IVirtualDataSourceManager.GetVirtualDataSource() + { + return (IVirtualDataSource)GetVirtualDataSource(); + } + + public List GetAllVirtualDataSources() + { + if (!IsMultiShardingConfiguration) + return new List(1) { _defaultVirtualDataSource }; + return _virtualDataSources.Values.ToList(); + } + + public VirtualDataSourceScope CreateScope(string configId) + { + var virtualDataSourceScope = new VirtualDataSourceScope(_virtualDataSourceAccessor); + _virtualDataSourceAccessor.DataSourceContext = new VirtualDataSourceContext(configId); + return virtualDataSourceScope; + } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceRouteManager.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceRouteManager.cs new file mode 100644 index 00000000..543cff22 --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceRouteManager.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.ShardingEnumerableQueries; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Core.VirtualRoutes.DataSourceRoutes; +using ShardingCore.Exceptions; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +{ + public class VirtualDataSourceRouteManager : IVirtualDataSourceRouteManager + where TShardingDbContext : DbContext, IShardingDbContext + { + private readonly IEntityMetadataManager _entityMetadataManager; + private readonly ConcurrentDictionary _dataSourceVirtualRoutes = new ConcurrentDictionary(); + + public VirtualDataSourceRouteManager(IEntityMetadataManager entityMetadataManager) + { + _entityMetadataManager = entityMetadataManager; + } + + public IVirtualDataSourceRoute GetRoute() where TEntity : class + { + return (IVirtualDataSourceRoute)GetRoute(typeof(TEntity)); + } + + public IVirtualDataSourceRoute GetRoute(Type entityType) + { + if (!_entityMetadataManager.IsShardingDataSource(entityType)) + throw new ShardingCoreInvalidOperationException( + $"entity type :[{entityType.FullName}] not configure sharding data source"); + + if (!_dataSourceVirtualRoutes.TryGetValue(entityType, out var dataSourceVirtualRoute)) + throw new ShardingCoreInvalidOperationException( + $"entity type :[{entityType.FullName}] not found virtual data source route"); + return dataSourceVirtualRoute; + } + /// + /// 添加分库路由 + /// + /// + /// + /// 对象未配置分库 + public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute) + { + if (!virtualDataSourceRoute.EntityMetadata.IsShardingDataSource()) + throw new ShardingCoreInvalidOperationException($"{virtualDataSourceRoute.EntityMetadata.EntityType.FullName} should configure sharding data source"); + + return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.EntityMetadata.EntityType, virtualDataSourceRoute); + } + } +} diff --git a/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceScope.cs b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceScope.cs new file mode 100644 index 00000000..00a45f4b --- /dev/null +++ b/src/ShardingCore/Core/VirtualDatabase/VirtualDataSources/VirtualDataSourceScope.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; + +namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources +{ + public class VirtualDataSourceScope:IDisposable + { + /// + /// 分片配置访问器 + /// + public IVirtualDataSourceAccessor VirtualDataSourceAccessor { get; } + + /// + /// 构造函数 + /// + /// + public VirtualDataSourceScope(IVirtualDataSourceAccessor virtualDataSourceAccessor) + { + VirtualDataSourceAccessor = virtualDataSourceAccessor; + } + + /// + /// 回收 + /// + public void Dispose() + { + VirtualDataSourceAccessor.DataSourceContext = null; + } + } +} diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs index d71f10c2..0a30b39d 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs @@ -35,7 +35,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions { if (EnableRouteParseCompileCache.HasValue) return EnableRouteParseCompileCache.Value; - return ShardingConfigOption.EnableDataSourceRouteCompileCache.GetValueOrDefault(); + return EntityConfigOptions.EnableDataSourceRouteCompileCache.GetValueOrDefault(); } /// diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs index 627d7a7b..6f78ccb1 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.EntityShardingMetadatas; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Exceptions; using ShardingCore.Sharding.MergeEngines.ParallelControl; using ShardingCore.Sharding.PaginationConfigurations; @@ -19,7 +20,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions { public EntityMetadata EntityMetadata { get; private set; } private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce(); - public IShardingConfigOption ShardingConfigOption { get; private set; } + public IShardingEntityConfigOptions EntityConfigOptions { get; private set; } public void Initialize(EntityMetadata entityMetadata) @@ -35,8 +36,8 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions paginationConfiguration.Configure(paginationBuilder); } - ShardingConfigOption = - ShardingContainer.GetRequiredShardingConfigOption(entityMetadata.ShardingDbContextType); + EntityConfigOptions = + ShardingContainer.GetRequiredShardingEntityConfigOption(entityMetadata.ShardingDbContextType); } public virtual IPaginationConfiguration CreatePaginationConfiguration() diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleContext.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleContext.cs index 8ee5ba96..541ed379 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleContext.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleContext.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine { @@ -19,15 +21,20 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine /// public class DataSourceRouteRuleContext { - public ISet QueryEntities { get; } - public DataSourceRouteRuleContext(IQueryable queryable,Type dbContextType) + public DataSourceRouteRuleContext(IQueryable queryable,IShardingDbContext shardingDbContext) { Queryable = queryable; - QueryEntities = queryable.ParseQueryableEntities(dbContextType); + ShardingDbContext = shardingDbContext; + VirtualDataSource = shardingDbContext.GetVirtualDataSource(); + QueryEntities = queryable.ParseQueryableEntities(shardingDbContext.GetType()); } + public ISet QueryEntities { get; } /// /// 查询条件 /// public IQueryable Queryable { get; } + + public IShardingDbContext ShardingDbContext { get; } + public IVirtualDataSource VirtualDataSource { get; } } } diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs index 8fe4c33b..e87cf03f 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngine.cs @@ -21,21 +21,20 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine */ public class DataSourceRouteRuleEngine : IDataSourceRouteRuleEngine where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IVirtualDataSource _virtualDataSource; private readonly IEntityMetadataManager _entityMetadataManager; - public DataSourceRouteRuleEngine(IVirtualDataSource virtualDataSource,IEntityMetadataManager entityMetadataManager) + public DataSourceRouteRuleEngine(IEntityMetadataManager entityMetadataManager) { - _virtualDataSource = virtualDataSource; _entityMetadataManager = entityMetadataManager; } public DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext) { + var virtualDataSource = routeRuleContext.VirtualDataSource; var dataSourceMaps = new Dictionary>(); var notShardingDataSourceEntityType = routeRuleContext.QueryEntities.FirstOrDefault(o => !_entityMetadataManager.IsShardingDataSource(o)); //存在不分库的 if (notShardingDataSourceEntityType != null) - dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet() { _virtualDataSource.DefaultDataSourceName }); + dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet() { virtualDataSource.DefaultDataSourceName }); //if (queryEntities.Count > 1) @@ -46,7 +45,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine { continue; } - var dataSourceConfigs = _virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable)); + var dataSourceConfigs = virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable)); if (!dataSourceMaps.ContainsKey(queryEntity)) { dataSourceMaps.Add(queryEntity, dataSourceConfigs.ToHashSet()); diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs index d8a9f9db..94873161 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/DataSourceRouteRuleEngineFactory.cs @@ -33,20 +33,22 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine /// /// /// + /// /// - public DataSourceRouteRuleContext CreateContext(IQueryable queryable) + public DataSourceRouteRuleContext CreateContext(IQueryable queryable,IShardingDbContext shardingDbContext) { - return new DataSourceRouteRuleContext(queryable,typeof(TShardingDbContext)); + return new DataSourceRouteRuleContext(queryable, shardingDbContext); } /// /// 路由到具体的物理数据源 /// /// /// + /// /// - public DataSourceRouteResult Route(IQueryable queryable) + public DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext) { - var ruleContext = CreateContext(queryable); + var ruleContext = CreateContext(queryable, shardingDbContext); return _dataSourceRouteRuleEngine.Route(ruleContext); } /// diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs index 85dc2ddc..3a769daf 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/RouteRuleEngine/IDataSourceRouteRuleEngineFactory.cs @@ -16,8 +16,8 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine */ public interface IDataSourceRouteRuleEngineFactory { - DataSourceRouteRuleContext CreateContext(IQueryable queryable); - DataSourceRouteResult Route(IQueryable queryable); + DataSourceRouteRuleContext CreateContext(IQueryable queryable, IShardingDbContext shardingDbContext); + DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext); DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext); } public interface IDataSourceRouteRuleEngineFactory : IDataSourceRouteRuleEngineFactory diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs index d19b34cd..0725ab71 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs @@ -37,7 +37,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions { if (EnableRouteParseCompileCache.HasValue) return EnableRouteParseCompileCache.Value; - return ShardingConfigOption.EnableTableRouteCompileCache.GetValueOrDefault(); + return EntityConfigOptions.EnableTableRouteCompileCache.GetValueOrDefault(); } /// /// 对表达式进行缓存编译默认永久缓存单个参数表达式,且不包含orElse只包含单个AndAlso或者没有AndAlso的, diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs index ca3a1bee..9f5d829b 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs @@ -5,6 +5,7 @@ using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.QueryRouteManagers; using ShardingCore.Core.QueryRouteManagers.Abstractions; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Exceptions; using ShardingCore.Extensions; using ShardingCore.Sharding.MergeEngines.ParallelControl; @@ -22,14 +23,15 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions { private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce(); - public IShardingConfigOption ShardingConfigOption { get; private set; } + public IShardingEntityConfigOptions EntityConfigOptions { get; private set; } public virtual void Initialize(EntityMetadata entityMetadata) { if (!_doOnlyOnce.IsUnDo()) throw new ShardingCoreInvalidOperationException("already init"); EntityMetadata = entityMetadata; - ShardingConfigOption = - ShardingContainer.GetRequiredShardingConfigOption(entityMetadata.ShardingDbContextType); + + EntityConfigOptions = + ShardingContainer.GetRequiredShardingEntityConfigOption(entityMetadata.ShardingDbContextType); } public virtual IPaginationConfiguration CreatePaginationConfiguration() { diff --git a/src/ShardingCore/DIExtension.cs b/src/ShardingCore/DIExtension.cs index 60a770aa..e7155794 100644 --- a/src/ShardingCore/DIExtension.cs +++ b/src/ShardingCore/DIExtension.cs @@ -30,6 +30,8 @@ using ShardingCore.Sharding.ShardingQueryExecutors; using ShardingCore.TableCreator; using System; using ShardingCore.Core.QueryTrackers; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.DynamicDataSources; using ShardingCore.Sharding.ParallelTables; using ShardingCore.Sharding.ReadWriteConfigurations; @@ -53,13 +55,11 @@ namespace ShardingCore /// /// /// - /// /// /// /// /// public static ShardingCoreConfigBuilder AddShardingDbContext(this IServiceCollection services, - Action optionsAction = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TShardingDbContext : DbContext, IShardingDbContext @@ -70,20 +70,20 @@ namespace ShardingCore throw new NotSupportedException($"{nameof(optionsLifetime)}:{nameof(ServiceLifetime.Singleton)}"); Action shardingOptionAction = (sp, option) => { - var virtualDataSource = sp.GetRequiredService>(); + var virtualDataSource = sp.GetRequiredService>().GetVirtualDataSource(); var connectionString = virtualDataSource.GetConnectionString(virtualDataSource.DefaultDataSourceName); - optionsAction?.Invoke(connectionString, option); + virtualDataSource.ConfigurationParams.UseDbContextOptionsBuilder(connectionString, option); option.UseSharding(); }; services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); - return services.AddShardingConfigure(optionsAction); + return services.AddShardingConfigure(); } - public static ShardingCoreConfigBuilder AddShardingConfigure(this IServiceCollection services, Action queryConfigure) + public static ShardingCoreConfigBuilder AddShardingConfigure(this IServiceCollection services) where TShardingDbContext : DbContext, IShardingDbContext { ShardingCoreHelper.CheckContextConstructors(); - return new ShardingCoreConfigBuilder(services, queryConfigure); + return new ShardingCoreConfigBuilder(services); } internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services) @@ -98,10 +98,11 @@ namespace ShardingCore services.TryAddSingleton(typeof(IStreamMergeContextFactory<>), typeof(StreamMergeContextFactory<>)); services.TryAddSingleton(typeof(IShardingTableCreator<>), typeof(ShardingTableCreator<>)); //虚拟数据源管理 - services.TryAddSingleton(typeof(IVirtualDataSource<>), typeof(VirtualDataSource<>)); + services.TryAddSingleton(typeof(IVirtualDataSourceRouteManager<>), typeof(VirtualDataSourceRouteManager<>)); services.TryAddSingleton(typeof(IDataSourceRouteRuleEngine<>), typeof(DataSourceRouteRuleEngine<>)); services.TryAddSingleton(typeof(IDataSourceRouteRuleEngineFactory<>), typeof(DataSourceRouteRuleEngineFactory<>)); - + //读写分离链接创建工厂 + services.TryAddSingleton(); //虚拟表管理 services.TryAddSingleton(typeof(IVirtualTableManager<>), typeof(VirtualTableManager<>)); @@ -163,5 +164,29 @@ namespace ShardingCore .ReplaceService() .ReplaceService>(); } + + + + + //public static IServiceCollection AddSingleShardingDbContext(this IServiceCollection services, Action configure, + // Action optionsAction = null, + // ServiceLifetime contextLifetime = ServiceLifetime.Scoped, + // ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) + // where TShardingDbContext : DbContext, IShardingDbContext + //{ + // if (contextLifetime == ServiceLifetime.Singleton) + // throw new NotSupportedException($"{nameof(contextLifetime)}:{nameof(ServiceLifetime.Singleton)}"); + // if (optionsLifetime == ServiceLifetime.Singleton) + // throw new NotSupportedException($"{nameof(optionsLifetime)}:{nameof(ServiceLifetime.Singleton)}"); + // Action shardingOptionAction = (sp, option) => + // { + // var virtualDataSource = sp.GetRequiredService>().GetVirtualDataSource(); + // var connectionString = virtualDataSource.GetConnectionString(virtualDataSource.DefaultDataSourceName); + // optionsAction?.Invoke(connectionString, option); + // option.UseSharding(); + // }; + // services.AddDbContext(shardingOptionAction, contextLifetime, optionsLifetime); + // return services.AddShardingConfigure(optionsAction); + //} } } \ No newline at end of file diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs index 1a2e3d74..ac003bb9 100644 --- a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs @@ -4,6 +4,9 @@ using System.Linq; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using ShardingCore.Core; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.ShardingConfigurations.ConfigBuilders; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.ParallelTables; @@ -24,17 +27,19 @@ namespace ShardingCore.DIExtensions public ShardingConfigOption ShardingConfigOption { get; } + public List ShardingGlobalConfigOptions { get; } + public ShardingEntityConfigOptions ShardingEntityConfigOptions { get; } - - public ShardingCoreConfigBuilder(IServiceCollection services,Action queryConfigure) + public ShardingCoreConfigBuilder(IServiceCollection services) { Services = services; ShardingConfigOption = new ShardingConfigOption(); - ShardingConfigOption.UseShardingQuery(queryConfigure); + ShardingGlobalConfigOptions = new List(); + ShardingEntityConfigOptions = new ShardingEntityConfigOptions(); } - + [Obsolete("plz use AddEntityConfig")] public ShardingTransactionBuilder Begin(Action shardingCoreBeginOptionsConfigure) { var shardingCoreBeginOptions = new ShardingCoreBeginOptions(); @@ -64,6 +69,12 @@ namespace ShardingCore.DIExtensions return new ShardingTransactionBuilder(this); //return new ShardingQueryBuilder(this); } + + public ShardingEntityConfigBuilder AddEntityConfig(Action> entityConfigure) + { + entityConfigure?.Invoke(ShardingEntityConfigOptions); + return new ShardingEntityConfigBuilder(this); + } //public ShardingCoreConfigBuilder AddDefaultDataSource(string dataSourceName, string connectionString) //{ // if (!string.IsNullOrWhiteSpace(defaultDataSourceName) || !string.IsNullOrWhiteSpace(defaultConnectionString)) @@ -84,6 +95,14 @@ namespace ShardingCore.DIExtensions public class ShardingCoreBeginOptions { + /// + /// 配置id + /// + public string ConfigId { get; set; } + /// + /// 优先级 + /// + public int Priority { get; set; } /// /// 如果数据库不存在就创建并且创建表除了分表的 /// @@ -114,7 +133,7 @@ namespace ShardingCore.DIExtensions public bool? EnableTableRouteCompileCache { get; set; } public bool? EnableDataSourceRouteCompileCache { get; set; } - private readonly ISet _createTableEntities = new HashSet(); + private readonly ISet _createTableEntities = new HashSet(); public void AddEntitiesTryCreateTable(params Type[] entityTypes) { diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs index 8f124f55..35ffff4c 100644 --- a/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs @@ -42,7 +42,7 @@ namespace ShardingCore.DIExtensions /// /// /// - public ShardingCoreConfigEndBuilder ReplaceShardingComparer(Func> newShardingComparerFactory) + public ShardingCoreConfigEndBuilder ReplaceShardingComparer(Func newShardingComparerFactory) { _shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory); return this; @@ -64,19 +64,19 @@ namespace ShardingCore.DIExtensions _shardingCoreConfigBuilder.ShardingConfigOption); - //添加创建TActualDbContext 的DbContextOptionsBuilder创建者 - var config = new ShardingDbContextOptionsBuilderConfig( - _shardingCoreConfigBuilder.ShardingConfigOption.SameConnectionConfigure, - _shardingCoreConfigBuilder.ShardingConfigOption.DefaultQueryConfigure); - services - .AddSingleton, - ShardingDbContextOptionsBuilderConfig>(sp => config); + ////添加创建TActualDbContext 的DbContextOptionsBuilder创建者 + //var config = new ShardingDbContextOptionsBuilderConfig( + // _shardingCoreConfigBuilder.ShardingConfigOption.SameConnectionConfigure, + // _shardingCoreConfigBuilder.ShardingConfigOption.DefaultQueryConfigure); + //services + // .AddSingleton, + // ShardingDbContextOptionsBuilderConfig>(sp => config); if (_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory == null) { throw new ShardingCoreConfigException($"{nameof(_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory)} is null"); } - services.AddSingleton>(_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory); + //services.AddSingleton(_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory); if (_shardingCoreConfigBuilder.ShardingConfigOption.TableEnsureManagerFactory == null) { throw new ShardingCoreConfigException($"{nameof(_shardingCoreConfigBuilder.ShardingConfigOption.TableEnsureManagerFactory)} is null"); @@ -84,15 +84,15 @@ namespace ShardingCore.DIExtensions services.AddSingleton>(_shardingCoreConfigBuilder.ShardingConfigOption.TableEnsureManagerFactory); - if (!UseReadWrite) - { - services.AddTransient, DefaultConnectionStringManager>(); - } - else - { - services.AddTransient, ReadWriteConnectionStringManager>(); - RegisterReadWriteConfigure(services); - } + //if (!UseReadWrite) + //{ + // services.AddTransient, DefaultConnectionStringManager>(); + //} + //else + //{ + // services.AddTransient, ReadWriteConnectionStringManager>(); + // RegisterReadWriteConfigure(services); + //} services.AddInternalShardingCore(); return services; @@ -105,27 +105,27 @@ namespace ShardingCore.DIExtensions /// private void RegisterReadWriteConfigure(IServiceCollection services) { - services.AddSingleton, ReadWriteOptions>(sp => - new ReadWriteOptions( - _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority, - _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable, - _shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum, - _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy)); + //services.AddSingleton, ReadWriteOptions>(sp => + // new ReadWriteOptions( + // _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority, + // _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable, + // _shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum, + // _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy)); - services - .AddSingleton, - ReadWriteShardingConnectionStringResolver>(sp => - { - var readWriteConnectorFactory = sp.GetRequiredService(); - var readConnStrings = _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringConfigure(sp); - var readWriteLoopConnectors = readConnStrings.Select(o => readWriteConnectorFactory.CreateConnector(_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,o.Key,o.Value)); + //services + // .AddSingleton, + // ReadWriteShardingConnectionStringResolver>(sp => + // { + // var readWriteConnectorFactory = sp.GetRequiredService(); + // var readConnStrings = _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringConfigure(sp); + // var readWriteLoopConnectors = readConnStrings.Select(o => readWriteConnectorFactory.CreateConnector(_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,o.Key,o.Value)); - return new ReadWriteShardingConnectionStringResolver( - readWriteLoopConnectors); - }); + // return new ReadWriteShardingConnectionStringResolver( + // readWriteLoopConnectors); + // }); services.TryAddSingleton(); - services.AddSingleton>(); + services.TryAddSingleton>(); } } diff --git a/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs b/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs index 8e97ecf1..a2bdc0ce 100644 --- a/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingDataBaseOrTableBuilder.cs @@ -43,7 +43,7 @@ namespace ShardingCore.DIExtensions } return new ShardingReadWriteSeparationBuilder(_shardingCoreConfigBuilder); } - public ShardingDataBaseOrTableBuilder ReplaceShardingComparer(Func> newShardingComparerFactory) + public ShardingDataBaseOrTableBuilder ReplaceShardingComparer(Func newShardingComparerFactory) { _shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory); return this; diff --git a/src/ShardingCore/DIExtensions/ShardingDataSourceRouteBuilder.cs b/src/ShardingCore/DIExtensions/ShardingDataSourceRouteBuilder.cs index c8ca2ae3..d66c0339 100644 --- a/src/ShardingCore/DIExtensions/ShardingDataSourceRouteBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingDataSourceRouteBuilder.cs @@ -39,7 +39,7 @@ namespace ShardingCore.DIExtensions return new ShardingTableBuilder(_shardingCoreConfigBuilder); } - public ShardingDataSourceRouteBuilder ReplaceShardingComparer(Func> newShardingComparerFactory) + public ShardingDataSourceRouteBuilder ReplaceShardingComparer(Func newShardingComparerFactory) { _shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory); return this; diff --git a/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs b/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs index c6b4b8c6..f0044b78 100644 --- a/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingReadWriteSeparationBuilder.cs @@ -37,7 +37,7 @@ namespace ShardingCore.DIExtensions _shardingCoreConfigBuilder.ShardingConfigOption.UseReadWriteConfiguration(readWriteSeparationConfigure,readStrategyEnum, defaultEnable,defaultPriority, readConnStringGetStrategy); return new ShardingCoreConfigEndBuilder(_shardingCoreConfigBuilder); } - public ShardingReadWriteSeparationBuilder ReplaceShardingComparer(Func> newShardingComparerFactory) + public ShardingReadWriteSeparationBuilder ReplaceShardingComparer(Func newShardingComparerFactory) { _shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory); return this; diff --git a/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs b/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs index 68b77fb4..0b7c0921 100644 --- a/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingTableBuilder.cs @@ -38,7 +38,7 @@ namespace ShardingCore.DIExtensions } return new ShardingReadWriteSeparationBuilder(_shardingCoreConfigBuilder); } - public ShardingTableBuilder ReplaceShardingComparer(Func> newShardingComparerFactory) + public ShardingTableBuilder ReplaceShardingComparer(Func newShardingComparerFactory) { _shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory); return this; diff --git a/src/ShardingCore/DynamicDataSources/DefaultDataSourceInitializer.cs b/src/ShardingCore/DynamicDataSources/DefaultDataSourceInitializer.cs index 74db6e56..40160f63 100644 --- a/src/ShardingCore/DynamicDataSources/DefaultDataSourceInitializer.cs +++ b/src/ShardingCore/DynamicDataSources/DefaultDataSourceInitializer.cs @@ -1,85 +1,76 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using ShardingCore.Bootstrapers; using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.PhysicTables; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Core.VirtualTables; using ShardingCore.Exceptions; using ShardingCore.Extensions; -using ShardingCore.Extensions.InternalExtensions; using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.ParallelTables; using ShardingCore.TableCreator; -using ShardingCore.TableExists; -using ShardingCore.TableExists.Abstractions; +using System; +using System.Collections.Generic; +using System.Threading; namespace ShardingCore.DynamicDataSources { public class DataSourceInitializer : IDataSourceInitializer where TShardingDbContext : DbContext, IShardingDbContext { + private readonly IShardingEntityConfigOptions _entityConfigOptions; private readonly IRouteTailFactory _routeTailFactory; private readonly IVirtualTableManager _virtualTableManager; - private readonly IVirtualDataSource _virtualDataSource; private readonly IEntityMetadataManager _entityMetadataManager; private readonly IShardingTableCreator _tableCreator; private readonly ILogger> _logger; - private readonly IShardingConfigOption _shardingConfigOption; - public DataSourceInitializer(IShardingConfigOption shardingConfigOption, + public DataSourceInitializer( + IShardingEntityConfigOptions entityConfigOptions, IRouteTailFactory routeTailFactory, IVirtualTableManager virtualTableManager, IEntityMetadataManager entityMetadataManager, IShardingTableCreator shardingTableCreator, - IVirtualDataSource virtualDataSource, ILogger> logger) { - _shardingConfigOption = shardingConfigOption; + _entityConfigOptions = entityConfigOptions; _routeTailFactory = routeTailFactory; _virtualTableManager = virtualTableManager; _entityMetadataManager = entityMetadataManager; _tableCreator = shardingTableCreator; - _virtualDataSource = virtualDataSource; _logger = logger; } - public void InitConfigure(string dataSourceName, string connectionString, bool isOnStart) + public void InitConfigure(IVirtualDataSource virtualDataSource, string dataSourceName, string connectionString, bool isOnStart) { using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope()) { - _virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false)); using var context = serviceScope.ServiceProvider.GetService(); - if (_shardingConfigOption.EnsureCreatedWithOutShardingTable||!isOnStart) - EnsureCreated(context, dataSourceName); - var tableEnsureManager = ShardingContainer.GetService>(); - //获取数据库存在的所有的表 - var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? new HashSet(); + if (_entityConfigOptions.EnsureCreatedWithOutShardingTable || !isOnStart) + EnsureCreated(virtualDataSource, context, dataSourceName); + //var tableEnsureManager = ShardingContainer.GetService>(); + ////获取数据库存在的所有的表 + //var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? new HashSet(); + var existTables = new HashSet(); foreach (var entity in context.Model.GetEntityTypes()) { var entityType = entity.ClrType; - if (_virtualDataSource.IsDefault(dataSourceName)) + if (virtualDataSource.IsDefault(dataSourceName)) { if (_entityMetadataManager.IsShardingTable(entityType)) { var virtualTable = _virtualTableManager.GetVirtualTable(entityType); //创建表 - CreateDataTable(dataSourceName, virtualTable, existTables,isOnStart); + CreateDataTable( dataSourceName, virtualTable, existTables, isOnStart); } } else { if (_entityMetadataManager.IsShardingDataSource(entityType)) { - var virtualDataSourceRoute = _virtualDataSource.GetRoute(entityType); + var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType); if (virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName)) { if (_entityMetadataManager.IsShardingTable(entityType)) @@ -91,11 +82,6 @@ namespace ShardingCore.DynamicDataSources } } } - if (isOnStart&&_shardingConfigOption.NeedCreateTable(entityType)) - { - if (!existTables.Contains(entity.GetEntityTypeTableName())) - _tableCreator.CreateTable(dataSourceName, entityType, string.Empty); - } } } } @@ -117,7 +103,7 @@ namespace ShardingCore.DynamicDataSources } catch (Exception e) { - if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) + if (!_entityConfigOptions.IgnoreCreateTableError.GetValueOrDefault()) { _logger.LogWarning(e, $"table :{virtualTable.GetVirtualTableName()}{entityMetadata.TableSeparator}{tail} will created."); @@ -154,15 +140,15 @@ namespace ShardingCore.DynamicDataSources } } - return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault(); + return _entityConfigOptions.CreateShardingTableOnStart.GetValueOrDefault(); } - private void EnsureCreated(DbContext context, string dataSourceName) + private void EnsureCreated(IVirtualDataSource virtualDataSource, DbContext context, string dataSourceName) { if (context is IShardingDbContext shardingDbContext) { var dbContext = shardingDbContext.GetDbContext(dataSourceName, false, _routeTailFactory.Create(string.Empty)); - var isDefault = _virtualDataSource.IsDefault(dataSourceName); + var isDefault = virtualDataSource.IsDefault(dataSourceName); var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); diff --git a/src/ShardingCore/DynamicDataSources/DynamicDataSourceHelper.cs b/src/ShardingCore/DynamicDataSources/DynamicDataSourceHelper.cs index d1baa12e..48002343 100644 --- a/src/ShardingCore/DynamicDataSources/DynamicDataSourceHelper.cs +++ b/src/ShardingCore/DynamicDataSources/DynamicDataSourceHelper.cs @@ -12,11 +12,11 @@ namespace ShardingCore.DynamicDataSources throw new InvalidOperationException($"{nameof(DynamicDataSourceHelper)} create instance"); } - public static void DynamicAppendDataSource(string dataSourceName, string connectionString) where TShardingDbContext:DbContext,IShardingDbContext - { - var defaultDataSourceInitializer = ShardingContainer.GetService>(); - defaultDataSourceInitializer.InitConfigure(dataSourceName, connectionString,false); - } + //public static void DynamicAppendDataSource(string dataSourceName, string connectionString) where TShardingDbContext:DbContext,IShardingDbContext + //{ + // var defaultDataSourceInitializer = ShardingContainer.GetService>(); + // defaultDataSourceInitializer.InitConfigure(dataSourceName, connectionString,false); + //} } } diff --git a/src/ShardingCore/DynamicDataSources/IDataSourceInitializer`1.cs b/src/ShardingCore/DynamicDataSources/IDataSourceInitializer`1.cs index 40586469..8cdd0204 100644 --- a/src/ShardingCore/DynamicDataSources/IDataSourceInitializer`1.cs +++ b/src/ShardingCore/DynamicDataSources/IDataSourceInitializer`1.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.DynamicDataSources @@ -13,9 +14,10 @@ namespace ShardingCore.DynamicDataSources /// /// /// + /// /// /// /// 当前是否是启动时被调用 - void InitConfigure(string dataSourceName, string connectionString,bool isOnStart); + void InitConfigure(IVirtualDataSource virtualDataSource,string dataSourceName, string connectionString,bool isOnStart); } } diff --git a/src/ShardingCore/EFCores/ShardingInternalDbSet.cs b/src/ShardingCore/EFCores/ShardingInternalDbSet.cs index a1056039..6ab37cf2 100644 --- a/src/ShardingCore/EFCores/ShardingInternalDbSet.cs +++ b/src/ShardingCore/EFCores/ShardingInternalDbSet.cs @@ -53,9 +53,7 @@ namespace ShardingCore.EFCores { if (null == _virtualDataSource) { - _virtualDataSource = - (IVirtualDataSource) ShardingContainer.GetService( - typeof(IVirtualDataSource<>).GetGenericType0(_context.GetType())); + _virtualDataSource = _context.GetVirtualDataSource(); } return _virtualDataSource; diff --git a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs new file mode 100644 index 00000000..ceb75c51 --- /dev/null +++ b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Extensions +{ + public static class ShardingDbContextExtension + { + public static bool IsUseReadWriteSeparation(this IShardingDbContext shardingDbContext) + { + return shardingDbContext.GetVirtualDataSource().UseReadWriteSeparation; + } + } +} diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs index 6992dc6f..0ef237fd 100644 --- a/src/ShardingCore/Extensions/ShardingExtension.cs +++ b/src/ShardingCore/Extensions/ShardingExtension.cs @@ -89,7 +89,7 @@ namespace ShardingCore.Extensions return new Dictionary>>(); var entityType = typeof(TEntity); var routeTailFactory = ShardingContainer.GetService(); - var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(shardingDbContext.GetType())); + var virtualDataSource = shardingDbContext.GetVirtualDataSource(); var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType())); var dataSourceNames = new Dictionary>>(); var entitiesArray = entities as TEntity[] ?? entities.ToArray(); @@ -245,7 +245,7 @@ namespace ShardingCore.Extensions public static IDictionary> BulkShardingExpression(this TShardingDbContext shardingDbContext, Expression> where) where TEntity : class where TShardingDbContext : DbContext, IShardingDbContext { - var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(shardingDbContext.GetType())); + var virtualDataSource = shardingDbContext.GetVirtualDataSource(); var routeTailFactory = ShardingContainer.GetService(); var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContext.GetType())); var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType())); diff --git a/src/ShardingCore/Extensions/ShardingReadWriteExtension.cs b/src/ShardingCore/Extensions/ShardingReadWriteExtension.cs index eff8fca8..878a098e 100644 --- a/src/ShardingCore/Extensions/ShardingReadWriteExtension.cs +++ b/src/ShardingCore/Extensions/ShardingReadWriteExtension.cs @@ -85,9 +85,7 @@ namespace ShardingCore.Extensions if (shardingDbContext is ISupportShardingReadWrite shardingReadWrite) { var shardingDbContextType = shardingDbContext.GetType(); - var shardingConfigOption = ShardingContainer.GetRequiredShardingConfigOption(shardingDbContextType); - var useReadWrite=shardingConfigOption?.UseReadWrite ?? false; - if (useReadWrite) + if (shardingDbContext.IsUseReadWriteSeparation()) { var shardingReadWriteManager = ShardingContainer.GetService(); var shardingReadWriteContext = shardingReadWriteManager.GetCurrent(shardingDbContextType); diff --git a/src/ShardingCore/Extensions/VirtualDataSourceExtension.cs b/src/ShardingCore/Extensions/VirtualDataSourceExtension.cs index 1a24aa48..fd6c4fa2 100644 --- a/src/ShardingCore/Extensions/VirtualDataSourceExtension.cs +++ b/src/ShardingCore/Extensions/VirtualDataSourceExtension.cs @@ -38,10 +38,6 @@ namespace ShardingCore.Extensions return virtualDataSource.RouteTo(typeof(TEntity), new ShardingDataSourceRouteConfig(shardingKeyValue:shardingKeyValue))[0]; } - - public static IVirtualDataSourceRoute GetRoute(this IVirtualDataSource virtualDataSource) where TEntity : class - { - return (IVirtualDataSourceRoute)virtualDataSource.GetRoute(typeof(TEntity)); - } + } } diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index ee58509e..98d81fc6 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -13,6 +13,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; namespace ShardingCore.Sharding { @@ -83,6 +84,11 @@ namespace ShardingCore.Sharding return ShardingDbContextExecutor.CreateGenericDbContext(entity); } + public IVirtualDataSource GetVirtualDataSource() + { + return ShardingDbContextExecutor.GetVirtualDataSource(); + } + public override EntityEntry Add(object entity) { diff --git a/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs b/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs index 25eac021..b62da5c1 100644 --- a/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/Abstractions/IConnectionStringManager.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Sharding.Abstractions * @Ver: 1.0 * @Email: 326308290@qq.com */ - public interface IConnectionStringManager where TShardingDbContext:DbContext,IShardingDbContext + public interface IConnectionStringManager { string GetConnectionString(string dataSourceName); } diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs index 784a495f..9ae69540 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using System; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; namespace ShardingCore.Sharding.Abstractions { @@ -29,6 +30,8 @@ namespace ShardingCore.Sharding.Abstractions /// DbContext CreateGenericDbContext(T entity) where T : class; + IVirtualDataSource GetVirtualDataSource(); + } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs index b720f780..206a3206 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Sharding.ShardingDbContextExecutors; namespace ShardingCore.Sharding.Abstractions @@ -52,6 +53,8 @@ namespace ShardingCore.Sharding.Abstractions /// DbContext CreateGenericDbContext(TEntity entity) where TEntity : class; + IVirtualDataSource GetVirtualDataSource(); + Task SaveChangesAsync(bool acceptAllChangesOnSuccess, diff --git a/src/ShardingCore/Sharding/ActualConnectionStringManager.cs b/src/ShardingCore/Sharding/ActualConnectionStringManager.cs index edef802c..7db0352b 100644 --- a/src/ShardingCore/Sharding/ActualConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/ActualConnectionStringManager.cs @@ -19,30 +19,26 @@ namespace ShardingCore.Sharding */ public class ActualConnectionStringManager where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IConnectionStringManager _connectionStringManager; - private readonly IReadWriteOptions _readWriteOptions; private readonly bool _useReadWriteSeparation; private readonly IShardingReadWriteManager _shardingReadWriteManager; private readonly IVirtualDataSource _virtualDataSource; public int ReadWriteSeparationPriority { get; set; } public bool ReadWriteSeparation { get; set; } + public ReadStrategyEnum ReadStrategy { get; set; } + public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; set; } private string _cacheConnectionString; - public ActualConnectionStringManager() + public ActualConnectionStringManager(IVirtualDataSource virtualDataSource) { - _virtualDataSource=ShardingContainer.GetService>(); - _connectionStringManager = ShardingContainer.GetService>(); + _virtualDataSource=virtualDataSource; _shardingReadWriteManager = ShardingContainer.GetService(); - _useReadWriteSeparation = _connectionStringManager is ReadWriteConnectionStringManager; + _useReadWriteSeparation = virtualDataSource.ConnectionStringManager is ReadWriteConnectionStringManager; if (_useReadWriteSeparation) { - _readWriteOptions = ShardingContainer.GetService>(); - if (_readWriteOptions != null) - { - ReadWriteSeparationPriority = _readWriteOptions.ReadWritePriority; - ReadWriteSeparation = _readWriteOptions.ReadWriteSupport; - } + ReadWriteSeparationPriority = virtualDataSource.ConfigurationParams.ReadWriteDefaultPriority.GetValueOrDefault(); + ReadWriteSeparation = virtualDataSource.ConfigurationParams.ReadWriteDefaultEnable.GetValueOrDefault(); + ReadStrategy = virtualDataSource.ConfigurationParams.ReadStrategy.GetValueOrDefault(); + ReadConnStringGetStrategy = virtualDataSource.ConfigurationParams.ReadConnStringGetStrategy.GetValueOrDefault(); } - } //public bool IsUseReadWriteSeparation() //{ @@ -54,7 +50,7 @@ namespace ShardingCore.Sharding return GetWriteConnectionString(dataSourceName); if (!_useReadWriteSeparation) { - return _connectionStringManager.GetConnectionString(dataSourceName); + return _virtualDataSource.ConnectionStringManager.GetConnectionString(dataSourceName); } else { @@ -85,19 +81,19 @@ namespace ShardingCore.Sharding } private string GetReadWriteSeparationConnectString0(string dataSourceName) { - if (_readWriteOptions.ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestFirstTime) + if (ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestFirstTime) { if (_cacheConnectionString == null) - _cacheConnectionString = _connectionStringManager.GetConnectionString(dataSourceName); + _cacheConnectionString = _virtualDataSource.ConnectionStringManager.GetConnectionString(dataSourceName); return _cacheConnectionString; } - else if (_readWriteOptions.ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestEveryTime) + else if (ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestEveryTime) { - return _connectionStringManager.GetConnectionString(dataSourceName); + return _virtualDataSource.ConnectionStringManager.GetConnectionString(dataSourceName); } else { - throw new ShardingCoreInvalidOperationException($"ReadWriteConnectionStringManager:{_readWriteOptions.ReadConnStringGetStrategy}"); + throw new ShardingCoreInvalidOperationException($"ReadWriteConnectionStringManager ReadConnStringGetStrategy:{ReadConnStringGetStrategy}"); } } diff --git a/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs b/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs index 8ceca5bb..15148c5b 100644 --- a/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/DefaultConnectionStringManager.cs @@ -11,17 +11,19 @@ namespace ShardingCore.Sharding * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class DefaultConnectionStringManager : IConnectionStringManager where TShardingDbContext : DbContext, IShardingDbContext + public class DefaultConnectionStringManager : IConnectionStringManager { - private readonly IVirtualDataSource _virtualDataSource; + private readonly IVirtualDataSource _virtualDataSource; - public DefaultConnectionStringManager(IVirtualDataSource virtualDataSource) + public DefaultConnectionStringManager(IVirtualDataSource virtualDataSource) { _virtualDataSource = virtualDataSource; } public string GetConnectionString(string dataSourceName) { - return _virtualDataSource.GetConnectionString(dataSourceName); + if (_virtualDataSource.IsDefault(dataSourceName)) + return _virtualDataSource.DefaultConnectionString; + return _virtualDataSource.GetPhysicDataSource(dataSourceName).ConnectionString; } } } diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorStreamMergeEngineFactory.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorStreamMergeEngineFactory.cs index a9cefa5b..607e0f49 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorStreamMergeEngineFactory.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorStreamMergeEngineFactory.cs @@ -34,14 +34,12 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines private readonly StreamMergeContext _streamMergeContext; private readonly IShardingPageManager _shardingPageManager; private readonly IVirtualTableManager _virtualTableManager; - private readonly IVirtualDataSource _virtualDataSource; private readonly IEntityMetadataManager _entityMetadataManager; private EnumeratorStreamMergeEngineFactory(StreamMergeContext streamMergeContext) { _streamMergeContext = streamMergeContext; _shardingPageManager = ShardingContainer.GetService(); _virtualTableManager = ShardingContainer.GetService>(); - _virtualDataSource = ShardingContainer.GetService>(); _entityMetadataManager = ShardingContainer.GetService>(); } @@ -50,6 +48,10 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines return new EnumeratorStreamMergeEngineFactory(streamMergeContext); } + public IVirtualDataSourceRoute GetRoute(Type entityType) + { + return _streamMergeContext.GetShardingDbContext().GetVirtualDataSource().GetRoute(entityType); + } public IEnumeratorStreamMergeEngine GetMergeEngine() { if (_streamMergeContext.IsRouteNotMatch()) @@ -63,7 +65,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines } //未开启系统分表或者本次查询涉及多张分表 - if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSupportPaginationQuery() && _shardingPageManager.Current != null) + if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSupportPaginationQuery() && _shardingPageManager.Current != null) { //获取虚拟表判断是否启用了分页配置 var shardingEntityType = _streamMergeContext.QueryEntities.FirstOrDefault(o => _entityMetadataManager.IsShardingDataSource(o) || _entityMetadataManager.IsShardingTable(o)); @@ -100,7 +102,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines PaginationSequenceConfig tableSequenceOrderConfig = null; if (isShardingDataSource) { - var virtualDataSourceRoute = _virtualDataSource.GetRoute(shardingEntityType); + var virtualDataSourceRoute = GetRoute(shardingEntityType); if (virtualDataSourceRoute.EnablePagination) { dataSourceSequenceOrderConfig = virtualDataSourceRoute.PaginationMetadata.PaginationConfigs.OrderByDescending(o => o.AppendOrder) @@ -146,7 +148,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines bool tableUseReverse = true; if (isShardingDataSource) { - virtualDataSourceRoute = _virtualDataSource.GetRoute(shardingEntityType); + virtualDataSourceRoute = GetRoute(shardingEntityType); if (virtualDataSourceRoute.EnablePagination) { dataSourceSequenceOrderConfig = orderCount == 1 ? GetPaginationFullMatch(virtualDataSourceRoute.PaginationMetadata.PaginationConfigs, primaryOrder) : GetPaginationPrimaryMatch(virtualDataSourceRoute.PaginationMetadata.PaginationConfigs, primaryOrder); @@ -164,14 +166,14 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines var useSequenceEnumeratorMergeEngine = isShardingDataSource && (dataSourceSequenceOrderConfig != null || (isShardingTable && - !_streamMergeContext.IsCrossDataSource)) || (!isShardingDataSource&&isShardingTable && tableSequenceOrderConfig != null); + !_streamMergeContext.IsCrossDataSource)) || (!isShardingDataSource && isShardingTable && tableSequenceOrderConfig != null); if (useSequenceEnumeratorMergeEngine) { return new SequenceEnumeratorAsyncStreamMergeEngine(_streamMergeContext, dataSourceSequenceOrderConfig, tableSequenceOrderConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc); } var total = _shardingPageManager.Current.RouteQueryResults.Sum(o => o.QueryResult); - if (isShardingDataSource&& virtualDataSourceRoute.EnablePagination) + if (isShardingDataSource && virtualDataSourceRoute.EnablePagination) { dataSourceUseReverse = EntityDataSourceUseReverseShardingPage(virtualDataSourceRoute, total); @@ -181,7 +183,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines tableUseReverse = EntityTableReverseShardingPage(virtualTable, total); } - + //skip过大reserve skip if (dataSourceUseReverse && tableUseReverse) @@ -196,7 +198,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines return null; } - private bool EntityDataSourceUseReverseShardingPage( IVirtualDataSourceRoute virtualDataSourceRoute,long total) + private bool EntityDataSourceUseReverseShardingPage(IVirtualDataSourceRoute virtualDataSourceRoute, long total) { if (virtualDataSourceRoute.PaginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0) { @@ -207,7 +209,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines } return false; } - private bool EntityTableReverseShardingPage( IVirtualTable virtualTable, long total) + private bool EntityTableReverseShardingPage(IVirtualTable virtualTable, long total) { if (virtualTable.PaginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0) { diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteConnectorFactory.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteConnectorFactory.cs index b8598189..3caae2a9 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteConnectorFactory.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteConnectorFactory.cs @@ -10,6 +10,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions { public interface IReadWriteConnectorFactory { - IReadWriteConnector CreateConnector(ReadStrategyEnum strategy, string dataSourceName, IEnumerable connectionStrings) where TShardingDbContext:DbContext,IShardingDbContext; + IReadWriteConnector CreateConnector(ReadStrategyEnum strategy, string dataSourceName, + IEnumerable connectionStrings); } } diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs index a7152737..e6139a98 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs @@ -1,30 +1,30 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.EntityFrameworkCore; -using ShardingCore.Sharding.Abstractions; +//using System; +//using System.Collections.Generic; +//using System.Text; +//using Microsoft.EntityFrameworkCore; +//using ShardingCore.Sharding.Abstractions; -namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/9/7 11:13:52 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public interface IReadWriteOptions - where TShardingDbContext : DbContext, IShardingDbContext - { - /// - /// 默认读写配置优先级 - /// - int ReadWritePriority { get; } - /// - /// 默认是否开启读写分离 - /// - bool ReadWriteSupport { get; } - ReadStrategyEnum ReadStrategy { get; } - ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; } - } -} +//namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: 2021/9/7 11:13:52 +// * @Ver: 1.0 +// * @Email: 326308290@qq.com +// */ +// public interface IReadWriteOptions +// where TShardingDbContext : DbContext, IShardingDbContext +// { +// /// +// /// 默认读写配置优先级 +// /// +// int ReadWritePriority { get; } +// /// +// /// 默认是否开启读写分离 +// /// +// bool ReadWriteSupport { get; } +// ReadStrategyEnum ReadStrategy { get; } +// ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; } +// } +//} diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IShardingConnectionStringResolver.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IShardingConnectionStringResolver.cs index 919d1705..6eae1521 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IShardingConnectionStringResolver.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IShardingConnectionStringResolver.cs @@ -16,9 +16,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions /// /// 读写分离链接字符串解析 /// - /// - public interface IShardingConnectionStringResolver - where TShardingDbContext : DbContext, IShardingDbContext + public interface IShardingConnectionStringResolver { bool ContainsReadWriteDataSourceName(string dataSourceName); string GetConnectionString(string dataSourceName); diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectionStringManager.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectionStringManager.cs index 23354b19..47aa02e4 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectionStringManager.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectionStringManager.cs @@ -16,16 +16,18 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations * @Ver: 1.0 * @Email: 326308290@qq.com */ - public class ReadWriteConnectionStringManager : IConnectionStringManager, IReadWriteAppendConnectionString where TShardingDbContext : DbContext, IShardingDbContext + public class ReadWriteConnectionStringManager: IConnectionStringManager, IReadWriteAppendConnectionString { - private IShardingConnectionStringResolver _shardingConnectionStringResolver; - private readonly IVirtualDataSource _virtualDataSource; + private IShardingConnectionStringResolver _shardingConnectionStringResolver; + private readonly IVirtualDataSource _virtualDataSource; - public ReadWriteConnectionStringManager(IShardingConnectionStringResolver shardingConnectionStringResolver,IVirtualDataSource virtualDataSource) + public ReadWriteConnectionStringManager(IVirtualDataSource virtualDataSource) { - _shardingConnectionStringResolver = shardingConnectionStringResolver; _virtualDataSource = virtualDataSource; + var readWriteConnectorFactory = ShardingContainer.GetService(); + var readWriteConnectors = virtualDataSource.ConfigurationParams.ReadWriteSeparationConfigs.Select(o=> readWriteConnectorFactory.CreateConnector(virtualDataSource.ConfigurationParams.ReadStrategy.GetValueOrDefault(), o.Key,o.Value)); + _shardingConnectionStringResolver = new ReadWriteShardingConnectionStringResolver(readWriteConnectors, virtualDataSource.ConfigurationParams.ReadStrategy.GetValueOrDefault()); } public string GetConnectionString(string dataSourceName) { diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectorFactory.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectorFactory.cs index bb3883f3..38fd96a4 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectorFactory.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteConnectorFactory.cs @@ -12,25 +12,21 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations { public class ReadWriteConnectorFactory: IReadWriteConnectorFactory { - public IReadWriteConnector CreateConnector(ReadStrategyEnum strategy,string dataSourceName, IEnumerable connectionStrings) where TShardingDbContext : DbContext, IShardingDbContext + public IReadWriteConnector CreateConnector(ReadStrategyEnum strategy,string dataSourceName, IEnumerable connectionStrings) { - var readWriteOptions = ShardingContainer.GetService>(); - if (readWriteOptions == null) - throw new ShardingCoreInvalidOperationException( - "cant create read write connector should use read write"); - if (readWriteOptions.ReadStrategy == ReadStrategyEnum.Loop) + if (strategy == ReadStrategyEnum.Loop) { return new ReadWriteLoopConnector(dataSourceName, connectionStrings); } - else if (readWriteOptions.ReadStrategy == ReadStrategyEnum.Random) + else if (strategy == ReadStrategyEnum.Random) { return new ReadWriteRandomConnector(dataSourceName, connectionStrings); } else { throw new ShardingCoreInvalidOperationException( - $"unknown read write strategy:[{readWriteOptions.ReadStrategy}]"); + $"unknown read write strategy:[{strategy}]"); } } } diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs index b791a1f8..03c0e663 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs @@ -1,41 +1,41 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.EntityFrameworkCore; -using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; +//using System; +//using System.Collections.Generic; +//using System.Text; +//using Microsoft.EntityFrameworkCore; +//using ShardingCore.Sharding.Abstractions; +//using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; -namespace ShardingCore.Sharding.ReadWriteConfigurations -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/9/7 11:06:40 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ +//namespace ShardingCore.Sharding.ReadWriteConfigurations +//{ +// /* +// * @Author: xjm +// * @Description: +// * @Date: 2021/9/7 11:06:40 +// * @Ver: 1.0 +// * @Email: 326308290@qq.com +// */ - public class ReadWriteOptions : IReadWriteOptions - where TShardingDbContext : DbContext, IShardingDbContext - { - public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadStrategyEnum readStrategy, ReadConnStringGetStrategyEnum readConnStringGetStrategy) - { - ReadWritePriority = readWritePriority; - ReadWriteSupport = readWriteSupport; - ReadStrategy = readStrategy; - ReadConnStringGetStrategy = readConnStringGetStrategy; - } - public Type ShardingDbContextType => typeof(TShardingDbContext); - /// - /// 默认读写配置优先级 - /// - public int ReadWritePriority { get; } - /// - /// 默认是否开启读写分离 - /// - public bool ReadWriteSupport { get; } +// public class ReadWriteOptions : IReadWriteOptions +// where TShardingDbContext : DbContext, IShardingDbContext +// { +// public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadStrategyEnum readStrategy, ReadConnStringGetStrategyEnum readConnStringGetStrategy) +// { +// ReadWritePriority = readWritePriority; +// ReadWriteSupport = readWriteSupport; +// ReadStrategy = readStrategy; +// ReadConnStringGetStrategy = readConnStringGetStrategy; +// } +// public Type ShardingDbContextType => typeof(TShardingDbContext); +// /// +// /// 默认读写配置优先级 +// /// +// public int ReadWritePriority { get; } +// /// +// /// 默认是否开启读写分离 +// /// +// public bool ReadWriteSupport { get; } - public ReadStrategyEnum ReadStrategy { get; } - public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; } - } -} +// public ReadStrategyEnum ReadStrategy { get; } +// public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; } +// } +//} diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs index 4d3f4bee..ddd032a3 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs @@ -11,15 +11,17 @@ using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; namespace ShardingCore.Sharding.ReadWriteConfigurations { - public class ReadWriteShardingConnectionStringResolver : IShardingConnectionStringResolver where TShardingDbContext : DbContext, IShardingDbContext + public class ReadWriteShardingConnectionStringResolver : IShardingConnectionStringResolver { + private readonly ReadStrategyEnum _readStrategy; + private readonly ConcurrentDictionary _connectors = new ConcurrentDictionary(); - private readonly IReadWriteOptions _readWriteOptions; private readonly IReadWriteConnectorFactory _readWriteConnectorFactory; - public ReadWriteShardingConnectionStringResolver(IEnumerable connectors) + public ReadWriteShardingConnectionStringResolver(IEnumerable connectors, ReadStrategyEnum readStrategy) { + _readStrategy = readStrategy; var enumerator = connectors.GetEnumerator(); while (enumerator.MoveNext()) { @@ -28,7 +30,6 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations _connectors.TryAdd(currentConnector.DataSourceName, currentConnector); } - _readWriteOptions = ShardingContainer.GetService>(); _readWriteConnectorFactory = ShardingContainer.GetService(); } @@ -48,7 +49,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations { if (!_connectors.TryGetValue(dataSourceName, out var connector)) { - connector = _readWriteConnectorFactory.CreateConnector(_readWriteOptions.ReadStrategy, + connector = _readWriteConnectorFactory.CreateConnector(_readStrategy, dataSourceName, new List() { connectionString diff --git a/src/ShardingCore/Sharding/ShardingComparision/Abstractions/IShardingComparer.cs b/src/ShardingCore/Sharding/ShardingComparision/Abstractions/IShardingComparer.cs index 60522302..1da08c0c 100644 --- a/src/ShardingCore/Sharding/ShardingComparision/Abstractions/IShardingComparer.cs +++ b/src/ShardingCore/Sharding/ShardingComparision/Abstractions/IShardingComparer.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; -using ShardingCore.Sharding.Abstractions; /* * @Author: xjm @@ -31,12 +28,4 @@ namespace ShardingCore.Sharding.ShardingComparision.Abstractions /// object CreateComparer(Type comparerType); } - /// - /// 泛型比较器用于依赖注入 - /// - /// - public interface IShardingComparer : IShardingComparer where TShardingDbContext:DbContext,IShardingDbContext - { - - } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/ShardingComparision/CSharpLanguageShardingComparer.cs b/src/ShardingCore/Sharding/ShardingComparision/CSharpLanguageShardingComparer.cs index 4c1e37b5..b0eacf27 100644 --- a/src/ShardingCore/Sharding/ShardingComparision/CSharpLanguageShardingComparer.cs +++ b/src/ShardingCore/Sharding/ShardingComparision/CSharpLanguageShardingComparer.cs @@ -15,9 +15,9 @@ namespace ShardingCore.Sharding.ShardingComparision * @Date: Sunday, 31 October 2021 15:39:46 * @Email: 326308290@qq.com */ - public class CSharpLanguageShardingComparer : IShardingComparer where TShardingDbContext : DbContext, IShardingDbContext + public class CSharpLanguageShardingComparer : IShardingComparer { - private readonly ConcurrentDictionary _comparers = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _comparers = new (); public virtual int Compare(IComparable x, IComparable y, bool asc) { if (x is Guid xg && y is Guid yg) diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs index e0bd3311..d301c416 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs @@ -61,13 +61,13 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors public ShardingDbContextExecutor(DbContext shardingDbContext) { _shardingDbContext = shardingDbContext; - _virtualDataSource = ShardingContainer.GetService>(); + _virtualDataSource = ShardingContainer.GetRequiredVirtualDataSource(); _virtualTableManager = ShardingContainer.GetService>(); _shardingDbContextFactory = ShardingContainer.GetService>(); _shardingDbContextOptionsBuilderConfig = ShardingContainer.GetService>(); _entityMetadataManager = ShardingContainer.GetService>(); _routeTailFactory = ShardingContainer.GetService(); - _actualConnectionStringManager = new ActualConnectionStringManager(); + _actualConnectionStringManager = new ActualConnectionStringManager(_virtualDataSource); } #region create db context @@ -116,6 +116,11 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors return CreateDbContext(false, dataSourceName, _routeTailFactory.Create(tail)); } + public IVirtualDataSource GetVirtualDataSource() + { + return _virtualDataSource; + } + private string GetDataSourceName(TEntity entity) where TEntity : class { if (!_entityMetadataManager.IsShardingDataSource(entity.GetType())) diff --git a/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfigure.cs b/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfigure.cs new file mode 100644 index 00000000..01243a0b --- /dev/null +++ b/src/ShardingCore/Sharding/ShardingDbContextOptionsBuilderConfigure.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.Sharding +{ + public class ShardingDbContextOptionsBuilderConfigure where TShardingDbContext : DbContext, IShardingDbContext + { + public ShardingDbContextOptionsBuilderConfigure(Action sameConnectionDbContextOptionsCreator, Action defaultQueryDbContextOptionsCreator) + { + SameConnectionDbContextOptionsCreator = sameConnectionDbContextOptionsCreator; + DefaultQueryDbContextOptionsCreator = defaultQueryDbContextOptionsCreator; + } + public Action SameConnectionDbContextOptionsCreator { get; } + public Action DefaultQueryDbContextOptionsCreator { get; } + + public DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder) + { + SameConnectionDbContextOptionsCreator(dbConnection, dbContextOptionsBuilder); + dbContextOptionsBuilder.UseInnerDbContextSharding(); + return dbContextOptionsBuilder; + } + + public DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder) + { + DefaultQueryDbContextOptionsCreator(connectionString, dbContextOptionsBuilder); + dbContextOptionsBuilder.UseInnerDbContextSharding(); + return dbContextOptionsBuilder; + } + } +} diff --git a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs index 5530671d..ecffd0ee 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs @@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Extensions; @@ -24,7 +25,7 @@ namespace ShardingCore.Sharding.ShardingExecutors private readonly Expression _queryExpression; private readonly IEntityMetadataManager _entityMetadataManager; private readonly Type _shardingDbContextType; - private readonly IShardingConfigOption _shardingConfigOption; + private readonly IShardingEntityConfigOptions _entityConfigOptions; private QueryCompilerExecutor _queryCompilerExecutor; private bool? hasQueryCompilerExecutor; private bool? _isNoTracking; @@ -39,10 +40,9 @@ namespace ShardingCore.Sharding.ShardingExecutors _queryExpression = queryExpression; _entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(_shardingDbContextType)); - _shardingConfigOption = ShardingContainer.GetRequiredShardingConfigOption(_shardingDbContextType); + _entityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(_shardingDbContextType); //原生对象的原生查询如果是读写分离就需要启用并行查询 - _isParallelQuery = - _shardingConfigOption.UseReadWrite && _shardingDbContext.CurrentIsReadWriteSeparation(); + _isParallelQuery = shardingDbContext.IsUseReadWriteSeparation() && _shardingDbContext.CurrentIsReadWriteSeparation(); } public static QueryCompilerContext Create(IShardingDbContext shardingDbContext, Expression queryExpression) @@ -103,8 +103,7 @@ namespace ShardingCore.Sharding.ShardingExecutors hasQueryCompilerExecutor = _queryEntities.All(o => !_entityMetadataManager.IsSharding(o)); if (hasQueryCompilerExecutor.Value) { - var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService( - typeof(IVirtualDataSource<>).GetGenericType0(_shardingDbContextType)); + var virtualDataSource = _shardingDbContext.GetVirtualDataSource(); var routeTailFactory = ShardingContainer.GetService(); var dbContext = _shardingDbContext.GetDbContext(virtualDataSource.DefaultDataSourceName, IsParallelQuery(), routeTailFactory.Create(string.Empty)); _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, _queryExpression); diff --git a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs index 2c8a8376..30eb1346 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs @@ -43,7 +43,7 @@ namespace ShardingCore.Sharding.ShardingExecutors var dataSourceRouteRuleEngineFactory = (IDataSourceRouteRuleEngineFactory)ShardingContainer.GetService(typeof(IDataSourceRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType())); var tableRouteRuleEngineFactory = (ITableRouteRuleEngineFactory)ShardingContainer.GetService(typeof(ITableRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType())); var queryCombineResult = queryableCombine.Combine(queryCompilerContext); - var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable()); + var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(),shardingDbContext); var tableRouteResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable()); var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray(); var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult, diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index 6e3f646d..1a3c144b 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -17,6 +17,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Exceptions; @@ -65,11 +66,10 @@ namespace ShardingCore.Sharding public bool IsCrossTable { get; } private readonly ITrackerManager _trackerManager; - private readonly IShardingConfigOption _shardingConfigOption; + private readonly IShardingEntityConfigOptions _shardingEntityConfigOptions; private readonly ConcurrentDictionary _parallelDbContexts; - private readonly IShardingComparer _shardingComparer; public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext, IRouteTailFactory routeTailFactory) @@ -94,9 +94,8 @@ namespace ShardingCore.Sharding _trackerManager = (ITrackerManager)ShardingContainer.GetService( typeof(ITrackerManager<>).GetGenericType0(mergeQueryCompilerContext.GetShardingDbContextType())); - _shardingComparer = (IShardingComparer)ShardingContainer.GetService(typeof(IShardingComparer<>).GetGenericType0(_shardingDbContext.GetType())); - _shardingConfigOption = ShardingContainer.GetRequiredShardingConfigOption(mergeQueryCompilerContext.GetShardingDbContextType()); + _shardingEntityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(mergeQueryCompilerContext.GetShardingDbContextType()); _parallelDbContexts = new ConcurrentDictionary(); } public void ReSetOrders(IEnumerable orders) @@ -197,7 +196,7 @@ namespace ShardingCore.Sharding public int GetMaxQueryConnectionsLimit() { - return _shardingConfigOption.MaxQueryConnectionsLimit; + return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit; } public ConnectionModeEnum GetConnectionMode(int sqlCount) { @@ -206,13 +205,13 @@ namespace ShardingCore.Sharding private ConnectionModeEnum CalcConnectionMode(int sqlCount) { - switch (_shardingConfigOption.ConnectionMode) + switch (_shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode) { case ConnectionModeEnum.MEMORY_STRICTLY: - case ConnectionModeEnum.CONNECTION_STRICTLY: return _shardingConfigOption.ConnectionMode; + case ConnectionModeEnum.CONNECTION_STRICTLY: return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode; default: { - return _shardingConfigOption.MaxQueryConnectionsLimit < sqlCount + return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit < sqlCount ? ConnectionModeEnum.CONNECTION_STRICTLY : ConnectionModeEnum.MEMORY_STRICTLY; ; } @@ -224,7 +223,7 @@ namespace ShardingCore.Sharding /// private bool IsUseReadWriteSeparation() { - return _shardingConfigOption.UseReadWrite&&_shardingDbContext.CurrentIsReadWriteSeparation(); + return _shardingDbContext.IsUseReadWriteSeparation()&&_shardingDbContext.CurrentIsReadWriteSeparation(); } /// @@ -253,7 +252,7 @@ namespace ShardingCore.Sharding public IShardingComparer GetShardingComparer() { - return _shardingComparer; + return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ShardingComparer; } public TResult PreperExecute(Func emptyFunc) @@ -296,7 +295,7 @@ namespace ShardingCore.Sharding private bool ThrowIfQueryRouteNotMatch() { - return _shardingConfigOption.ThrowIfQueryRouteNotMatch; + return _shardingEntityConfigOptions.ThrowIfQueryRouteNotMatch; } public void Dispose() { diff --git a/src/ShardingCore/ShardingConfigOption.cs b/src/ShardingCore/ShardingConfigOption.cs index 73ab54e3..0fe4cc6e 100644 --- a/src/ShardingCore/ShardingConfigOption.cs +++ b/src/ShardingCore/ShardingConfigOption.cs @@ -35,14 +35,8 @@ namespace ShardingCore public readonly ISet _parallelTables = new HashSet(); public Action SameConnectionConfigure { get; private set; } - public Action DefaultQueryConfigure { get; private set; } public Func> DataSourcesConfigure { get; private set; } - - public void UseShardingQuery(Action queryConfigure) - { - DefaultQueryConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure)); - } public void UseShardingTransaction(Action transactionConfigure) { SameConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure)); @@ -53,13 +47,13 @@ namespace ShardingCore DataSourcesConfigure = dataSourcesConfigure ?? throw new ArgumentNullException(nameof(dataSourcesConfigure)); } - public Func> ReplaceShardingComparerFactory { get; private set; } = sp => new CSharpLanguageShardingComparer(); + public Func ReplaceShardingComparerFactory { get; private set; } = sp => new CSharpLanguageShardingComparer(); /// /// 替换默认的比较器 /// /// /// - public void ReplaceShardingComparer(Func> newShardingComparerFactory) + public void ReplaceShardingComparer(Func newShardingComparerFactory) { ReplaceShardingComparerFactory=newShardingComparerFactory ?? throw new ArgumentNullException(nameof(newShardingComparerFactory)); } @@ -79,8 +73,8 @@ namespace ShardingCore //public void UseShardingOptionsBuilder(Action sameConnectionConfigure, Action defaultQueryConfigure = null) //{ - // SameConnectionConfigure = sameConnectionConfigure ?? throw new ArgumentNullException(nameof(sameConnectionConfigure)); - // DefaultQueryConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure)); + // ConnectionConfigure = sameConnectionConfigure ?? throw new ArgumentNullException(nameof(sameConnectionConfigure)); + // ConnectionStringConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure)); //} public bool UseReadWrite => ReadConnStringConfigure != null; diff --git a/src/ShardingCore/ShardingContainer.cs b/src/ShardingCore/ShardingContainer.cs index 095257a6..7ae8dffd 100644 --- a/src/ShardingCore/ShardingContainer.cs +++ b/src/ShardingCore/ShardingContainer.cs @@ -7,6 +7,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using ShardingCore.Core.ShardingConfigurations; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; namespace ShardingCore { @@ -108,14 +111,42 @@ namespace ShardingCore return Activator.CreateInstance(serviceType, @params); } - public static IShardingConfigOption GetRequiredShardingConfigOption() + //public static IShardingConfigOption GetRequiredShardingConfigOption() + // where TShardingDbContext : DbContext, IShardingDbContext + //{ + // return (IShardingConfigOption)GetRequiredShardingConfigOption(typeof(TShardingDbContext)); + //} + //public static IShardingConfigOption GetRequiredShardingConfigOption(Type shardingDbContextType) + //{ + // return (IShardingConfigOption)ServiceProvider.GetService(typeof(IShardingConfigOption<>).GetGenericType0(shardingDbContextType)); + //} + public static IShardingEntityConfigOptions GetRequiredShardingEntityConfigOption() where TShardingDbContext : DbContext, IShardingDbContext { - return (IShardingConfigOption)GetRequiredShardingConfigOption(typeof(TShardingDbContext)); + return (IShardingEntityConfigOptions)GetRequiredShardingEntityConfigOption(typeof(TShardingDbContext)); } - public static IShardingConfigOption GetRequiredShardingConfigOption(Type shardingDbContextType) + public static IShardingEntityConfigOptions GetRequiredShardingEntityConfigOption(Type shardingDbContextType) { - return (IShardingConfigOption)ServiceProvider.GetService(typeof(IShardingConfigOption<>).GetGenericType0(shardingDbContextType)); + return (IShardingEntityConfigOptions)ServiceProvider.GetService(typeof(IShardingEntityConfigOptions<>).GetGenericType0(shardingDbContextType)); + } + + public static IVirtualDataSourceManager GetRequiredVirtualDataSourceManager() + where TShardingDbContext : DbContext, IShardingDbContext + { + return (IVirtualDataSourceManager)GetRequiredVirtualDataSourceManager(typeof(TShardingDbContext)); + } + public static IVirtualDataSourceManager GetRequiredVirtualDataSourceManager(Type shardingDbContextType) + { + return (IVirtualDataSourceManager)ServiceProvider.GetService(typeof(IVirtualDataSourceManager<>).GetGenericType0(shardingDbContextType)); + } + public static IVirtualDataSource GetRequiredVirtualDataSource() + where TShardingDbContext : DbContext, IShardingDbContext + { + return GetRequiredVirtualDataSourceManager().GetVirtualDataSource(); + } + public static IVirtualDataSource GetRequiredVirtualDataSource(Type shardingDbContextType) + { + return GetRequiredVirtualDataSourceManager(shardingDbContextType).GetVirtualDataSource(); } } } \ No newline at end of file diff --git a/src/ShardingCore/TableCreator/ShardingTableCreator.cs b/src/ShardingCore/TableCreator/ShardingTableCreator.cs index 3844b10f..1d3e4a80 100644 --- a/src/ShardingCore/TableCreator/ShardingTableCreator.cs +++ b/src/ShardingCore/TableCreator/ShardingTableCreator.cs @@ -13,6 +13,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using ShardingCore.Core.ShardingConfigurations; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; @@ -28,14 +29,14 @@ namespace ShardingCore.TableCreator { private readonly ILogger> _logger; private readonly IServiceProvider _serviceProvider; - private readonly IShardingConfigOption _shardingConfigOption; + private readonly IShardingEntityConfigOptions _entityConfigOptions; private readonly IRouteTailFactory _routeTailFactory; - public ShardingTableCreator(ILogger> logger, IServiceProvider serviceProvider, IShardingConfigOption shardingConfigOption, IRouteTailFactory routeTailFactory) + public ShardingTableCreator(ILogger> logger, IServiceProvider serviceProvider, IShardingEntityConfigOptions entityConfigOptions, IRouteTailFactory routeTailFactory) { _logger = logger; _serviceProvider = serviceProvider; - _shardingConfigOption = shardingConfigOption; + _entityConfigOptions = entityConfigOptions; _routeTailFactory = routeTailFactory; } @@ -77,7 +78,7 @@ namespace ShardingCore.TableCreator } catch (Exception ex) { - if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) + if (!_entityConfigOptions.IgnoreCreateTableError.GetValueOrDefault()) { _logger.LogWarning(ex, $"create table error entity name:[{shardingEntityType.Name}]."); diff --git a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs index 159cebc6..8c2c8aea 100644 --- a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.PhysicTables; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; @@ -64,38 +65,42 @@ namespace ShardingCore.VirtualRoutes.Abstractions return Task.CompletedTask; } var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType)); - var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(EntityMetadata.ShardingDbContextType)); var tableCreator = (IShardingTableCreator)ShardingContainer.GetService(typeof(IShardingTableCreator<>).GetGenericType0(EntityMetadata.ShardingDbContextType)); + var virtualDataSourceManager = (IVirtualDataSourceManager)ShardingContainer.GetService(typeof(IVirtualDataSourceManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType)); + var allVirtualDataSources = virtualDataSourceManager.GetAllVirtualDataSources(); var now = DateTime.Now.AddMinutes(IncrementMinutes); var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now); - ISet dataSources = new HashSet(); - if (entityMetadataManager.IsShardingDataSource(typeof(TEntity))) + foreach (var virtualDataSource in allVirtualDataSources) { - var virtualDataSourceRoute = virtualDataSource.GetRoute(typeof(TEntity)); - foreach (var dataSourceName in virtualDataSourceRoute.GetAllDataSourceNames()) + ISet dataSources = new HashSet(); + if (entityMetadataManager.IsShardingDataSource(typeof(TEntity))) { - dataSources.Add(dataSourceName); + var virtualDataSourceRoute = virtualDataSource.GetRoute(typeof(TEntity)); + foreach (var dataSourceName in virtualDataSourceRoute.GetAllDataSourceNames()) + { + dataSources.Add(dataSourceName); + } } - } - else - { - dataSources.Add(virtualDataSource.DefaultDataSourceName); - } - _logger.LogInformation($"auto create table data source names:[{string.Join(",", dataSources)}]"); - foreach (var dataSource in dataSources) - { - try + else { - _logger.LogInformation($"begin table tail:[{tail}],entity:[{typeof(TEntity).Name}]"); - tableCreator.CreateTable(dataSource, typeof(TEntity), tail); - _logger.LogInformation($"succeed table tail:[{tail}],entity:[{typeof(TEntity).Name}]"); + dataSources.Add(virtualDataSource.DefaultDataSourceName); } - catch (Exception e) + _logger.LogInformation($"auto create table data source names:[{string.Join(",", dataSources)}]"); + foreach (var dataSource in dataSources) { - //ignore - _logger.LogInformation($"warning table tail:[{tail}],entity:[{typeof(TEntity).Name}]"); - if (DoLogError) - _logger.LogError(e, $"{dataSource} {typeof(TEntity).Name}'s create table error "); + try + { + _logger.LogInformation($"begin table tail:[{tail}],entity:[{typeof(TEntity).Name}]"); + tableCreator.CreateTable(dataSource, typeof(TEntity), tail); + _logger.LogInformation($"succeed table tail:[{tail}],entity:[{typeof(TEntity).Name}]"); + } + catch (Exception e) + { + //ignore + _logger.LogInformation($"warning table tail:[{tail}],entity:[{typeof(TEntity).Name}]"); + if (DoLogError) + _logger.LogError(e, $"{dataSource} {typeof(TEntity).Name}'s create table error "); + } } } virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail));