Skip to content

Commit fe72758

Browse files
committed
修复动态添加读写分离从库bug
1 parent af905a7 commit fe72758

File tree

7 files changed

+188
-8
lines changed

7 files changed

+188
-8
lines changed

nuget-publish.bat

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
:start
22
::定义版本
3-
set EFCORE2=2.3.1.75
4-
set EFCORE3=3.3.1.75
5-
set EFCORE5=5.3.1.75
6-
set EFCORE6=6.3.1.75
3+
set EFCORE2=2.3.1.76
4+
set EFCORE3=3.3.1.76
5+
set EFCORE5=5.3.1.76
6+
set EFCORE6=6.3.1.76
77

88
::删除所有bin与obj下的文件
99
@echo off
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
using System;
2+
using Microsoft.EntityFrameworkCore;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using ShardingCore;
5+
using ShardingCore.Core.EntityMetadatas;
6+
using ShardingCore.Core.PhysicTables;
7+
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
8+
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
9+
using ShardingCore.Core.VirtualDatabase.VirtualTables;
10+
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
11+
using ShardingCore.Core.VirtualTables;
12+
using ShardingCore.Exceptions;
13+
using ShardingCore.Extensions;
14+
using ShardingCore.Sharding.Abstractions;
15+
using ShardingCore.TableCreator;
16+
17+
namespace Sample.SqlServerShardingAll
18+
{
19+
public class DbContextHelper
20+
{
21+
public static void EnsureSubDbCreatedAndCreateSubTables(string dataSourceName, string connectionString, Type entityType, int sum4SubTable)
22+
{
23+
var _entityMetadataManager = ShardingContainer.GetService<IEntityMetadataManager<MyDbContext>>();
24+
var _virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<MyDbContext>>();
25+
var _virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<MyDbContext>>();
26+
var _tableCreator = ShardingContainer.GetService<IShardingTableCreator<MyDbContext>>();
27+
28+
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
29+
{
30+
_virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false));
31+
var virtualDataSourceRoute = _virtualDataSource.GetRoute(entityType);
32+
virtualDataSourceRoute.AddDataSourceName(dataSourceName);
33+
34+
using var context = (DbContext)serviceScope.ServiceProvider.GetService(typeof(MyDbContext));
35+
EnsureCreated(context, dataSourceName);
36+
foreach (var entity in context.Model.GetEntityTypes())
37+
{
38+
if (entity.ClrType != entityType)
39+
{
40+
continue;
41+
}
42+
if (_entityMetadataManager.IsShardingTable(entityType))
43+
{
44+
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
45+
//创建表
46+
CreateDataTable(dataSourceName, virtualTable, sum4SubTable);
47+
}
48+
else
49+
{
50+
_tableCreator.CreateTable(dataSourceName, entityType, string.Empty);
51+
}
52+
}
53+
}
54+
}
55+
private static void CreateDataTable(string dataSourceName, IVirtualTable virtualTable, int sum4SubTable)
56+
{
57+
var _tableCreator = ShardingContainer.GetService<IShardingTableCreator<MyDbContext>>();
58+
var entityMetadata = virtualTable.EntityMetadata;
59+
int currentCount = 0;
60+
foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails())
61+
{
62+
if (currentCount >= sum4SubTable)
63+
{
64+
break;
65+
}
66+
67+
if (NeedCreateTable(entityMetadata))
68+
{
69+
try
70+
{
71+
//添加物理表
72+
virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail));
73+
_tableCreator.CreateTable(dataSourceName, entityMetadata.EntityType, tail);
74+
}
75+
catch (Exception ex)
76+
{
77+
//if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault())
78+
//{
79+
// _logger.LogWarning(ex,
80+
// $"table :{virtualTable.GetVirtualTableName()}{entityMetadata.TableSeparator}{tail} will created.");
81+
//}
82+
//TODO: 记录异常日志
83+
System.Diagnostics.Trace.TraceError($"DbContextHelper-->CreateDataTable ERROR: {ex}");
84+
}
85+
}
86+
else
87+
{
88+
//添加物理表
89+
virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail));
90+
}
91+
currentCount++;
92+
}
93+
}
94+
95+
96+
private static bool NeedCreateTable(EntityMetadata entityMetadata)
97+
{
98+
if (entityMetadata.AutoCreateTable.HasValue)
99+
{
100+
if (entityMetadata.AutoCreateTable.Value)
101+
return entityMetadata.AutoCreateTable.Value;
102+
else
103+
{
104+
if (entityMetadata.AutoCreateDataSourceTable.HasValue)
105+
return entityMetadata.AutoCreateDataSourceTable.Value;
106+
}
107+
}
108+
if (entityMetadata.AutoCreateDataSourceTable.HasValue)
109+
{
110+
if (entityMetadata.AutoCreateDataSourceTable.Value)
111+
return entityMetadata.AutoCreateDataSourceTable.Value;
112+
else
113+
{
114+
if (entityMetadata.AutoCreateTable.HasValue)
115+
return entityMetadata.AutoCreateTable.Value;
116+
}
117+
}
118+
119+
//return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault();
120+
return true;
121+
}
122+
123+
private static void EnsureCreated(DbContext context, string dataSourceName)
124+
{
125+
var _routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
126+
127+
if (context is IShardingDbContext shardingDbContext)
128+
{
129+
var dbContext = shardingDbContext.GetDbContext(dataSourceName, false, _routeTailFactory.Create(string.Empty));
130+
131+
var modelCacheSyncObject = dbContext.GetModelCacheSyncObject();
132+
133+
var acquire = System.Threading.Monitor.TryEnter(modelCacheSyncObject, TimeSpan.FromSeconds(3));
134+
if (!acquire)
135+
{
136+
throw new ShardingCoreException("cant get modelCacheSyncObject lock");
137+
}
138+
139+
try
140+
{
141+
dbContext.RemoveDbContextRelationModelThatIsShardingTable();
142+
dbContext.Database.EnsureCreated();
143+
dbContext.RemoveModelCache();
144+
}
145+
finally
146+
{
147+
System.Threading.Monitor.Exit(modelCacheSyncObject);
148+
}
149+
}
150+
}
151+
}
152+
}

