Skip to content

Commit da640d3

Browse files
committed
修复bug,分表下会多次初始化,启动建表会创建虚拟表,定时任务无法创建分库下的表,发布x.3.1.18修复bug
1 parent d841c63 commit da640d3

16 files changed

+315
-151
lines changed

nuget-publish.bat

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
:start
22
::定义版本
3-
set EFCORE2=2.3.1.16
4-
set EFCORE3=3.3.1.16
5-
set EFCORE5=5.3.1.16
3+
set EFCORE2=2.3.1.18
4+
set EFCORE3=3.3.1.18
5+
set EFCORE5=5.3.1.18
66

77
::删除所有bin与obj下的文件
88
@echo off

src/ShardingCore/Bootstrapers/EntityMetadataInitializer.cs

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,8 @@ public void Initialize()
108108
_virtualTableManager.AddVirtualTable(virtualTable);
109109
//检测校验分表分库对象元数据
110110
entityMetadata.CheckMetadata();
111-
//创建表
112-
CreateDataTable(_dataSourceName, virtualTable);
113111
//添加任务
114-
if (virtualTableRoute is IJob routeJob&& routeJob.StartJob())
112+
if (virtualTableRoute is IJob routeJob && routeJob.StartJob())
115113
{
116114
var jobManager = ShardingContainer.GetService<IJobManager>();
117115
var jobEntries = JobTypeParser.Parse(virtualTableRoute.GetType());
@@ -127,61 +125,6 @@ public void Initialize()
127125
}
128126
}
129127

