protected virtual void MigrateAspectServices(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor, Action migrateStructureAction) { IServicesManager <IMigrateAccessorAspect> aspects = null; // 数据迁移支持写入连接(包括未启用读写分离的默认连接)// 或启用数据同步的默认与写入连接(数据同步改为在 AccessorBatchExecutor 底层实现) if (dbContextAccessor.IsWritingConnectionString()) // || dbContextAccessor.CurrentTenant.DataSynchronization { aspects = dbContextAccessor.GetService <IServicesManager <IMigrateAccessorAspect> >(); aspects.ForEach(aspect => { if (aspect.Enabled) { aspect.PreProcess(dbContextAccessor); // 前置处理数据迁移 } }); } // 结构迁移支持写入连接(包括未启用读写分离的默认连接)或启用结构同步的默认与写入连接 if (dbContextAccessor.IsWritingConnectionString() || dbContextAccessor.CurrentTenant.StructureSynchronization) { migrateStructureAction.Invoke(); } if (aspects.IsNotNull()) { aspects.ForEach(aspect => { if (aspect.Enabled) { aspect.PostProcess(dbContextAccessor); // 后置处理数据迁移 } }); } }
protected virtual async Task MigrateCoreAsync(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor, CancellationToken cancellationToken) { var lastModel = ResolvePersistentModel(dbContextAccessor); if (lastModel.IsNotNull()) { // 对比差异 var modelDiffer = dbContextAccessor.GetService <IMigrationsModelDiffer>(); var differences = modelDiffer.GetDifferences(lastModel, dbContextAccessor.Model); if (differences.IsNotEmpty()) { AddMigration(dbContextAccessor); await MigrateAspectServicesAsync(dbContextAccessor, () => { // 执行差异迁移 ExecuteMigrationCommands(dbContextAccessor, differences); }, cancellationToken).ConfigureAwait(); } } else { await MigrateAspectServicesAsync(dbContextAccessor, async() => { // 初始化整体迁移 await dbContextAccessor.Database.MigrateAsync().ConfigureAwait(); AddMigration(dbContextAccessor); }, cancellationToken).ConfigureAwait(); } }
protected virtual void MigrateCore(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor) { var lastModel = ResolvePersistentModel(dbContextAccessor); if (lastModel.IsNotNull()) { // 对比差异 var modelDiffer = dbContextAccessor.GetService <IMigrationsModelDiffer>(); var differences = modelDiffer.GetDifferences(lastModel, dbContextAccessor.Model); if (differences.IsNotEmpty()) { AddMigration(dbContextAccessor); // 执行差异迁移 MigrateAspectServices(dbContextAccessor, () => ExecuteMigrationCommands(dbContextAccessor, differences)); } } else { // 数据库整体迁移 MigrateAspectServices(dbContextAccessor, () => { dbContextAccessor.Database.Migrate(); AddMigration(dbContextAccessor); }); } }
protected virtual void ExecuteMigrationCommands(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor, IReadOnlyList <MigrationOperation> operationDifferences) { //var rawSqlCommandBuilder = dbContextAccessor.GetService<IRawSqlCommandBuilder>(); var migrationsSqlGenerator = dbContextAccessor.GetService <IMigrationsSqlGenerator>(); var migrationCommandExecutor = dbContextAccessor.GetService <IMigrationCommandExecutor>(); var connection = dbContextAccessor.GetService <IRelationalConnection>(); //var historyRepository = dbContextAccessor.GetService<IHistoryRepository>(); //var insertCommand = rawSqlCommandBuilder.Build(historyRepository.GetInsertScript(new HistoryRow(migration.GetId(), ProductInfo.GetVersion()))); // 过滤已迁移的操作集合(如历史分表迁移) operationDifferences = FilterMigratedOperations(dbContextAccessor.TabulationsManager, operationDifferences); if (operationDifferences.IsNull()) { return; } // 按表操作为最高优先级排序 operationDifferences = operationDifferences.OrderByTableOperation(); // 生成操作差异的迁移命令集合(如数据库不支持的迁移操作命令) var differenceCommands = migrationsSqlGenerator.Generate(operationDifferences, dbContextAccessor.Model); //.Concat(new[] { new MigrationCommand(insertCommand, _currentContext.Context, _commandLogger) }) if (differenceCommands.Count <= 0) { return; } // 过滤已执行的迁移命令集合 var executeCommands = ExecutionValidator.FilterExecuted(dbContextAccessor, differenceCommands); if (executeCommands.Count <= 0) { return; } ExtensionSettings.Preference.RunLocker(() => { migrationCommandExecutor.ExecuteNonQuery(executeCommands, connection); ExecutionValidator.SaveExecuted(dbContextAccessor); }); }
protected override void PostProcessCore(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor) { (var adds, var updates) = GetAddsOrUpdates(dbContextAccessor); if (adds.IsNotNull() || updates.IsNotNull()) { var notification = new TabulationNotification <TTabulation>(); notification.Adds = adds; notification.Updates = updates; var mediator = dbContextAccessor.GetService <IMediator>(); mediator.Publish(notification).ConfigureAwaitCompleted(); } }
protected virtual void AddMigration (DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor) { if (!dbContextAccessor.IsWritingConnectionString()) { return; } (var body, var hash) = CreateModelSnapshot(dbContextAccessor, out var typeName); dbContextAccessor.MigrationsManager.TryAdd(p => p.ModelHash == hash, () => { var identifierGenerator = (IDataStoreIdentificationGenerator <TGenId>)dbContextAccessor .GetService <IStoreIdentificationGenerator>(); var migration = ObjectExtensions.EnsureCreate <TMigration>(); migration.Id = identifierGenerator.GenerateMigrationId(); migration.PopulateCreation(identifierGenerator.Clock); migration.AccessorName = dbContextAccessor.CurrentType.GetDisplayNameWithNamespace(); migration.ModelSnapshotName = typeName; migration.ModelBody = body; migration.ModelHash = hash; return(migration); }, addedPost => { if (!dbContextAccessor.RequiredSaveChanges) { dbContextAccessor.RequiredSaveChanges = true; } // 移除当前缓存 var cacheKey = DbContextAccessorHelper.GetMigrationCacheKey(dbContextAccessor); MemoryCache.Remove(cacheKey); // 发送迁移通知 var mediator = dbContextAccessor.GetService <IMediator>(); mediator.Publish(new MigrationNotification <TMigration> { Migration = addedPost.Entity }) .ConfigureAwaitCompleted(); }); }
protected override async Task PostProcessCoreAsync(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor, CancellationToken cancellationToken = default) { (var adds, var updates) = GetAddsOrUpdates(dbContextAccessor, cancellationToken); if (adds.IsNotNull() || updates.IsNotNull()) { var notification = new TabulationNotification <TTabulation>(); notification.Adds = adds; notification.Updates = updates; var mediator = dbContextAccessor.GetService <IMediator>(); await mediator.Publish(notification, cancellationToken).ConfigureAwait(); } }
protected override void PreProcessCore(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor) { var entityEntries = GetEntityEntries(dbContextAccessor.ChangeTracker); if (entityEntries.IsEmpty()) { return; } var dictionary = GetAdds(dbContextAccessor, entityEntries); if (dictionary.IsNotNull()) { var mediator = dbContextAccessor.GetService <IMediator>(); mediator.Publish(new AuditNotification <TAudit, TAuditProperty>(dictionary)).ConfigureAwaitCompleted(); } }
protected override async Task PreProcessCoreAsync(DataDbContextAccessor <TAudit, TAuditProperty, TMigration, TTabulation, TTenant, TGenId, TIncremId, TCreatedBy> dbContextAccessor, CancellationToken cancellationToken = default) { var entityEntries = GetEntityEntries(dbContextAccessor.ChangeTracker); if (entityEntries.IsEmpty()) { return; } var dictionary = GetAdds(dbContextAccessor, entityEntries); if (dictionary.IsNotNull()) { var mediator = dbContextAccessor.GetService <IMediator>(); await mediator.Publish(new AuditNotification <TAudit, TAuditProperty>(dictionary), cancellationToken).ConfigureAwait(); } }