优化添加脚本分片的支持并且发布x.6.0.34

This commit is contained in:
xuejiaming 2022-09-21 22:09:07 +08:00
parent 071a9c9971
commit a04ca15169
9 changed files with 213 additions and 112 deletions

View File

@ -1,9 +1,9 @@
:start :start
::定义版本 ::定义版本
set EFCORE2=2.6.0.33 set EFCORE2=2.6.0.34
set EFCORE3=3.6.0.33 set EFCORE3=3.6.0.34
set EFCORE5=5.6.0.33 set EFCORE5=5.6.0.34
set EFCORE6=6.6.0.33 set EFCORE6=6.6.0.34
::删除所有bin与obj下的文件 ::删除所有bin与obj下的文件
@echo off @echo off

View File

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
namespace ShardingCore.EFCores
{
public abstract class AbstractScriptMigrationGenerator
{
private readonly IShardingRuntimeContext _shardingRuntimeContext;
public AbstractScriptMigrationGenerator(IShardingRuntimeContext shardingRuntimeContext)
{
_shardingRuntimeContext = shardingRuntimeContext;
}
public string GenerateScript()
{
var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource();
var allDataSourceNames = virtualDataSource.GetAllDataSourceNames();
var dbContextCreator = _shardingRuntimeContext.GetDbContextCreator();
var shardingProvider = _shardingRuntimeContext.GetShardingProvider();
var shardingConfigOptions = _shardingRuntimeContext.GetShardingConfigOptions();
var defaultDataSourceName = virtualDataSource.DefaultDataSourceName;
using (var scope = shardingProvider.CreateScope())
{
using (var shellDbContext = dbContextCreator.GetShellDbContext(scope.ServiceProvider))
{
var parallelCount = shardingConfigOptions.MigrationParallelCount;
if (parallelCount <= 0)
{
throw new ShardingCoreInvalidOperationException($"migration parallel count must >0");
}
//默认数据源需要最后执行 否则可能会导致异常的情况下GetPendingMigrations为空
var partitionMigrationUnits = allDataSourceNames.Where(o => o != defaultDataSourceName)
.Partition(parallelCount);
var scriptStringBuilder = new StringBuilder();
foreach (var migrationUnits in partitionMigrationUnits)
{
var migrateUnits = migrationUnits.Select(o => new MigrateUnit(shellDbContext, o)).ToList();
var scriptSql = ExecuteMigrateUnits(_shardingRuntimeContext, migrateUnits);
scriptStringBuilder.AppendLine(scriptSql);
}
//包含默认默认的单独最后一次处理
if (allDataSourceNames.Contains(defaultDataSourceName))
{
var scriptSql = ExecuteMigrateUnits(_shardingRuntimeContext,
new List<MigrateUnit>() { new MigrateUnit(shellDbContext, defaultDataSourceName) });
scriptStringBuilder.AppendLine(scriptSql);
}
return scriptStringBuilder.ToString();
}
}
}
private string ExecuteMigrateUnits(IShardingRuntimeContext shardingRuntimeContext,
List<MigrateUnit> migrateUnits)
{
var shardingMigrationManager = shardingRuntimeContext.GetShardingMigrationManager();
var dbContextCreator = shardingRuntimeContext.GetDbContextCreator();
var routeTailFactory = shardingRuntimeContext.GetRouteTailFactory();
var migrateTasks = migrateUnits.Select(migrateUnit =>
{
return Task.Run(() =>
{
using (shardingMigrationManager.CreateScope())
{
shardingMigrationManager.Current.CurrentDataSourceName = migrateUnit.DataSourceName;
var dbContextOptions = DynamicShardingHelper.CreateShellDbContextOptions(shardingRuntimeContext,
migrateUnit.ShellDbContext.GetType(),
migrateUnit.DataSourceName);
using (var dbContext = dbContextCreator.CreateDbContext(migrateUnit.ShellDbContext,
new ShardingDbContextOptions(dbContextOptions,
routeTailFactory.Create(string.Empty, false))))
{
var migrator = dbContext.GetService<IMigrator>();
return $"-- DataSource:{migrateUnit.DataSourceName}" + Environment.NewLine +
GenerateScriptSql(migrator) +
Environment.NewLine;
}
}
});
}).ToArray();
var scripts = TaskHelper.WhenAllFastFail(migrateTasks).WaitAndUnwrapException();
return string.Join(Environment.NewLine, scripts);
}
protected abstract string GenerateScriptSql(IMigrator migrator);
}
}

View File

