예제 #1
0
        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); // 后置处理数据迁移
                    }
                });
            }
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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);
                });
            }
        }
예제 #4
0
        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();
            }
        }
예제 #6
0
        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();
            }
        }