130-
private void CreateDataTable(string dataSourceName, IVirtualTable virtualTable)
131-
{
132-
var entityMetadata = virtualTable.EntityMetadata;
133-
foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails())
134-
{
135-
if (NeedCreateTable(entityMetadata))
136-
{
137-
try
138-
{
139-
//添加物理表
140-
virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail));
141-
_tableCreator.CreateTable(dataSourceName, entityMetadata.EntityType, tail);
142-
}
143-
catch (Exception e)
144-
{
145-
if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault())
146-
{
147-
_logger.LogWarning(
148-
$"table :{virtualTable.GetVirtualTableName()}{entityMetadata.TableSeparator}{tail} will created.", e);
149-
}
150-
}
151-
}
152-
else
153-
{
154-
//添加物理表
155-
virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail));
156-
}
157-
158-
}
159-
}
160-
private bool NeedCreateTable(EntityMetadata entityMetadata)
161-
{
162-
if (entityMetadata.AutoCreateTable.HasValue)
163-
{
164-
if (entityMetadata.AutoCreateTable.Value)
165-
return entityMetadata.AutoCreateTable.Value;
166-
else
167-
{
168-
if (entityMetadata.AutoCreateDataSourceTable.HasValue)
169-
return entityMetadata.AutoCreateDataSourceTable.Value;
170-
}
171-
}
172-
if (entityMetadata.AutoCreateDataSourceTable.HasValue)
173-
{
174-
if (entityMetadata.AutoCreateDataSourceTable.Value)
175-
return entityMetadata.AutoCreateDataSourceTable.Value;
176-
else
177-
{
178-
if (entityMetadata.AutoCreateTable.HasValue)
179-
return entityMetadata.AutoCreateTable.Value;
180-
}
181-
}
182-
183-
return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault();
184-
}
185128
private IVirtualDataSourceRoute<TEntity> CreateVirtualDataSourceRoute(Type virtualRouteType,EntityMetadata entityMetadata)
186129
{
187130
var constructors

src/ShardingCore/Bootstrapers/ShardingDbContextBootstrapper.cs

Lines changed: 108 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
2020
using ShardingCore.Core.VirtualTables;
2121
using ShardingCore.Extensions;
22+
using ShardingCore.Jobs;
23+
using ShardingCore.Jobs.Abstaractions;
2224
using ShardingCore.Sharding.Abstractions;
2325
using ShardingCore.TableCreator;
2426
using ShardingCore.Utils;
@@ -63,6 +65,7 @@ public void Init()
6365
// virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceKv.Key,
6466
// dataSourceKv.Value, false));
6567
//}
68+
ISet<Type> entitiesInitSet = new HashSet<Type>();
6669
foreach (var dataSourceKv in dataSources)
6770
{
6871

@@ -78,41 +81,121 @@ public void Init()
7881
foreach (var entity in context.Model.GetEntityTypes())
7982
{
8083
var entityType = entity.ClrType;
84+
8185
if (_shardingConfigOption.HasVirtualDataSourceRoute(entityType) ||
82-
_shardingConfigOption.HasVirtualTableRoute(entityType))
86+
_shardingConfigOption.HasVirtualTableRoute(entityType))
8387
{
84-
//获取ShardingEntity的实际表名
88+
//只初始化一次
89+
if (!entitiesInitSet.Contains(entityType))
90+
{
91+
//获取ShardingEntity的实际表名
8592
#if !EFCORE2
86-
var virtualTableName = context.Model.FindEntityType(entityType).GetTableName();
93+
var virtualTableName = context.Model.FindEntityType(entityType).GetTableName();
8794
#endif
8895
#if EFCORE2
89-
var virtualTableName = context.Model.FindEntityType(entityType).Relational().TableName;
96+
var virtualTableName = context.Model.FindEntityType(entityType).Relational().TableName;
9097
#endif
91-
var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(typeof(TShardingDbContext), entityType);
92-
var constructors
93-
= entityMetadataInitializerType.GetTypeInfo().DeclaredConstructors
94-
.Where(c => !c.IsStatic && c.IsPublic)
95-
.ToArray();
96-
var @params = constructors[0].GetParameters().Select((o,i) =>
97-
{
98-
99-
100-
if (i==0)
98+
var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(typeof(TShardingDbContext), entityType);
99+
var constructors
100+
= entityMetadataInitializerType.GetTypeInfo().DeclaredConstructors
101+
.Where(c => !c.IsStatic && c.IsPublic)
102+
.ToArray();
103+
var @params = constructors[0].GetParameters().Select((o, i) =>
101104
{
102-
if (o.ParameterType != typeof(EntityMetadataEnsureParams))
103-
throw new InvalidOperationException($"{typeof(EntityMetadataInitializer<,>).FullName} constructors first params type should {typeof(EntityMetadataEnsureParams).FullName}");
104-
return new EntityMetadataEnsureParams(dataSourceName,entity,virtualTableName);
105-
}
106-
107-
return ShardingContainer.GetService(o.ParameterType);
108-
}).ToArray();
109-
var entityMetadataInitializer = (IEntityMetadataInitializer)Activator.CreateInstance(entityMetadataInitializerType,@params);
110-
entityMetadataInitializer.Initialize();
105+
106+
107+
if (i == 0)
108+
{
109+
if (o.ParameterType != typeof(EntityMetadataEnsureParams))
110+
throw new InvalidOperationException($"{typeof(EntityMetadataInitializer<,>).FullName} constructors first params type should {typeof(EntityMetadataEnsureParams).FullName}");
111+
return new EntityMetadataEnsureParams(dataSourceName, entity, virtualTableName);
112+
}
113+
114+
return ShardingContainer.GetService(o.ParameterType);
115+
}).ToArray();
116+
var entityMetadataInitializer = (IEntityMetadataInitializer)Activator.CreateInstance(entityMetadataInitializerType, @params);
117+
entityMetadataInitializer.Initialize();
118+
entitiesInitSet.Add(entityType);
119+
}
120+
121+
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
122+
//创建表
123+
CreateDataTable(dataSourceName, virtualTable);
124+
//var virtualTableRoute = virtualTable.GetVirtualRoute();
125+
////添加任务
126+
//if (virtualTableRoute is IJob routeJob && routeJob.StartJob())
127+
//{
128+
// var jobManager = ShardingContainer.GetService<IJobManager>();
129+
// var jobEntries = JobTypeParser.Parse(virtualTableRoute.GetType());
130+
// jobEntries.ForEach(o =>
131+
// {
132+
// o.JobName = $"{routeJob.JobName}:{o.JobName}";
133+
// });
134+
// foreach (var jobEntry in jobEntries)
135+
// {
136+
// jobManager.AddJob(jobEntry);
137+
// }
138+
//}
139+
}
140+
}
141+
}
142+
}
143+
}
144+
private void CreateDataTable(string dataSourceName, IVirtualTable virtualTable)
145+
{
146+
var entityMetadata = virtualTable.EntityMetadata;
147+
foreach (var tail in virtualTable.GetVirtualRoute().GetAllTails())
148+
{
149+
if (NeedCreateTable(entityMetadata))
150+
{
151+
try
152+
{
153+
//添加物理表
154+
virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail));
155+
_tableCreator.CreateTable(dataSourceName, entityMetadata.EntityType, tail);
156+
}
157+
catch (Exception e)
158+
{
159+
if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault())
160+
{
161+
_logger.LogWarning(
162+
$"table :{virtualTable.GetVirtualTableName()}{entityMetadata.TableSeparator}{tail} will created.", e);
111163
}
112164
}
113165
}
166+
else
167+
{
168+
//添加物理表
169+
virtualTable.AddPhysicTable(new DefaultPhysicTable(virtualTable, tail));
170+
}
171+
114172
}
115173
}
174+
private bool NeedCreateTable(EntityMetadata entityMetadata)
175+
{
176+
if (entityMetadata.AutoCreateTable.HasValue)
177+
{
178+
if (entityMetadata.AutoCreateTable.Value)
179+
return entityMetadata.AutoCreateTable.Value;
180+
else
181+
{
182+
if (entityMetadata.AutoCreateDataSourceTable.HasValue)
183+
return entityMetadata.AutoCreateDataSourceTable.Value;
184+
}
185+
}
186+
if (entityMetadata.AutoCreateDataSourceTable.HasValue)
187+
{
188+
if (entityMetadata.AutoCreateDataSourceTable.Value)
189+
return entityMetadata.AutoCreateDataSourceTable.Value;
190+
else
191+
{
192+
if (entityMetadata.AutoCreateTable.HasValue)
193+
return entityMetadata.AutoCreateTable.Value;
194+
}
195+
}
196+
197+
return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault();
198+
}
116199
private void EnsureCreated(DbContext context, string dataSourceName)
117200
{
118201
if (context is IShardingDbContext shardingDbContext)
@@ -122,7 +205,8 @@ private void EnsureCreated(DbContext context, string dataSourceName)
122205

123206
lock (modelCacheSyncObject)
124207
{
125-
dbContext.RemoveDbContextRelationModelThatIsShardingTable();
208+
var shardingEntitiyTypes = _shardingConfigOption.GetShardingTableRouteTypes();
209+
dbContext.RemoveDbContextRelationModelThatIsShardingTable(shardingEntitiyTypes);
126210
dbContext.Database.EnsureCreated();
127211
dbContext.RemoveModelCache();
128212
}

src/ShardingCore/Core/EntityMetadatas/EntityMetadataDataSourceBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ private EntityMetadataDataSourceBuilder(EntityMetadata entityMetadata)
2727
public EntityMetadataDataSourceBuilder<TEntity> ShardingProperty<TProperty>(Expression<Func<TEntity, TProperty>> propertyExpression)
2828
{
2929
var propertyAccess = propertyExpression.GetPropertyAccess();
30-
_entityMetadata.SetShardingTableProperty(propertyAccess);
30+
_entityMetadata.SetShardingDataSourceProperty(propertyAccess);
3131
return this;
3232
}
3333
public EntityMetadataDataSourceBuilder<TEntity> ShardingProperty(string propertyName)
3434
{
3535
var propertyInfo = typeof(TEntity).GetProperty(propertyName);
36-
_entityMetadata.SetShardingTableProperty(propertyInfo);
36+
_entityMetadata.SetShardingDataSourceProperty(propertyInfo);
3737
return this;
3838
}
3939
/// <summary>

src/ShardingCore/Extensions/DbContextExtension.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,14 @@ public static class DbContextExtension
2424
/// 移除所有的分表关系的模型
2525
/// </summary>
2626
/// <param name="dbContext"></param>
27-
public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext)
27+
internal static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext,ISet<Type> shardingTableType)
2828
{
2929
var contextModel = dbContext.Model as Model;
30-
var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(dbContext.GetType()));
3130