@ -0,0 +1,27 @@
#if EFCORE2
using Microsoft.EntityFrameworkCore.Migrations;
using ShardingCore.Core.RuntimeContexts;
namespace ShardingCore.EFCores
{
public sealed class ScriptMigrationGenerator:AbstractScriptMigrationGenerator
{
private readonly string _fromMigration;
private readonly string _toMigration;
private readonly bool _idempotent;
public ScriptMigrationGenerator(IShardingRuntimeContext shardingRuntimeContext, string fromMigration = null,
string toMigration = null, bool idempotent = false) : base(shardingRuntimeContext)
{
_fromMigration = fromMigration;
_toMigration = toMigration;
_idempotent = idempotent;
}
protected override string GenerateScriptSql(IMigrator migrator)
{
return migrator.GenerateScript(_fromMigration, _toMigration, _idempotent);
}
}
}
#endif

View File

@ -0,0 +1,27 @@
#if EFCORE3
using Microsoft.EntityFrameworkCore.Migrations;
using ShardingCore.Core.RuntimeContexts;
namespace ShardingCore.EFCores
{
public sealed class ScriptMigrationGenerator:AbstractScriptMigrationGenerator
{
private readonly string _fromMigration;
private readonly string _toMigration;
private readonly bool _idempotent;
public ScriptMigrationGenerator(IShardingRuntimeContext shardingRuntimeContext, string fromMigration = null,
string toMigration = null, bool idempotent = false) : base(shardingRuntimeContext)
{
_fromMigration = fromMigration;
_toMigration = toMigration;
_idempotent = idempotent;
}
protected override string GenerateScriptSql(IMigrator migrator)
{
return migrator.GenerateScript(_fromMigration, _toMigration, _idempotent);
}
}
}
#endif

View File

@ -0,0 +1,28 @@
#if EFCORE5
using Microsoft.EntityFrameworkCore.Migrations;
using ShardingCore.Core.RuntimeContexts;
namespace ShardingCore.EFCores
{
public sealed class ScriptMigrationGenerator:AbstractScriptMigrationGenerator
{
private readonly string _fromMigration;
private readonly string _toMigration;
private readonly MigrationsSqlGenerationOptions _options;
public ScriptMigrationGenerator(IShardingRuntimeContext shardingRuntimeContext, string fromMigration = null,
string toMigration = null,
MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) : base(shardingRuntimeContext)
{
_fromMigration = fromMigration;
_toMigration = toMigration;
_options = options;
}
protected override string GenerateScriptSql(IMigrator migrator)
{
return migrator.GenerateScript(_fromMigration, _toMigration, _options);
}
}
}
#endif

View File

