diff --git a/nuget-publish.bat b/nuget-publish.bat index 1b036f68..ab51070f 100644 --- a/nuget-publish.bat +++ b/nuget-publish.bat @@ -1,9 +1,9 @@ :start ::定义版本 -set EFCORE2=2.3.1.75 -set EFCORE3=3.3.1.75 -set EFCORE5=5.3.1.75 -set EFCORE6=6.3.1.75 +set EFCORE2=2.3.1.76 +set EFCORE3=3.3.1.76 +set EFCORE5=5.3.1.76 +set EFCORE6=6.3.1.76 ::删除所有bin与obj下的文件 @echo off diff --git a/samples/Sample.SqlServerShardingAll/DbContextHelper.cs b/samples/Sample.SqlServerShardingAll/DbContextHelper.cs new file mode 100644 index 00000000..816beb9e --- /dev/null +++ b/samples/Sample.SqlServerShardingAll/DbContextHelper.cs @@ -0,0 +1,152 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using ShardingCore; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.PhysicTables; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; +using ShardingCore.Core.VirtualDatabase.VirtualTables; +using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; +using ShardingCore.Core.VirtualTables; +using ShardingCore.Exceptions; +using ShardingCore.Extensions; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.TableCreator; + +namespace Sample.SqlServerShardingAll +{ + public class DbContextHelper + { + public static void EnsureSubDbCreatedAndCreateSubTables(string dataSourceName, string connectionString, Type entityType, int sum4SubTable) + { + var _entityMetadataManager = ShardingContainer.GetService>(); + var _virtualDataSource = ShardingContainer.GetService>(); + var _virtualTableManager = ShardingContainer.GetService>(); + var _tableCreator = ShardingContainer.GetService>(); + + using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope()) + { + _virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false)); + var virtualDataSourceRoute = _virtualDataSource.GetRoute(entityType); + virtualDataSourceRoute.AddDataSourceName(dataSourceName); + + using var context = (DbContext)serviceScope.ServiceProvider.GetService(typeof(MyDbContext)); + EnsureCreated(context, dataSourceName); + foreach (var entity in context.Model.GetEntityTypes()) + { + if (entity.ClrType != entityType) + { + continue; + } + if (_entityMetadataManager.IsShardingTable(entityType)) + { + var virtualTable = _virtualTableManager.GetVirtualTable(entityType); + //创建表 + CreateDataTable(dataSourceName, virtualTable, sum4SubTable); + } + else + { + _tableCreator.CreateTable(dataSourceName, entityType, string.Empty); + } + } + } + } + private static void CreateDataTable(string dataSourceName, IVirtualTable virtualTable, int sum4SubTable) + { + var _tableCreator = ShardingContainer.GetService>(); + var entityMetadata = virtualTable.EntityMetadata; + int currentCount = 0; + foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails()) + { + if (currentCount >= sum4SubTable) + { + break; + } + + if (NeedCreateTable(entityMetadata)) + { + try + { + //添加物理表 + virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); + _tableCreator.CreateTable(dataSourceName, entityMetadata.EntityType, tail); + } + catch (Exception ex) + { + //if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault()) + //{ + // _logger.LogWarning(ex, + // $"table :{virtualTable.GetVirtualTableName()}{entityMetadata.TableSeparator}{tail} will created."); + //} + //TODO: 记录异常日志 + System.Diagnostics.Trace.TraceError($"DbContextHelper-->CreateDataTable ERROR: {ex}"); + } + } + else + { + //添加物理表 + virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail)); + } + currentCount++; + } + } + + + private static bool NeedCreateTable(EntityMetadata entityMetadata) + { + if (entityMetadata.AutoCreateTable.HasValue) + { + if (entityMetadata.AutoCreateTable.Value) + return entityMetadata.AutoCreateTable.Value; + else + { + if (entityMetadata.AutoCreateDataSourceTable.HasValue) + return entityMetadata.AutoCreateDataSourceTable.Value; + } + } + if (entityMetadata.AutoCreateDataSourceTable.HasValue) + { + if (entityMetadata.AutoCreateDataSourceTable.Value) + return entityMetadata.AutoCreateDataSourceTable.Value; + else + { + if (entityMetadata.AutoCreateTable.HasValue) + return entityMetadata.AutoCreateTable.Value; + } + } + + //return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault(); + return true; + } + + private static void EnsureCreated(DbContext context, string dataSourceName) + { + var _routeTailFactory = ShardingContainer.GetService(); + + if (context is IShardingDbContext shardingDbContext) + { + var dbContext = shardingDbContext.GetDbContext(dataSourceName, false, _routeTailFactory.Create(string.Empty)); + + var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); + + var acquire = System.Threading.Monitor.TryEnter(modelCacheSyncObject, TimeSpan.FromSeconds(3)); + if (!acquire) + { + throw new ShardingCoreException("cant get modelCacheSyncObject lock"); + } + + try + { + dbContext.RemoveDbContextRelationModelThatIsShardingTable(); + dbContext.Database.EnsureCreated(); + dbContext.RemoveModelCache(); + } + finally + { + System.Threading.Monitor.Exit(modelCacheSyncObject); + } + } + } + } +} diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs index 4a525cdb..6c4c6080 100644 --- a/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs @@ -96,6 +96,7 @@ namespace ShardingCore.DIExtensions new ReadWriteOptions( _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority, _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable, + _shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum, _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy)); bool isLoop = false; var readStrategyEnum = _shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum; diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs index 1674a1d7..a7152737 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs @@ -24,6 +24,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions /// 默认是否开启读写分离 /// bool ReadWriteSupport { get; } + ReadStrategyEnum ReadStrategy { get; } ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; } } } diff --git a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs index 60016b9b..b791a1f8 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs @@ -18,10 +18,11 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations public class ReadWriteOptions : IReadWriteOptions where TShardingDbContext : DbContext, IShardingDbContext { - public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadConnStringGetStrategyEnum readConnStringGetStrategy) + public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadStrategyEnum readStrategy, ReadConnStringGetStrategyEnum readConnStringGetStrategy) { ReadWritePriority = readWritePriority; ReadWriteSupport = readWriteSupport; + ReadStrategy = readStrategy; ReadConnStringGetStrategy = readConnStringGetStrategy; } public Type ShardingDbContextType => typeof(TShardingDbContext); @@ -33,6 +34,8 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations /// 默认是否开启读写分离 /// public bool ReadWriteSupport { 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 97a5925b..4d88ac65 100644 --- a/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs +++ b/src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs @@ -16,6 +16,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations private readonly ConcurrentDictionary _connectors = new ConcurrentDictionary(); + private readonly IReadWriteOptions _readWriteOptions; public ReadWriteShardingConnectionStringResolver(IEnumerable connectors) { var enumerator = connectors.GetEnumerator(); @@ -26,6 +27,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations _connectors.TryAdd(currentConnector.DataSourceName, currentConnector); } + _readWriteOptions = ShardingContainer.GetService>(); } public bool ContainsReadWriteDataSourceName(string dataSourceName) @@ -43,8 +45,24 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations public bool AddConnectionString(string dataSourceName, string connectionString) { if (!_connectors.TryGetValue(dataSourceName, out var connector)) - throw new ShardingCoreInvalidOperationException($"read write connector not found, data source name:[{dataSourceName}]"); - return connector.AddConnectionString(connectionString); + { + if (_readWriteOptions.ReadStrategy == ReadStrategyEnum.Loop) + { + connector= new ReadWriteLoopConnector(dataSourceName, new List { connectionString }); + } + else if (_readWriteOptions.ReadStrategy == ReadStrategyEnum.Random) + { + connector= new ReadWriteLoopConnector(dataSourceName, new List { connectionString }); + } + + throw new ShardingCoreInvalidOperationException( + $"unknown read write strategy:[{_readWriteOptions.ReadStrategy}]"); + + } + else + { + return connector.AddConnectionString(connectionString); + } } } } diff --git a/test/ShardingCore.Test/ShardingTest.cs b/test/ShardingCore.Test/ShardingTest.cs index 20693782..b31bc039 100644 --- a/test/ShardingCore.Test/ShardingTest.cs +++ b/test/ShardingCore.Test/ShardingTest.cs @@ -51,12 +51,13 @@ namespace ShardingCore.Test private readonly IShardingTableCreator _shardingTableCreator; private readonly IShardingReadWriteManager _shardingReadWriteManager; private readonly IRouteTailFactory _routeTailFactory; + private readonly IShardingConnectionStringResolver _shardingConnectionStringResolver; public ShardingTest(ShardingDefaultDbContext virtualDbContext, IShardingRouteManager shardingRouteManager, IConfiguration configuration, IEntityMetadataManager entityMetadataManager, IShardingComparer shardingComparer, IVirtualDataSource virtualDataSource, IVirtualTableManager virtualTableManager, - IShardingTableCreator shardingTableCreator, IShardingReadWriteManager shardingReadWriteManager,IRouteTailFactory routeTailFactory) + IShardingTableCreator shardingTableCreator, IShardingReadWriteManager shardingReadWriteManager,IRouteTailFactory routeTailFactory,IShardingConnectionStringResolver shardingConnectionStringResolver) { _virtualDbContext = virtualDbContext; _shardingRouteManager = shardingRouteManager; @@ -69,6 +70,7 @@ namespace ShardingCore.Test _shardingTableCreator = shardingTableCreator; _shardingReadWriteManager = shardingReadWriteManager; _routeTailFactory = routeTailFactory; + _shardingConnectionStringResolver = shardingConnectionStringResolver; //var dataSource = ShardingContainer.GetService>(); //dataSource.AddPhysicDataSource(new DefaultPhysicDataSource("E", "XXXXX", false)); @@ -222,6 +224,9 @@ namespace ShardingCore.Test { new ParallelTableComparerType(typeof(SysUserSalary)),new ParallelTableComparerType(typeof(SysUserMod)), }); Assert.Equal(x1x1, x2x2); Assert.Equal(x1x1.GetHashCode(), x2x2.GetHashCode()); + var succeedAddConnectionString = _shardingConnectionStringResolver.AddConnectionString("A", "Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;"); + Assert.True(succeedAddConnectionString); + } public class SequenceClass