[#161]支持分库迁移
This commit is contained in:
parent
4cd1a8a073
commit
98f76b409b
|
@ -31,7 +31,7 @@ namespace Sample.Migrations.EFCores
|
|||
var newCmds = builder.GetCommandList().ToList();
|
||||
var addCmds = newCmds.Where(x => !oldCmds.Contains(x)).ToList();
|
||||
|
||||
MigrationHelper.Generate<TShardingDbContext>(_shardingRuntimeContext,operation, builder, Dependencies.SqlGenerationHelper, addCmds);
|
||||
MigrationHelper.Generate(_shardingRuntimeContext,operation, builder, Dependencies.SqlGenerationHelper, addCmds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Sample.MySql
|
|||
{
|
||||
Id = id.ToString(),
|
||||
Age = id,
|
||||
Name = $"name_{id}",
|
||||
Name = $"ds{(id%3)}",
|
||||
});
|
||||
}
|
||||
var userModMonths = new List<SysUserLogByMonth>();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||
using Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal;
|
||||
using Pomelo.EntityFrameworkCore.MySql.Migrations;
|
||||
using ShardingCore.Core.RuntimeContexts;
|
||||
using ShardingCore.Helpers;
|
||||
|
||||
namespace Sample.MySql
|
||||
{
|
||||
public class ShardingMySqlMigrationsSqlGenerator:MySqlMigrationsSqlGenerator
|
||||
{
|
||||
private readonly IShardingRuntimeContext _shardingRuntimeContext;
|
||||
|
||||
public ShardingMySqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IRelationalAnnotationProvider annotationProvider, IMySqlOptions options,IShardingRuntimeContext shardingRuntimeContext) : base(dependencies, annotationProvider, options)
|
||||
{
|
||||
_shardingRuntimeContext = shardingRuntimeContext;
|
||||
}
|
||||
protected override void Generate(
|
||||
MigrationOperation operation,
|
||||
IModel model,
|
||||
MigrationCommandListBuilder builder)
|
||||
{
|
||||
var oldCmds = builder.GetCommandList().ToList();
|
||||
base.Generate(operation, model, builder);
|
||||
var newCmds = builder.GetCommandList().ToList();
|
||||
var addCmds = newCmds.Where(x => !oldCmds.Contains(x)).ToList();
|
||||
|
||||
MigrationHelper.Generate(_shardingRuntimeContext,operation, builder, Dependencies.SqlGenerationHelper, addCmds);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,10 @@ public class SysUserModVirtualDataSourceRoute:AbstractShardingOperatorVirtualDat
|
|||
|
||||
public override List<string> GetAllDataSourceNames()
|
||||
{
|
||||
return Enumerable.Range(0, 500).Select(o => $"ds{o}").ToList();
|
||||
return new List<string>()
|
||||
{
|
||||
"ds0", "ds1", "ds2"
|
||||
};
|
||||
}
|
||||
|
||||
public override bool AddDataSourceName(string dataSourceName)
|
||||
|
|
|
@ -1,17 +1,36 @@
|
|||
using System.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Sample.MySql.DbContexts;
|
||||
using Sample.MySql.Shardings;
|
||||
using ShardingCore;
|
||||
using ShardingCore.Bootstrappers;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.RuntimeContexts;
|
||||
using ShardingCore.EFCores;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.TableExists;
|
||||
using ShardingCore.TableExists.Abstractions;
|
||||
|
||||
namespace Sample.MySql
|
||||
{
|
||||
// public class AutoStart : IHostedService
|
||||
// {
|
||||
//
|
||||
// public AutoStart(IShardingBootstrapper shardingBootstrapper)
|
||||
// {
|
||||
// shardingBootstrapper.Start();
|
||||
// }
|
||||
// public Task StartAsync(CancellationToken cancellationToken)
|
||||
// {
|
||||
// return Task.CompletedTask;
|
||||
// }
|
||||
//
|
||||
// public Task StopAsync(CancellationToken cancellationToken)
|
||||
// {
|
||||
// return Task.CompletedTask;
|
||||
// }
|
||||
// }
|
||||
public class Startup
|
||||
{
|
||||
public static readonly ILoggerFactory efLogger = LoggerFactory.Create(builder =>
|
||||
|
@ -28,6 +47,7 @@ namespace Sample.MySql
|
|||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// services.AddHostedService<AutoStart>();
|
||||
services.AddControllers();
|
||||
// services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseMySql(hostBuilderContext.Configuration.GetSection("MySql")["ConnectionString"],new MySqlServerVersion("5.7.15"))
|
||||
// ,op =>
|
||||
|
@ -49,7 +69,7 @@ namespace Sample.MySql
|
|||
{
|
||||
o.AddShardingTableRoute<SysUserLogByMonthRoute>();
|
||||
o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||
// o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
|
||||
o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
|
||||
}).UseConfig(o =>
|
||||
{
|
||||
o.UseShardingQuery((conStr,builder)=>
|
||||
|
@ -68,6 +88,19 @@ namespace Sample.MySql
|
|||
.EnableSensitiveDataLogging();
|
||||
});
|
||||
o.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
|
||||
o.AddExtraDataSource(sp=>new Dictionary<string, string>()
|
||||
{
|
||||
{"ds1", "server=127.0.0.1;port=3306;database=dbdbd1;userid=root;password=root;"},
|
||||
{"ds2", "server=127.0.0.1;port=3306;database=dbdbd2;userid=root;password=root;"}
|
||||
});
|
||||
o.UseShellDbContextConfigure(b =>
|
||||
{
|
||||
b.ReplaceService<IMigrator, ShardingMigrator>();
|
||||
});
|
||||
o.UseExecutorDbContextConfigure(b =>
|
||||
{
|
||||
b.ReplaceService<IMigrationsSqlGenerator, ShardingMySqlMigrationsSqlGenerator>();
|
||||
});
|
||||
}).ReplaceService<ITableEnsureManager,MySqlTableEnsureManager>(ServiceLifetime.Singleton)
|
||||
.Build(sp);
|
||||
stopwatch.Stop();
|
||||
|
@ -120,6 +153,17 @@ namespace Sample.MySql
|
|||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
app.ApplicationServices.UseAutoShardingCreate();
|
||||
|
||||
using (var scope = app.ApplicationServices.CreateScope())
|
||||
{
|
||||
var defaultShardingDbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
|
||||
if (defaultShardingDbContext.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
defaultShardingDbContext.Database.Migrate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
app.ApplicationServices.UseAutoTryCompensateTable();
|
||||
app.UseRouting();
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace Samples.AutoByDate.SqlServer
|
|||
/// <summary>
|
||||
/// https://github.com/Coldairarrow/EFCore.Sharding/blob/master/src/EFCore.Sharding.SqlServer/ShardingSqlServerMigrationsSqlGenerator.cs
|
||||
/// </summary>
|
||||
public class ShardingSqlServerMigrationsSqlGenerator<TShardingDbContext> : SqlServerMigrationsSqlGenerator where TShardingDbContext : DbContext, IShardingDbContext
|
||||
public class ShardingSqlServerMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
|
||||
{
|
||||
private readonly IShardingRuntimeContext _shardingRuntimeContext;
|
||||
|
||||
|
@ -78,7 +78,7 @@ namespace Samples.AutoByDate.SqlServer
|
|||
var newCmds = builder.GetCommandList().ToList();
|
||||
var addCmds = newCmds.Where(x => !oldCmds.Contains(x)).ToList();
|
||||
|
||||
MigrationHelper.Generate<TShardingDbContext>(_shardingRuntimeContext,operation, builder, Dependencies.SqlGenerationHelper, addCmds);
|
||||
MigrationHelper.Generate(_shardingRuntimeContext,operation, builder, Dependencies.SqlGenerationHelper, addCmds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace ShardingCore.Core.RuntimeContexts
|
|||
|
||||
public interface IShardingRuntimeContext
|
||||
{
|
||||
IShardingProvider GetIhardingProvider();
|
||||
IShardingProvider GetShardingProvider();
|
||||
IShardingComparer GetShardingComparer();
|
||||
IShardingCompilerExecutor GetShardingCompilerExecutor();
|
||||
IShardingReadWriteManager GetShardingReadWriteManager();
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace ShardingCore.Core.RuntimeContexts
|
|||
}
|
||||
|
||||
private IShardingProvider _shardingProvider;
|
||||
public IShardingProvider GetIhardingProvider()
|
||||
public IShardingProvider GetShardingProvider()
|
||||
{
|
||||
return _shardingProvider??=GetRequiredService<IShardingProvider>();
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ namespace ShardingCore.Core.RuntimeContexts
|
|||
|
||||
try
|
||||
{
|
||||
var shardingProvider = GetIhardingProvider();
|
||||
var shardingProvider = GetShardingProvider();
|
||||
using (var scope = shardingProvider.CreateScope())
|
||||
{
|
||||
using (var dbContext = _dbContextCreator.GetShellDbContext(scope.ServiceProvider))
|
||||
|
@ -222,6 +222,11 @@ namespace ShardingCore.Core.RuntimeContexts
|
|||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
trackerManager.AddDbContextModel(entityType.ClrType, entityType.FindPrimaryKey() != null);
|
||||
if (!entityMetadataManager.IsSharding(entityType.ClrType))
|
||||
{
|
||||
var entityMetadata = new EntityMetadata(entityType.ClrType);
|
||||
entityMetadataManager.AddEntityMetadata(entityMetadata);
|
||||
}
|
||||
entityMetadataManager.TryInitModel(entityType);
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +294,7 @@ namespace ShardingCore.Core.RuntimeContexts
|
|||
|
||||
private void InitFieldValue()
|
||||
{
|
||||
GetIhardingProvider();
|
||||
GetShardingProvider();
|
||||
GetShardingComparer();
|
||||
GetShardingCompilerExecutor();
|
||||
GetShardingReadWriteManager();
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
namespace ShardingCore.Core.ShardingMigrations.Abstractions
|
||||
{
|
||||
|
||||
public interface IShardingMigrationAccessor
|
||||
{
|
||||
ShardingMigrationContext ShardingMigrationContext { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
namespace ShardingCore.Core.ShardingMigrations.Abstractions
|
||||
{
|
||||
|
||||
public interface IShardingMigrationManager
|
||||
{
|
||||
ShardingMigrationContext Current { get; }
|
||||
/// <summary>
|
||||
/// 创建路由scope
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
ShardingMigrationScope CreateScope();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System.Threading;
|
||||
using ShardingCore.Core.ShardingMigrations.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.ShardingMigrations
|
||||
{
|
||||
|
||||
public class ShardingMigrationAccessor:IShardingMigrationAccessor
|
||||
{
|
||||
private static AsyncLocal<ShardingMigrationContext> _shardingMigrationContext = new AsyncLocal<ShardingMigrationContext>();
|
||||
public ShardingMigrationContext ShardingMigrationContext
|
||||
{
|
||||
get => _shardingMigrationContext.Value;
|
||||
set => _shardingMigrationContext.Value = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
namespace ShardingCore.Core.ShardingMigrations
|
||||
{
|
||||
|
||||
public class ShardingMigrationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前的数据源名称
|
||||
/// </summary>
|
||||
public string CurrentDataSourceName { get; set; }
|
||||
|
||||
public static ShardingMigrationContext Create()
|
||||
{
|
||||
return new ShardingMigrationContext();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using ShardingCore.Core.ShardingMigrations.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.ShardingMigrations
|
||||
{
|
||||
public class ShardingMigrationManager:IShardingMigrationManager
|
||||
{
|
||||
private readonly IShardingMigrationAccessor _shardingMigrationAccessor;
|
||||
|
||||
public ShardingMigrationManager(IShardingMigrationAccessor shardingMigrationAccessor)
|
||||
{
|
||||
_shardingMigrationAccessor = shardingMigrationAccessor;
|
||||
}
|
||||
|
||||
public ShardingMigrationContext Current => _shardingMigrationAccessor.ShardingMigrationContext;
|
||||
public ShardingMigrationScope CreateScope()
|
||||
{
|
||||
var shardingMigrationScope = new ShardingMigrationScope(_shardingMigrationAccessor);
|
||||
_shardingMigrationAccessor.ShardingMigrationContext = ShardingMigrationContext.Create();
|
||||
return shardingMigrationScope;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
using System;
|
||||
|
||||
namespace ShardingCore.Core.ShardingMigrations
|
||||
{
|
||||
public class ShardingMigrationOptions
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using ShardingCore.Core.ShardingMigrations.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.ShardingMigrations
|
||||
{
|
||||
|
||||
public class ShardingMigrationScope:IDisposable
|
||||
{
|
||||
private readonly IShardingMigrationAccessor _shardingMigrationAccessor;
|
||||
|
||||
public ShardingMigrationScope(IShardingMigrationAccessor shardingMigrationAccessor)
|
||||
{
|
||||
_shardingMigrationAccessor = shardingMigrationAccessor;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
_shardingMigrationAccessor.ShardingMigrationContext = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -124,7 +124,7 @@ namespace ShardingCore.DynamicDataSources
|
|||
}
|
||||
else
|
||||
{
|
||||
dbContext.RemoveDbContextAllRelationModelThatIsNoSharding();
|
||||
dbContext.RemoveDbContextAllRelationModelWithoutShardingDataSourceOnly();
|
||||
}
|
||||
|
||||
dbContext.Database.EnsureCreated();
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Migrations.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using ShardingCore.Core.RuntimeContexts;
|
||||
using ShardingCore.Core.ShardingMigrations.Abstractions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace ShardingCore.EFCores
|
||||
{
|
||||
public class ShardingMigrator:Migrator
|
||||
{
|
||||
private readonly IShardingRuntimeContext _shardingRuntimeContext;
|
||||
|
||||
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)
|
||||
{
|
||||
_shardingRuntimeContext = shardingRuntimeContext;
|
||||
}
|
||||
|
||||
public override void Migrate(string targetMigration = null)
|
||||
{
|
||||
this.MigrateAsync(targetMigration).WaitAndUnwrapException();
|
||||
// base.Migrate(targetMigration);
|
||||
}
|
||||
|
||||
public override async Task MigrateAsync(string targetMigration = null, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource();
|
||||
var shardingProvider = _shardingRuntimeContext.GetShardingProvider();
|
||||
var dbContextCreator = _shardingRuntimeContext.GetDbContextCreator();
|
||||
var routeTailFactory = _shardingRuntimeContext.GetRouteTailFactory();
|
||||
var shardingMigrationManager = _shardingRuntimeContext.GetRequiredService<IShardingMigrationManager>();
|
||||
var allDataSourceNames = virtualDataSource.GetAllDataSourceNames();
|
||||
using (var scope=shardingProvider.CreateScope())
|
||||
{
|
||||
using (var shellDbContext = dbContextCreator.GetShellDbContext(scope.ServiceProvider))
|
||||
{
|
||||
var shardingDbContext = (IShardingDbContext)shellDbContext;
|
||||
foreach (var dataSourceName in allDataSourceNames)
|
||||
{
|
||||
using (shardingMigrationManager.CreateScope())
|
||||
{
|
||||
shardingMigrationManager.Current.CurrentDataSourceName = dataSourceName;
|
||||
|
||||
using (var dbContext = shardingDbContext.GetDbContext(dataSourceName, true,
|
||||
routeTailFactory.Create(string.Empty, false)))
|
||||
{
|
||||
if ((await dbContext.Database.GetPendingMigrationsAsync()).Any())
|
||||
{
|
||||
await dbContext.Database.MigrateAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -103,10 +103,10 @@ namespace ShardingCore.Extensions
|
|||
//#endif
|
||||
// }
|
||||
/// <summary>
|
||||
/// 移除所有的没有分片的表
|
||||
/// 移除所有除了仅分库的
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
public static void RemoveDbContextAllRelationModelThatIsNoSharding(this DbContext dbContext)
|
||||
public static void RemoveDbContextAllRelationModelWithoutShardingDataSourceOnly(this DbContext dbContext)
|
||||
{
|
||||
#if !EFCORE2&&!EFCORE3&&!EFCORE5&&!EFCORE6
|
||||
throw new NotImplementedException();
|
||||
|
|
|
@ -12,6 +12,8 @@ using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
|||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.RuntimeContexts;
|
||||
using ShardingCore.Core.ShardingMigrations.Abstractions;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
|
@ -31,33 +33,61 @@ namespace ShardingCore.Helpers
|
|||
public class MigrationHelper
|
||||
{
|
||||
private MigrationHelper() { }
|
||||
public static void Generate<TShardingDContext>(
|
||||
public static void Generate(
|
||||
IShardingRuntimeContext shardingRuntimeContext,
|
||||
MigrationOperation operation,
|
||||
MigrationCommandListBuilder builder,
|
||||
ISqlGenerationHelper sqlGenerationHelper,
|
||||
List<MigrationCommand> addCmds
|
||||
) where TShardingDContext:DbContext,IShardingDbContext
|
||||
)
|
||||
{
|
||||
var migrationCommands = (List<MigrationCommand>) builder.GetFieldValue("_commands");
|
||||
addCmds.ForEach(aAddCmd =>
|
||||
var shardingMigrationManager = shardingRuntimeContext.GetRequiredService<IShardingMigrationManager>();
|
||||
var virtualDataSource = shardingRuntimeContext.GetRequiredService<IVirtualDataSource>();
|
||||
if (shardingMigrationManager.Current == null||shardingMigrationManager.Current.CurrentDataSourceName==virtualDataSource.DefaultDataSourceName)
|
||||
{
|
||||
var shardingCmds = BuildShardingCmds<TShardingDContext>(shardingRuntimeContext,operation, aAddCmd.CommandText, sqlGenerationHelper);
|
||||
if (shardingCmds.IsNotEmpty())
|
||||
addCmds.ForEach(aAddCmd =>
|
||||
{
|
||||
migrationCommands.Remove(aAddCmd);
|
||||
//针对builder的原始表进行移除
|
||||
shardingCmds.ForEach(aShardingCmd =>
|
||||
var shardingCmds = BuildShardingCmds(shardingRuntimeContext,operation, aAddCmd.CommandText, sqlGenerationHelper);
|
||||
if (shardingCmds.IsNotEmpty())
|
||||
{
|
||||
builder.Append(aShardingCmd)
|
||||
.EndCommand();
|
||||
});
|
||||
}
|
||||
});
|
||||
migrationCommands.Remove(aAddCmd);
|
||||
//针对builder的原始表进行移除
|
||||
shardingCmds.ForEach(aShardingCmd =>
|
||||
{
|
||||
builder.Append(aShardingCmd)
|
||||
.EndCommand();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
addCmds.ForEach(aAddCmd =>
|
||||
{
|
||||
var (migrationResult,shardingCmds) = BuildDataSourceShardingCmds(shardingRuntimeContext,shardingMigrationManager.Current.CurrentDataSourceName,operation, aAddCmd.CommandText, sqlGenerationHelper);
|
||||
//如果是分库的
|
||||
if (migrationResult==MigrationResultEnum.DataSourceTableCommand)
|
||||
{
|
||||
if (shardingCmds.IsNotEmpty())
|
||||
{
|
||||
migrationCommands.Remove(aAddCmd);
|
||||
//针对builder的原始表进行移除
|
||||
shardingCmds.ForEach(aShardingCmd =>
|
||||
{
|
||||
builder.Append(aShardingCmd)
|
||||
.EndCommand();
|
||||
});
|
||||
}
|
||||
}else if (migrationResult==MigrationResultEnum.TableCommand)//如果不是分库并且有表的话那么就把命令删除掉
|
||||
{
|
||||
migrationCommands.Remove(aAddCmd);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> BuildShardingCmds<TShardingDContext>(IShardingRuntimeContext shardingRuntimeContext,MigrationOperation operation, string sourceCmd, ISqlGenerationHelper sqlGenerationHelper)
|
||||
where TShardingDContext : DbContext, IShardingDbContext
|
||||
private static List<string> BuildShardingCmds(IShardingRuntimeContext shardingRuntimeContext,MigrationOperation operation, string sourceCmd, ISqlGenerationHelper sqlGenerationHelper)
|
||||
{
|
||||
//所有MigrationOperation定义
|
||||
//https://github.com/dotnet/efcore/tree/b970bf29a46521f40862a01db9e276e6448d3cb0/src/EFCore.Relational/Migrations/Operations
|
||||
|
@ -114,6 +144,92 @@ namespace ShardingCore.Helpers
|
|||
return string.Format("^({0})$|^({0}_.*?)$|^(.*?_{0}_.*?)$|^(.*?_{0})$", absTableName);
|
||||
}
|
||||
}
|
||||
private static (MigrationResultEnum migrationResult,List<string>) BuildDataSourceShardingCmds(IShardingRuntimeContext shardingRuntimeContext,string dataSourceName,MigrationOperation operation, string sourceCmd, ISqlGenerationHelper sqlGenerationHelper)
|
||||
{
|
||||
//所有MigrationOperation定义
|
||||
//https://github.com/dotnet/efcore/tree/b970bf29a46521f40862a01db9e276e6448d3cb0/src/EFCore.Relational/Migrations/Operations
|
||||
//ColumnOperation仅替换Table
|
||||
//其余其余都是将Name和Table使用分表名替换
|
||||
var dataSourceRouteManager = shardingRuntimeContext.GetDataSourceRouteManager();
|
||||
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
|
||||
var tableRouteManager = shardingRuntimeContext.GetTableRouteManager();
|
||||
var tableRoutes = tableRouteManager.GetRoutes();
|
||||
var existsShardingTables = tableRoutes.ToDictionary(o => o.EntityMetadata.LogicTableName, o => o.GetTails().Select(p=>$"{o.EntityMetadata.LogicTableName}{o.EntityMetadata.TableSeparator}{p}").ToList());
|
||||
//Dictionary<string, List<string>> _existsShardingTables
|
||||
// = Cache.ServiceProvider.GetService<ShardingContainer>().ExistsShardingTables;
|
||||
List<string> resList = new List<string>();
|
||||
string absTableName = string.Empty;
|
||||
|
||||
string name = operation.GetPropertyValue("Name") as string;
|
||||
string tableName = operation.GetPropertyValue("Table") as string;
|
||||
string pattern = string.Format("^({0})$|^({0}_.*?)$|^(.*?_{0}_.*?)$|^(.*?_{0})$", absTableName);
|
||||
Func<KeyValuePair<string, List<string>>, bool> where = x =>
|
||||
existsShardingTables.Any(y =>x.Key==y.Key&& Regex.IsMatch(name, BuildPattern(y.Key)));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tableName))
|
||||
{
|
||||
absTableName = tableName;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
if (existsShardingTables.Any(x => where(x)))
|
||||
{
|
||||
absTableName = existsShardingTables.Where(x => where(x)).FirstOrDefault().Key;
|
||||
}
|
||||
else
|
||||
{
|
||||
absTableName = name;
|
||||
}
|
||||
}
|
||||
|
||||
MigrationResultEnum migrationResult = MigrationResultEnum.OtherCommand;
|
||||
var entityMetadata = entityMetadataManager.TryGetByLogicTableName(absTableName);
|
||||
if (entityMetadata != null)
|
||||
{
|
||||
migrationResult = MigrationResultEnum.TableCommand;
|
||||
|
||||
|
||||
bool isShardingDataSource =entityMetadata.IsShardingDataSource();
|
||||
if (isShardingDataSource)
|
||||
{
|
||||
var virtualDataSourceRoute = dataSourceRouteManager.GetRoute(entityMetadata.EntityType);
|
||||
isShardingDataSource = virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName);
|
||||
}
|
||||
|
||||
if (isShardingDataSource)
|
||||
{
|
||||
migrationResult= MigrationResultEnum.DataSourceTableCommand;
|
||||
}
|
||||
//分表
|
||||
if (!string.IsNullOrWhiteSpace(absTableName) && existsShardingTables.ContainsKey(absTableName))
|
||||
{
|
||||
|
||||
var shardings = existsShardingTables[absTableName];
|
||||
shardings.ForEach(aShardingTable =>
|
||||
{
|
||||
string newCmd = sourceCmd;
|
||||
GetReplaceGroups(operation, absTableName, aShardingTable).ForEach(aReplace =>
|
||||
{
|
||||
newCmd = newCmd.Replace(
|
||||
sqlGenerationHelper.DelimitIdentifier(aReplace.sourceName),
|
||||
sqlGenerationHelper.DelimitIdentifier(aReplace.targetName));
|
||||
});
|
||||
if (newCmd.Contains("EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE'"))
|
||||
{
|
||||
newCmd=newCmd.Replace($"EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'{absTableName}'", $"EXEC sp_addextendedproperty 'MS_Description', @description, 'SCHEMA', @defaultSchema, 'TABLE', N'{aShardingTable}'");
|
||||
}
|
||||
resList.Add(newCmd);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (migrationResult,resList);
|
||||
|
||||
string BuildPattern(string absTableName)
|
||||
{
|
||||
return string.Format("^({0})$|^({0}_.*?)$|^(.*?_{0}_.*?)$|^(.*?_{0})$", absTableName);
|
||||
}
|
||||
}
|
||||
private static List<(string sourceName, string targetName)> GetReplaceGroups(
|
||||
MigrationOperation operation, string sourceTableName, string targetTableName)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
namespace ShardingCore.Helpers
|
||||
{
|
||||
public enum MigrationResultEnum
|
||||
{
|
||||
OtherCommand,
|
||||
DataSourceTableCommand,
|
||||
TableCommand
|
||||
}
|
||||
}
|
|
@ -29,6 +29,8 @@ using ShardingCore.Core.DbContextCreator;
|
|||
using ShardingCore.Core.QueryTrackers;
|
||||
using ShardingCore.Core.RuntimeContexts;
|
||||
using ShardingCore.Core.ShardingConfigurations.ConfigBuilders;
|
||||
using ShardingCore.Core.ShardingMigrations;
|
||||
using ShardingCore.Core.ShardingMigrations.Abstractions;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
|
||||
|
@ -144,6 +146,10 @@ namespace ShardingCore
|
|||
services.TryAddSingleton<IQueryableRewriteEngine, QueryableRewriteEngine>();
|
||||
services.TryAddSingleton<IQueryableOptimizeEngine, QueryableOptimizeEngine>();
|
||||
|
||||
//migration manage
|
||||
services.TryAddSingleton<IShardingMigrationAccessor, ShardingMigrationAccessor>();
|
||||
services.TryAddSingleton<IShardingMigrationManager, ShardingMigrationManager>();
|
||||
|
||||
//route manage
|
||||
services.TryAddSingleton<IShardingRouteManager, ShardingRouteManager>();
|
||||
services.TryAddSingleton<IShardingRouteAccessor, ShardingRouteAccessor>();
|
||||
|
@ -151,6 +157,7 @@ namespace ShardingCore
|
|||
//sharding page
|
||||
services.TryAddSingleton<IShardingPageManager, ShardingPageManager>();
|
||||
services.TryAddSingleton<IShardingPageAccessor, ShardingPageAccessor>();
|
||||
|
||||
services.TryAddSingleton<IShardingBootstrapper, ShardingBootstrapper>();
|
||||
services.TryAddSingleton<IUnionAllMergeManager, UnionAllMergeManager>();
|
||||
services.TryAddSingleton<IUnionAllMergeAccessor, UnionAllMergeAccessor>();
|
||||
|
|
Loading…
Reference in New Issue