@ -1,128 +1,27 @@
#if EFCORE6 #if EFCORE6
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.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.RuntimeContexts; using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.ShardingDbContextExecutors;
namespace ShardingCore.EFCores namespace ShardingCore.EFCores
{ {
public sealed class ScriptMigrationGenerator public sealed class ScriptMigrationGenerator:AbstractScriptMigrationGenerator
{ {
private readonly IShardingRuntimeContext _shardingRuntimeContext;
private readonly string _fromMigration; private readonly string _fromMigration;
private readonly string _toMigration; private readonly string _toMigration;
private readonly MigrationsSqlGenerationOptions _options; private readonly MigrationsSqlGenerationOptions _options;
public ScriptMigrationGenerator(IShardingRuntimeContext shardingRuntimeContext, string fromMigration = null, public ScriptMigrationGenerator(IShardingRuntimeContext shardingRuntimeContext, string fromMigration = null,
string toMigration = null, string toMigration = null,
MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) : base(shardingRuntimeContext)
{ {
_shardingRuntimeContext = shardingRuntimeContext;
_fromMigration = fromMigration; _fromMigration = fromMigration;
_toMigration = toMigration; _toMigration = toMigration;
_options = options; _options = options;
} }
public string GenerateScript() protected override string GenerateScriptSql(IMigrator migrator)
{ {
var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource(); return migrator.GenerateScript(_fromMigration, _toMigration, _options);
var allDataSourceNames = virtualDataSource.GetAllDataSourceNames();
var dbContextCreator = _shardingRuntimeContext.GetDbContextCreator();
var shardingProvider = _shardingRuntimeContext.GetShardingProvider();
var shardingConfigOptions = _shardingRuntimeContext.GetShardingConfigOptions();
var defaultDataSourceName = virtualDataSource.DefaultDataSourceName;
using (var scope = shardingProvider.CreateScope())
{
using (var shellDbContext = dbContextCreator.GetShellDbContext(scope.ServiceProvider))
{
var parallelCount = shardingConfigOptions.MigrationParallelCount;
if (parallelCount <= 0)
{
throw new ShardingCoreInvalidOperationException($"migration parallel count must >0");
}
//默认数据源需要最后执行 否则可能会导致异常的情况下GetPendingMigrations为空
var partitionMigrationUnits = allDataSourceNames.Where(o => o != defaultDataSourceName)
.Partition(parallelCount);
var scriptStringBuilder = new StringBuilder();
foreach (var migrationUnits in partitionMigrationUnits)
{
var migrateUnits = migrationUnits.Select(o => new MigrateUnit(shellDbContext, o)).ToList();
var scriptSql = ExecuteMigrateUnits(_shardingRuntimeContext, migrateUnits);
scriptStringBuilder.AppendLine(scriptSql);
}
//包含默认默认的单独最后一次处理
if (allDataSourceNames.Contains(defaultDataSourceName))
{
var scriptSql = ExecuteMigrateUnits(_shardingRuntimeContext,
new List<MigrateUnit>() { new MigrateUnit(shellDbContext, defaultDataSourceName) });
scriptStringBuilder.AppendLine(scriptSql);
}
return scriptStringBuilder.ToString();
}
}
}
private string ExecuteMigrateUnits(IShardingRuntimeContext shardingRuntimeContext,
List<MigrateUnit> migrateUnits)
{
var shardingMigrationManager = shardingRuntimeContext.GetShardingMigrationManager();
var dbContextCreator = shardingRuntimeContext.GetDbContextCreator();
var routeTailFactory = shardingRuntimeContext.GetRouteTailFactory();
var migrateTasks = migrateUnits.Select(migrateUnit =>
{
return Task.Run(() =>
{
using (shardingMigrationManager.CreateScope())
{
shardingMigrationManager.Current.CurrentDataSourceName = migrateUnit.DataSourceName;
var dbContextOptions = CreateDbContextOptions(shardingRuntimeContext,
migrateUnit.ShellDbContext.GetType(),
migrateUnit.DataSourceName);
using (var dbContext = dbContextCreator.CreateDbContext(migrateUnit.ShellDbContext,
new ShardingDbContextOptions(dbContextOptions,
routeTailFactory.Create(string.Empty, false))))
{
var migrator = dbContext.GetService<IMigrator>();
return $"-- DataSource:{migrateUnit.DataSourceName}" + Environment.NewLine +
migrator.GenerateScript(_fromMigration, _toMigration, _options) +
Environment.NewLine;
}
}
});
}).ToArray();
var scripts = TaskHelper.WhenAllFastFail(migrateTasks).WaitAndUnwrapException();
return string.Join(Environment.NewLine, scripts);
}
private DbContextOptions CreateDbContextOptions(IShardingRuntimeContext shardingRuntimeContext,
Type dbContextType, string dataSourceName)
{
var virtualDataSource = shardingRuntimeContext.GetVirtualDataSource();
var shardingConfigOptions = shardingRuntimeContext.GetShardingConfigOptions();
var dbContextOptionBuilder = DataSourceDbContext.CreateDbContextOptionBuilder(dbContextType);
var connectionString = virtualDataSource.GetConnectionString(dataSourceName);
virtualDataSource.UseDbContextOptionsBuilder(connectionString, dbContextOptionBuilder);
shardingConfigOptions.ShardingMigrationConfigure?.Invoke(dbContextOptionBuilder);
//迁移
dbContextOptionBuilder.UseShardingOptions(shardingRuntimeContext);
return dbContextOptionBuilder.Options;
} }
} }
} }

View File

@ -35,6 +35,9 @@ namespace ShardingCore.EFCores
{ {
private readonly IShardingRuntimeContext _shardingRuntimeContext; private readonly IShardingRuntimeContext _shardingRuntimeContext;
#if !EFCORE2 && !EFCORE3 && !EFCORE5 && !EFCORE6
error
#endif
#if EFCORE6 #if EFCORE6
public ShardingMigrator(IShardingRuntimeContext shardingRuntimeContext,IMigrationsAssembly migrationsAssembly, IHistoryRepository historyRepository, IDatabaseCreator databaseCreator, IMigrationsSqlGenerator migrationsSqlGenerator, IRawSqlCommandBuilder rawSqlCommandBuilder, IMigrationCommandExecutor migrationCommandExecutor, IRelationalConnection connection, ISqlGenerationHelper sqlGenerationHelper, ICurrentDbContext currentContext, IModelRuntimeInitializer modelRuntimeInitializer, IDiagnosticsLogger<DbLoggerCategory.Migrations> logger, IRelationalCommandDiagnosticsLogger commandLogger, IDatabaseProvider databaseProvider) : base(migrationsAssembly, historyRepository, databaseCreator, migrationsSqlGenerator, rawSqlCommandBuilder, migrationCommandExecutor, connection, sqlGenerationHelper, currentContext, modelRuntimeInitializer, logger, commandLogger, databaseProvider) public ShardingMigrator(IShardingRuntimeContext shardingRuntimeContext,IMigrationsAssembly migrationsAssembly, IHistoryRepository historyRepository, IDatabaseCreator databaseCreator, IMigrationsSqlGenerator migrationsSqlGenerator, IRawSqlCommandBuilder rawSqlCommandBuilder, IMigrationCommandExecutor migrationCommandExecutor, IRelationalConnection connection, ISqlGenerationHelper sqlGenerationHelper, ICurrentDbContext currentContext, IModelRuntimeInitializer modelRuntimeInitializer, IDiagnosticsLogger<DbLoggerCategory.Migrations> logger, IRelationalCommandDiagnosticsLogger commandLogger, IDatabaseProvider databaseProvider) : base(migrationsAssembly, historyRepository, databaseCreator, migrationsSqlGenerator, rawSqlCommandBuilder, migrationCommandExecutor, connection, sqlGenerationHelper, currentContext, modelRuntimeInitializer, logger, commandLogger, databaseProvider)
@ -78,13 +81,20 @@ namespace ShardingCore.EFCores
await DynamicShardingHelper.DynamicMigrateWithDataSourcesAsync(_shardingRuntimeContext, allDataSourceNames, null,cancellationToken); await DynamicShardingHelper.DynamicMigrateWithDataSourcesAsync(_shardingRuntimeContext, allDataSourceNames, null,cancellationToken);
} }
#if EFCORE6 #if EFCORE6 || EFCORE5
public override string GenerateScript(string fromMigration = null, string toMigration = null, public override string GenerateScript(string fromMigration = null, string toMigration = null,
MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default) MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default)
{ {
return new ScriptMigrationGenerator(_shardingRuntimeContext, fromMigration, toMigration, options).GenerateScript(); return new ScriptMigrationGenerator(_shardingRuntimeContext, fromMigration, toMigration, options).GenerateScript();
} }
#endif
#if EFCORE3 || EFCORE2
public override string GenerateScript(string fromMigration = null, string toMigration = null, bool idempotent = false)
{
return new ScriptMigrationGenerator(_shardingRuntimeContext, fromMigration, toMigration, idempotent).GenerateScript();
}
#endif #endif
} }