3231
#if EFCORE5
3332
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
3433
var valueTuples =
35-
contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => entityMetadataManager.IsShardingTable(m.EntityType.ClrType))).Select(o => o.Key).ToList();
34+
contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => shardingTableType.Contains(m.EntityType.ClrType))).Select(o => o.Key).ToList();
3635
for (int i = 0; i < valueTuples.Count; i++)
3736
{
3837
contextModelRelationalModel.Tables.Remove(valueTuples[i]);
@@ -41,7 +40,7 @@ public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContex
4140
#if !EFCORE5
4241
var entityTypes =
4342
contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>;
44-
var list = entityTypes.Where(o=>entityMetadataManager.IsShardingTable(o.Value.ClrType)).Select(o=>o.Key).ToList();
43+
var list = entityTypes.Where(o=> shardingTableType.Contains(o.Value.ClrType)).Select(o=>o.Key).ToList();
4544
for (int i = 0; i < list.Count; i++)
4645
{
4746
entityTypes.Remove(list[i]);

src/ShardingCore/IShardingConfigOption.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public interface IShardingConfigOption
2424
bool HasVirtualDataSourceRoute(Type entityType);
2525
Type GetVirtualDataSourceRouteType(Type entityType);
2626

27+
ISet<Type> GetShardingTableRouteTypes();
28+
ISet<Type> GetShardingDataSourceRouteTypes();
29+
2730

2831
IDictionary<string, string> GetDataSources();
2932

src/ShardingCore/ShardingConfigOption.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,16 @@ public Type GetVirtualDataSourceRouteType(Type entityType)
173173
return _virtualDataSourceRoutes[entityType];
174174
}
175175

176+
public ISet<Type> GetShardingTableRouteTypes()
177+
{
178+
return _virtualTableRoutes.Keys.ToHashSet();
179+
}
180+
181+
public ISet<Type> GetShardingDataSourceRouteTypes()
182+
{
183+
return _virtualDataSourceRoutes.Keys.ToHashSet();
184+
}
185+
176186
public IDictionary<string, string> GetDataSources()
177187
{
178188
var defaultDataSources = new Dictionary<string, string>(){{DefaultDataSourceName,DefaultConnectionString}};

src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ protected override Expression<Func<string, bool>> GetRouteToFilter(DateTime shar
9090
[JobRun(Name = "定时创建表", Cron = "0 0 5 * * ?", RunOnceOnStart = true)]
9191
public virtual void AutoShardingTableCreate()
9292
{
93+
var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
9394
var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
9495
var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
9596
var tableCreator = (IShardingTableCreator)ShardingContainer.GetService(typeof(IShardingTableCreator<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
@@ -100,13 +101,29 @@ public virtual void AutoShardingTableCreate()
100101
}
101102
var now = DateTime.Now.Date.AddDays(1);
102103
var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now);
103-
try
104+
ISet<string> dataSources = new HashSet<string>()
104105
{
105-
tableCreator.CreateTable(virtualDataSource.DefaultDataSourceName, typeof(T), tail);
106+
virtualDataSource.DefaultDataSourceName
107+
};
108+
if (entityMetadataManager.IsShardingDataSource(typeof(T)))
109+
{
110+
var virtualDataSourceRoute = virtualDataSource.GetRoute(typeof(T));
111+
foreach (var dataSourceName in virtualDataSourceRoute.GetAllDataSourceNames())
112+
{
113+
dataSources.Add(dataSourceName);
114+
}
115+
106116
}
107-
catch (Exception e)
117+
foreach (var dataSource in dataSources)
108118
{
109-
//ignore
119+
try
120+
{
121+
tableCreator.CreateTable(dataSource, typeof(T), tail);
122+
}
123+
catch (Exception e)
124+
{
125+
//ignore
126+
}
110127
}
111128
}
112129
/// <summary>

0 commit comments

Comments
 (0)