使用 Entity Framework Core 时,经过代码自动 Migration 使用 Entity Framework Core 时,经过代码自动 Migration

使用 Entity Framework Core 时,经过代码自动 Migration

一 介绍

  在使用 Entity Framework Core (下面就叫 EF Core 吧)进行开发时,若是模型有变更,咱们要在用 EF Core 提供的命令行工具进行手工迁移,而后再运行程序。可是为了效率,我想能不能在程序的入口处进行 Migration 呢?从我的经验来讲应该是能够,由于 EF Tool 虽然提供了 CLI 可是它最终也是被程序解析这些命令。下面就开始分析,如何经过代码进行 Migration 。html

二 分析

  首先咱们要先了解,在使用 EF Core 的 CLI 时,要执行两个步骤:数据库

    第一步:生成 Migration 文件;ide

    第二步:更新变动项到数据库;函数

  既然是先生成 Migration 文件再更新,那么在 EF Core 里面必定有对应的模块作这件事情。下面咱们看一下 EF Core 项目的结构。从中咱们确实找到关于 Migration 的模块。在 Migrations/Design 目录的类名称上咱们能够看出来,它就是生成 Migration 文件的。这里先到这儿。工具

  

  找到了生成 Migration 文件的入口,咱们再来找一下如何经过代码将这些变动更新到数据库中。post

  在使用 EF Core 的时候,咱们都要经过继承 DbContext 来编写本身的 DbContext 子类。在 DbContext 类中咱们找到了一个 Database 属性。以下图所示:ui

  

  而后查看了 DatabaseFacde 这个类,并无发现执行迁移相关的函数。经过代码搜索,我在 RelationalDatabaseFacadeExtensions 这个类中有一个 Migration() 扩展方法。经过注释的解析,我也肯定了它就是执行 Migration 文件,并将变动更新到数据库。url

  这两个步骤对应的代码咱们都找到了,下面咱们就编写一段儿代码,完成自动将模型变动更新到数据库的功能。命令行

 1 public class AutoMigration
 2 {
 3     private readonly IServiceProvider _serviceProvider;
 4     private InformationDbContext _context;
 5 
 6     public AutoMigration(IServiceProvider serviceProvider)
 7     {
 8         _serviceProvider = serviceProvider;
 9         _context = serviceProvider.GetService<InformationDbContext>();
10     }
11 
12     public void Migrator()
13     {
14         var path = Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\Migrations\\");
15         if (!Directory.Exists(path))
16         {
17             Directory.CreateDirectory(path);
18         }
19         else
20         {
21             Directory.GetFiles(path).ToList().ForEach(File.Delete);
22         }
23 
24         using (_context)
25         {
26             var services = ((IInfrastructure<IServiceProvider>) _context).Instance;
27             var codeHelper = new CSharpHelper();
28             var scaffolder = ActivatorUtilities.CreateInstance<MigrationsScaffolder>(services,
29                 new CSharpMigrationsGenerator(codeHelper, new CSharpMigrationOperationGenerator(codeHelper),
30                     new CSharpSnapshotGenerator(codeHelper)));
31             
32             var projectDir = Path.Combine(path, "..\\");
33             var migrationAssembly = new MigrationsAssembly(new CurrentDbContext(_context), _context.Options, new MigrationsIdGenerator());
34             scaffolder.GetType().GetField("_migrationsAssembly", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(scaffolder, migrationAssembly);
35 
36             var readonlyDic = new ReadOnlyDictionary<string,TypeInfo>(new Dictionary<string, TypeInfo>());
37             migrationAssembly.GetType().GetField("_migrations", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(migrationAssembly, new LazyRef<IReadOnlyDictionary<string, TypeInfo>>(readonlyDic));
38             var migration = scaffolder.ScaffoldMigration("Information.Migrations", "Information");
39 
40             scaffolder.Save(projectDir, migration, path);
41 
42             //另一种保存方式
43             //File.WriteAllText($"Migrations\\{migration.MigrationId}{migration.FileExtension}", migration.MigrationCode);
44             //File.WriteAllText("Migrations\\" +
45             //    migration.MigrationId + ".Designer" + migration.FileExtension,
46             //    migration.MetadataCode);
47             //File.WriteAllText("Migrations\\" + migration.SnapshotName + migration.FileExtension,
48             //    migration.SnapshotCode);
49         }
50 
51         using(_context = (InformationDbContext)_serviceProvider.GetService<IDbContext>())
52         {
53             _context.Database.Migrate();
54         }
55     }
56 }

  另一个注意点:咱们须要指定一下迁移文件所在项目。3d

1 services.AddDbContext<InformationDbContext>(opt =>
2 {
3     var connectionString = configuration["ConnectionStrings:DefaultConnection"];
4     opt.UseSqlServer(connectionString, optionBuilder =>
5     {
6         optionBuilder.MigrationsAssembly("Information");
7     });
8 });

 

三 总结

  经过上面的分析能够知道,其实咱们就是把 CLI 的两个命令经过代码实现了一下。在 Startup 文件中进行调用便可。

原文连接:https://www.cnblogs.com/jRoger/p/entity-framework-core-auto-migration.html

相关文章
相关标签/搜索