View File

@ -98,7 +98,7 @@ namespace ShardingCore.Helpers
{ {
shardingMigrationManager.Current.CurrentDataSourceName = migrateUnit.DataSourceName; shardingMigrationManager.Current.CurrentDataSourceName = migrateUnit.DataSourceName;
var dbContextOptions = CreateDbContextOptions(shardingRuntimeContext,migrateUnit.ShellDbContext.GetType(), var dbContextOptions = CreateShellDbContextOptions(shardingRuntimeContext,migrateUnit.ShellDbContext.GetType(),
migrateUnit.DataSourceName); migrateUnit.DataSourceName);
using (var dbContext = dbContextCreator.CreateDbContext(migrateUnit.ShellDbContext, using (var dbContext = dbContextCreator.CreateDbContext(migrateUnit.ShellDbContext,
@ -119,7 +119,7 @@ namespace ShardingCore.Helpers
await TaskHelper.WhenAllFastFail(migrateTasks); await TaskHelper.WhenAllFastFail(migrateTasks);
} }
private static DbContextOptions CreateDbContextOptions(IShardingRuntimeContext shardingRuntimeContext,Type dbContextType,string dataSourceName) public static DbContextOptions CreateShellDbContextOptions(IShardingRuntimeContext shardingRuntimeContext,Type dbContextType,string dataSourceName)
{ {
var virtualDataSource = shardingRuntimeContext.GetVirtualDataSource(); var virtualDataSource = shardingRuntimeContext.GetVirtualDataSource();
var shardingConfigOptions = shardingRuntimeContext.GetShardingConfigOptions(); var shardingConfigOptions = shardingRuntimeContext.GetShardingConfigOptions();

View File

@ -28,6 +28,12 @@
<Compile Include="..\..\src\ShardingCore\**\*.cs" /> <Compile Include="..\..\src\ShardingCore\**\*.cs" />
<Compile Remove="..\..\src\ShardingCore\obj\**" /> <Compile Remove="..\..\src\ShardingCore\obj\**" />
<Compile Remove="..\..\src\ShardingCore\bin\**" /> <Compile Remove="..\..\src\ShardingCore\bin\**" />
<Compile Update="..\..\src\ShardingCore\EFCores\EFCore3x\ScriptMigrationGenerator.cs">
<Link>EFCores\EFCore3x\ScriptMigrationGenerator.cs</Link>
</Compile>
<Compile Update="..\..\src\ShardingCore\EFCores\EFCore2x\ScriptMigrationGenerator.cs">
<Link>EFCores\EFCore2x\ScriptMigrationGenerator.cs</Link>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>