src/ShardingCore/DIExtensions/ShardingCoreConfigEndBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ private void RegisterReadWriteConfigure(IServiceCollection services)
9696
new ReadWriteOptions<TShardingDbContext>(
9797
_shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority,
9898
_shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable,
99+
_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,
99100
_shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy));
100101
bool isLoop = false;
101102
var readStrategyEnum = _shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum;

src/ShardingCore/Sharding/ReadWriteConfigurations/Abstractions/IReadWriteOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public interface IReadWriteOptions<TShardingDbContext>
2424
/// 默认是否开启读写分离
2525
/// </summary>
2626
bool ReadWriteSupport { get; }
27+
ReadStrategyEnum ReadStrategy { get; }
2728
ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
2829
}
2930
}

src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteOptions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations
1818
public class ReadWriteOptions<TShardingDbContext> : IReadWriteOptions<TShardingDbContext>
1919
where TShardingDbContext : DbContext, IShardingDbContext
2020
{
21-
public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadConnStringGetStrategyEnum readConnStringGetStrategy)
21+
public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadStrategyEnum readStrategy, ReadConnStringGetStrategyEnum readConnStringGetStrategy)
2222
{
2323
ReadWritePriority = readWritePriority;
2424
ReadWriteSupport = readWriteSupport;
25+
ReadStrategy = readStrategy;
2526
ReadConnStringGetStrategy = readConnStringGetStrategy;
2627
}
2728
public Type ShardingDbContextType => typeof(TShardingDbContext);
@@ -33,6 +34,8 @@ public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadConnSt
3334
/// 默认是否开启读写分离
3435
/// </summary>
3536
public bool ReadWriteSupport { get; }
37+
38+
public ReadStrategyEnum ReadStrategy { get; }
3639
public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
3740
}
3841
}

src/ShardingCore/Sharding/ReadWriteConfigurations/ReadWriteShardingConnectionStringResolver.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class ReadWriteShardingConnectionStringResolver<TShardingDbContext> : ISh
1616
private readonly ConcurrentDictionary<string, IReadWriteConnector> _connectors =
1717
new ConcurrentDictionary<string, IReadWriteConnector>();
1818

19+
private readonly IReadWriteOptions<TShardingDbContext> _readWriteOptions;
1920
public ReadWriteShardingConnectionStringResolver(IEnumerable<IReadWriteConnector> connectors)
2021
{
2122
var enumerator = connectors.GetEnumerator();
@@ -26,6 +27,7 @@ public ReadWriteShardingConnectionStringResolver(IEnumerable<IReadWriteConnector
2627
_connectors.TryAdd(currentConnector.DataSourceName, currentConnector);
2728
}
2829

30+
_readWriteOptions = ShardingContainer.GetService<IReadWriteOptions<TShardingDbContext>>();
2931
}
3032

