修复Migrate在同步上下文中block的bug
This commit is contained in:
parent
44a6765139
commit
61f76b7b19
|
@ -1,6 +1,6 @@
|
|||
:start
|
||||
::定义版本
|
||||
set SHARDINGCORE=6.7.0.5
|
||||
set SHARDINGCORE=6.7.0.6
|
||||
|
||||
::删除所有bin与obj下的文件
|
||||
@echo off
|
||||
|
|
|
@ -52,6 +52,8 @@ public class WeatherForecastController : ControllerBase
|
|||
}
|
||||
public async Task<IActionResult> Query1()
|
||||
{
|
||||
var s = Guid.NewGuid().ToString();
|
||||
var anyAsync = await _defaultDbContext.Set<AreaDevice>().AnyAsync(o=>o.Area==s);
|
||||
var list = await _defaultDbContext.Set<AreaDevice>().ToListAsync();
|
||||
return Ok(list);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
using System.Linq.Expressions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace Sample.AutoCreateIfPresent;
|
||||
|
||||
public static class MyShardingExtension
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 根据对象集合解析
|
||||
/// </summary>
|
||||
/// <typeparam name="TShardingDbContext"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="shardingDbContext"></param>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<string, Dictionary<DbContext, IEnumerable<TEntity>>> BulkShardingEnumerable<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext,
|
||||
IEnumerable<TEntity> entities) where TShardingDbContext : DbContext, IShardingDbContext where TEntity : class
|
||||
{
|
||||
if (entities.IsEmpty())
|
||||
return new Dictionary<string, Dictionary<DbContext, IEnumerable<TEntity>>>();
|
||||
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
|
||||
var entityType = typeof(TEntity);
|
||||
var routeTailFactory = shardingRuntimeContext.GetRouteTailFactory();
|
||||
var virtualDataSource = shardingDbContext.GetVirtualDataSource();
|
||||
var dataSourceRouteManager = shardingRuntimeContext.GetDataSourceRouteManager();
|
||||
var tableRouteManager =shardingRuntimeContext.GetTableRouteManager();
|
||||
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
|
||||
var dataSourceNames = new Dictionary<string, Dictionary<string, BulkDicEntry<TEntity>>>();
|
||||
var entitiesArray = entities as TEntity[] ?? entities.ToArray();
|
||||
var isShardingDataSource = entityMetadataManager.IsShardingDataSource(entityType);
|
||||
var isShardingTable = entityMetadataManager.IsShardingTable(entityType);
|
||||
if (!isShardingDataSource && !isShardingTable)
|
||||
return new Dictionary<string, Dictionary<DbContext, IEnumerable<TEntity>>>()
|
||||
{
|
||||
{
|
||||
virtualDataSource.DefaultDataSourceName,
|
||||
new Dictionary<DbContext, IEnumerable<TEntity>>()
|
||||
{
|
||||
{
|
||||
shardingDbContext.CreateGenericDbContext(entitiesArray[0]),
|
||||
entitiesArray
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!isShardingDataSource)
|
||||
{
|
||||
var bulkDicEntries = new Dictionary<string, BulkDicEntry<TEntity>>();
|
||||
dataSourceNames.Add(virtualDataSource.DefaultDataSourceName, bulkDicEntries);
|
||||
|
||||
var tableRoute = tableRouteManager.GetRoute(entityType);
|
||||
var allTails = tableRoute.GetTails().ToHashSet();
|
||||
foreach (var entity in entitiesArray)
|
||||
{
|
||||
BulkShardingTableEnumerable(shardingDbContext, virtualDataSource.DefaultDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, tableRoute, allTails, entity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var virtualDataSourceRoute = dataSourceRouteManager.GetRoute(entityType);
|
||||
var allDataSourceNames = virtualDataSourceRoute.GetAllDataSourceNames().ToHashSet();
|
||||
|
||||
var entityMetadata = entityMetadataManager.TryGet(entityType);
|
||||
IVirtualTableRoute tableRoute = null;
|
||||
ISet<string> allTails = null;
|
||||
if (isShardingTable)
|
||||
{
|
||||
tableRoute = tableRouteManager.GetRoute(entityType);
|
||||
allTails = tableRoute.GetTails().ToHashSet();
|
||||
}
|
||||
foreach (var entity in entitiesArray)
|
||||
{
|
||||
var shardingDataSourceValue = entity.GetPropertyValue(entityMetadata.ShardingDataSourceProperty.Name);
|
||||
if (shardingDataSourceValue == null)
|
||||
throw new ShardingCoreInvalidOperationException($" etities has null value of sharding data source value");
|
||||
var shardingDataSourceName = virtualDataSourceRoute.ShardingKeyToDataSourceName(shardingDataSourceValue);
|
||||
if (!allDataSourceNames.Contains(shardingDataSourceName))
|
||||
throw new ShardingCoreException(
|
||||
$" data source name :[{shardingDataSourceName}] all data source names:[{string.Join(",", allDataSourceNames)}]");
|
||||
if (!dataSourceNames.TryGetValue(shardingDataSourceName, out var bulkDicEntries))
|
||||
{
|
||||
bulkDicEntries = new Dictionary<string, BulkDicEntry<TEntity>>();
|
||||
dataSourceNames.Add(shardingDataSourceName, bulkDicEntries);
|
||||
}
|
||||
|
||||
if (isShardingTable)
|
||||
{
|
||||
BulkShardingTableEnumerable(shardingDbContext, shardingDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, tableRoute, allTails, entity);
|
||||
}
|
||||
else
|
||||
BulkNoShardingTableEnumerable(shardingDbContext, shardingDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, entity);
|
||||
}
|
||||
}
|
||||
|
||||
return dataSourceNames.ToDictionary(o => o.Key,
|
||||
o => o.Value.Select(o => o.Value).ToDictionary(v => v.InnerDbContext, v => v.InnerEntities.Select(t => t)));
|
||||
}
|
||||
|
||||
private static void BulkShardingTableEnumerable<TShardingDbContext, TEntity>(TShardingDbContext shardingDbContext, string dataSourceName, Dictionary<string, BulkDicEntry<TEntity>> dataSourceBulkDicEntries,
|
||||
IRouteTailFactory routeTailFactory,IVirtualTableRoute tableRoute, ISet<string> allTails, TEntity entity)
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
where TEntity : class
|
||||
{
|
||||
var entityType = typeof(TEntity);
|
||||
|
||||
var shardingKey = entity.GetPropertyValue(tableRoute.EntityMetadata.ShardingTableProperty.Name);
|
||||
var tail = tableRoute.ShardingKeyToTail(shardingKey);
|
||||
if (!allTails.Contains(tail))
|
||||
{
|
||||
//不在alltails说明需要新增那么调用routewithvalue就会处理对应tail
|
||||
var tableRouteUnit = tableRoute.RouteWithValue(new DataSourceRouteResult(new HashSet<string>(new[] { dataSourceName })),
|
||||
shardingKey);
|
||||
if (tableRouteUnit.Tail != tail)
|
||||
{
|
||||
throw new ShardingCoreException(
|
||||
$"sharding key route not match entity:{entityType.FullName},sharding key:{shardingKey},sharding tail:{tail}");
|
||||
}
|
||||
allTails.Add(tail);
|
||||
}
|
||||
|
||||
var routeTail = routeTailFactory.Create(tail);
|
||||
var routeTailIdentity = routeTail.GetRouteTailIdentity();
|
||||
if (!dataSourceBulkDicEntries.TryGetValue(routeTailIdentity, out var bulkDicEntry))
|
||||
{
|
||||
var dbContext = shardingDbContext.GetShareDbContext(dataSourceName, routeTail);
|
||||
bulkDicEntry = new BulkDicEntry<TEntity>(dbContext, new LinkedList<TEntity>());
|
||||
dataSourceBulkDicEntries.Add(routeTailIdentity, bulkDicEntry);
|
||||
}
|
||||
|
||||
bulkDicEntry.InnerEntities.AddLast(entity);
|
||||
}
|
||||
private static void BulkNoShardingTableEnumerable<TShardingDbContext, TEntity>(TShardingDbContext shardingDbContext, string dataSourceName, Dictionary<string, BulkDicEntry<TEntity>> dataSourceBulkDicEntries, IRouteTailFactory routeTailFactory, TEntity entity)
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
where TEntity : class
|
||||
{
|
||||
var routeTail = routeTailFactory.Create(string.Empty);
|
||||
var routeTailIdentity = routeTail.GetRouteTailIdentity();
|
||||
if (!dataSourceBulkDicEntries.TryGetValue(routeTailIdentity, out var bulkDicEntry))
|
||||
{
|
||||
var dbContext = shardingDbContext.GetShareDbContext(dataSourceName, routeTail);
|
||||
bulkDicEntry = new BulkDicEntry<TEntity>(dbContext, new LinkedList<TEntity>());
|
||||
dataSourceBulkDicEntries.Add(routeTailIdentity, bulkDicEntry);
|
||||
}
|
||||
|
||||
bulkDicEntry.InnerEntities.AddLast(entity);
|
||||
}
|
||||
internal class BulkDicEntry<TEntity>
|
||||
{
|
||||
public BulkDicEntry(DbContext innerDbContext, LinkedList<TEntity> innerEntities)
|
||||
{
|
||||
InnerDbContext = innerDbContext;
|
||||
InnerEntities = innerEntities;
|
||||
}
|
||||
|
||||
public DbContext InnerDbContext { get; }
|
||||
public LinkedList<TEntity> InnerEntities { get; }
|
||||
}
|
||||
|
||||
public static Dictionary<DbContext, IEnumerable<TEntity>> BulkShardingTableEnumerable<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext,
|
||||
IEnumerable<TEntity> entities) where TShardingDbContext : DbContext, IShardingDbContext
|
||||
where TEntity : class
|
||||
{
|
||||
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
|
||||
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
|
||||
if (entityMetadataManager.IsShardingDataSource(typeof(TEntity)))
|
||||
throw new ShardingCoreInvalidOperationException(typeof(TEntity).FullName);
|
||||
//if (!entityMetadataManager.IsShardingTable(typeof(TEntity)))
|
||||
// throw new ShardingCoreInvalidOperationException(typeof(TEntity).FullName);
|
||||
if (entities.IsEmpty())
|
||||
return new Dictionary<DbContext, IEnumerable<TEntity>>();
|
||||
return shardingDbContext.BulkShardingEnumerable(entities).First().Value;
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据条件表达式解析
|
||||
/// </summary>
|
||||
/// <typeparam name="TShardingDbContext"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="shardingDbContext"></param>
|
||||
/// <param name="where"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary<string, IEnumerable<DbContext>> BulkShardingExpression<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext, Expression<Func<TEntity, bool>> where) where TEntity : class
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
|
||||
var routeTailFactory = shardingRuntimeContext.GetRouteTailFactory();
|
||||
var dataSourceRouteManager = shardingRuntimeContext.GetDataSourceRouteManager();
|
||||
var tableRouteManager = shardingRuntimeContext.GetTableRouteManager();// (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContext.GetType()));
|
||||
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();// (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType()));
|
||||
|
||||
var dataSourceNames = dataSourceRouteManager.GetDataSourceNames(where);
|
||||
var result = new Dictionary<string, LinkedList<DbContext>>();
|
||||
var entityType = typeof(TEntity);
|
||||
|
||||
foreach (var dataSourceName in dataSourceNames)
|
||||
{
|
||||
if (!result.TryGetValue(dataSourceName, out var dbContexts))
|
||||
{
|
||||
dbContexts = new LinkedList<DbContext>();
|
||||
result.Add(dataSourceName, dbContexts);
|
||||
}
|
||||
if (entityMetadataManager.IsShardingTable(entityType))
|
||||
{
|
||||
var physicTables = tableRouteManager.RouteTo(entityType,new DataSourceRouteResult(dataSourceName),new ShardingTableRouteConfig(predicate: @where));
|
||||
if (physicTables.IsEmpty())
|
||||
throw new ShardingCoreException($"{where.ShardingPrint()} cant found any physic table");
|
||||
|
||||
var dbs = physicTables.Select(o => shardingDbContext.GetShareDbContext(dataSourceName, routeTailFactory.Create(o.Tail))).ToList();
|
||||
foreach (var dbContext in dbs)
|
||||
{
|
||||
dbContexts.AddLast(dbContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbContext = shardingDbContext.GetShareDbContext(dataSourceName, routeTailFactory.Create(string.Empty));
|
||||
dbContexts.AddLast(dbContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result.ToDictionary(o => o.Key, o => (IEnumerable<DbContext>)o.Value);
|
||||
}
|
||||
|
||||
public static IEnumerable<DbContext> BulkShardingTableExpression<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext, Expression<Func<TEntity, bool>> where) where TEntity : class
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
|
||||
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();// (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType()));
|
||||
if (entityMetadataManager.IsShardingDataSource(typeof(TEntity)))
|
||||
throw new ShardingCoreInvalidOperationException(typeof(TEntity).FullName);
|
||||
return shardingDbContext.BulkShardingExpression<TShardingDbContext, TEntity>(where).First().Value;
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ namespace Sample.MySql.Controllers
|
|||
|
||||
// var firstOrDefault = _defaultTableDbContext.Set<SysUserMod>().FromSqlRaw($"select * from {nameof(SysUserMod)}").FirstOrDefault();
|
||||
|
||||
var sysUserMods1 = _defaultTableDbContext.Set<SysTest>()
|
||||
var sysUserMods1 = _defaultTableDbContext.Set<SysTest>().UseConnectionMode(1)
|
||||
.Select(o => new ssss(){ Id = o.Id, C = _abc.Select.Count(x => x.Id == o.Id) }).ToList();
|
||||
var sysUserMods2 = _defaultTableDbContext.Set<SysTest>()
|
||||
.Select(o => new ssss(){ Id = o.Id, C = GetAll().Count(x => x.Id == o.Id) }).ToList();
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace ShardingCore.EFCores
|
|||
#endif
|
||||
public override void Migrate(string targetMigration = null)
|
||||
{
|
||||
this.MigrateAsync(targetMigration).WaitAndUnwrapException();
|
||||
this.MigrateAsync(targetMigration).WaitAndUnwrapException(false);
|
||||
// base.Migrate(targetMigration);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ namespace ShardingCore.EFCores
|
|||
{
|
||||
var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource();
|
||||
var allDataSourceNames = virtualDataSource.GetAllDataSourceNames();
|
||||
await DynamicShardingHelper.DynamicMigrateWithDataSourcesAsync(_shardingRuntimeContext, allDataSourceNames, null,targetMigration,cancellationToken);
|
||||
await DynamicShardingHelper.DynamicMigrateWithDataSourcesAsync(_shardingRuntimeContext, allDataSourceNames, null,targetMigration,cancellationToken).ConfigureAwait(false);
|
||||
|
||||
}
|
||||
#if NET6_0 || NET5_0 || NETSTANDARD2_1
|
||||
|
|
|
@ -40,6 +40,12 @@ namespace ShardingCore.Extensions
|
|||
throw new ArgumentNullException(nameof(task));
|
||||
task.GetAwaiter().GetResult();
|
||||
}
|
||||
public static void WaitAndUnwrapException(this Task task,bool continueOnCapturedContext)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
task.ConfigureAwait(continueOnCapturedContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, unwrapping any exceptions.
|
||||
|
|
|
@ -76,13 +76,13 @@ namespace ShardingCore.Helpers
|
|||
foreach (var migrationUnits in partitionMigrationUnits)
|
||||
{
|
||||
var migrateUnits = migrationUnits.Select(o =>new MigrateUnit(shellDbContext,o)).ToList();
|
||||
await ExecuteMigrateUnitsAsync(shardingRuntimeContext,migrateUnits,targetMigration,cancellationToken);
|
||||
await ExecuteMigrateUnitsAsync(shardingRuntimeContext,migrateUnits,targetMigration,cancellationToken).ConfigureAwait((false));
|
||||
}
|
||||
|
||||
//包含默认默认的单独最后一次处理
|
||||
if (allDataSourceNames.Contains(defaultDataSourceName))
|
||||
{
|
||||
await ExecuteMigrateUnitsAsync(shardingRuntimeContext,new List<MigrateUnit>(){new MigrateUnit(shellDbContext,defaultDataSourceName)},targetMigration,cancellationToken);
|
||||
await ExecuteMigrateUnitsAsync(shardingRuntimeContext,new List<MigrateUnit>(){new MigrateUnit(shellDbContext,defaultDataSourceName)},targetMigration,cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ namespace ShardingCore.Helpers
|
|||
|
||||
},cancellationToken);
|
||||
}).ToArray();
|
||||
await TaskHelper.WhenAllFastFail(migrateTasks);
|
||||
await TaskHelper.WhenAllFastFail(migrateTasks).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static DbContextOptions CreateShellDbContextOptions(IShardingRuntimeContext shardingRuntimeContext,Type dbContextType,string dataSourceName)
|
||||
|
|
Loading…
Reference in New Issue