.NET 6控制台程序批量执行实体迁移类的合适设计模式?
.NET 6控制台程序自动执行数据迁移的DI实现方案
1. 定义统一迁移接口
先创建通用接口,让所有迁移类遵循同一执行标准:
public interface IDataMigrator { // 异步方法更适配数据迁移场景,同步需求可改为void Migrate() Task MigrateAsync(); }
2. 实现实体迁移类
每个实体类型对应一个实现类,按需注入依赖(如数据库上下文、配置等):
public class UserDataMigrator : IDataMigrator { private readonly SourceDbContext _sourceDb; private readonly TargetDbContext _targetDb; public UserDataMigrator(SourceDbContext sourceDb, TargetDbContext targetDb) { _sourceDb = sourceDb; _targetDb = targetDb; } public async Task MigrateAsync() { // 编写用户数据的迁移逻辑 var users = await _sourceDb.Users.ToListAsync(); await _targetDb.Users.AddRangeAsync(users); await _targetDb.SaveChangesAsync(); } }
其他实体(如订单、商品)的迁移类依此模式实现即可。
3. 批量注册迁移类到DI容器
在Program.cs中利用DI的扫描功能,一次性注册所有实现了IDataMigrator的类:
var builder = Host.CreateDefaultBuilder(args); builder.ConfigureServices(services => { // 先注册依赖服务,比如数据库上下文 services.AddDbContext<SourceDbContext>(options => options.UseSqlServer("YourSourceConnectionString")); services.AddDbContext<TargetDbContext>(options => options.UseSqlServer("YourTargetConnectionString")); // 批量扫描并注册所有迁移类 services.Scan(scan => scan .FromAssemblyOf<IDataMigrator>() // 指定接口/实现类所在的程序集 .AddClasses(classes => classes.AssignableTo<IDataMigrator>()) .AsImplementedInterfaces() .WithTransientLifetime()); // 迁移场景用Transient生命周期足够 }); var host = builder.Build();
4. 自动执行所有迁移逻辑
从DI容器中获取所有迁移实例,遍历执行迁移方法:
// 获取所有已注册的迁移服务 var migrators = host.Services.GetServices<IDataMigrator>(); foreach (var migrator in migrators) { try { await migrator.MigrateAsync(); Console.WriteLine($"[{migrator.GetType().Name}] 迁移完成"); } catch (Exception ex) { Console.WriteLine($"[{migrator.GetType().Name}] 迁移失败: {ex.Message}"); // 可按需选择终止程序或继续执行其他迁移 // throw; } } await host.RunAsync();
新增实体迁移的扩展说明
- 新增的迁移类只要实现
IDataMigrator接口,且位于FromAssemblyOf指定的程序集内,DI会自动识别并注册,无需修改原有注册代码。 - 如果需要控制迁移顺序,可以自定义优先级属性:
[AttributeUsage(AttributeTargets.Class)] public class MigrationPriorityAttribute : Attribute { public int Order { get; set; } } // 在迁移类上标记优先级 [MigrationPriority(Order = 1)] public class UserDataMigrator : IDataMigrator { ... }
然后遍历前排序:
var orderedMigrators = migrators.OrderBy(m => m.GetType().GetCustomAttribute<MigrationPriorityAttribute>()?.Order ?? int.MaxValue); foreach (var migrator in orderedMigrators) { await migrator.MigrateAsync(); }
内容的提问来源于stack exchange,提问作者obautista
相关产品推荐
相关产品推荐