3133
public bool ContainsReadWriteDataSourceName(string dataSourceName)
@@ -43,8 +45,24 @@ public string GetConnectionString(string dataSourceName)
4345
public bool AddConnectionString(string dataSourceName, string connectionString)
4446
{
4547
if (!_connectors.TryGetValue(dataSourceName, out var connector))
46-
throw new ShardingCoreInvalidOperationException($"read write connector not found, data source name:[{dataSourceName}]");
47-
return connector.AddConnectionString(connectionString);
48+
{
49+
if (_readWriteOptions.ReadStrategy == ReadStrategyEnum.Loop)
50+
{
51+
connector= new ReadWriteLoopConnector(dataSourceName, new List<string> { connectionString });
52+
}
53+
else if (_readWriteOptions.ReadStrategy == ReadStrategyEnum.Random)
54+
{
55+
connector= new ReadWriteLoopConnector(dataSourceName, new List<string> { connectionString });
56+
}
57+
58+
throw new ShardingCoreInvalidOperationException(
59+
$"unknown read write strategy:[{_readWriteOptions.ReadStrategy}]");
60+
61+
}
62+
else
63+
{
64+
return connector.AddConnectionString(connectionString);
65+
}
4866
}
4967
}
5068
}

test/ShardingCore.Test/ShardingTest.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ public class ShardingTest
5151
private readonly IShardingTableCreator<ShardingDefaultDbContext> _shardingTableCreator;
5252
private readonly IShardingReadWriteManager _shardingReadWriteManager;
5353
private readonly IRouteTailFactory _routeTailFactory;
54+
private readonly IShardingConnectionStringResolver<ShardingDefaultDbContext> _shardingConnectionStringResolver;
5455

5556
public ShardingTest(ShardingDefaultDbContext virtualDbContext, IShardingRouteManager shardingRouteManager, IConfiguration configuration,
5657
IEntityMetadataManager<ShardingDefaultDbContext> entityMetadataManager,
5758
IShardingComparer<ShardingDefaultDbContext> shardingComparer, IVirtualDataSource<ShardingDefaultDbContext> virtualDataSource,
5859
IVirtualTableManager<ShardingDefaultDbContext> virtualTableManager,
59-
IShardingTableCreator<ShardingDefaultDbContext> shardingTableCreator, IShardingReadWriteManager shardingReadWriteManager,IRouteTailFactory routeTailFactory)
60+
IShardingTableCreator<ShardingDefaultDbContext> shardingTableCreator, IShardingReadWriteManager shardingReadWriteManager,IRouteTailFactory routeTailFactory,IShardingConnectionStringResolver<ShardingDefaultDbContext> shardingConnectionStringResolver)
6061
{
6162
_virtualDbContext = virtualDbContext;
6263
_shardingRouteManager = shardingRouteManager;
@@ -69,6 +70,7 @@ public ShardingTest(ShardingDefaultDbContext virtualDbContext, IShardingRouteMan
6970
_shardingTableCreator = shardingTableCreator;
7071
_shardingReadWriteManager = shardingReadWriteManager;
7172
_routeTailFactory = routeTailFactory;
73+
_shardingConnectionStringResolver = shardingConnectionStringResolver;
7274

7375
//var dataSource = ShardingContainer.GetService<IVirtualDataSource<ShardingDefaultDbContext>>();
7476
//dataSource.AddPhysicDataSource(new DefaultPhysicDataSource("E", "XXXXX", false));
@@ -222,6 +224,9 @@ public async Task GenericTest()
222224
{ new ParallelTableComparerType(typeof(SysUserSalary)),new ParallelTableComparerType(typeof(SysUserMod)), });
223225
Assert.Equal(x1x1, x2x2);
224226
Assert.Equal(x1x1.GetHashCode(), x2x2.GetHashCode());
227+
var succeedAddConnectionString = _shardingConnectionStringResolver.AddConnectionString("A", "Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;");
228+
Assert.True(succeedAddConnectionString);
229+
225230
}
226231

227232
public class SequenceClass

0 commit comments

Comments
 (0)