HTML5技术

使用 Entity Framework Core 时,通过代码自动 Migration - JRoger

字号+ 作者:H5之家 来源:H5之家 2016-09-04 17:00 我要评论( )

一 介绍 在使用 Entity Framework Core (下面就叫 EF Core 吧)进行开发时,如果模型有变动,我们要在用 EF Core 提供的命令行工具进行手工迁移,然后再运行程序。但是为了效率,我想能不能在程序的入口处进行 Migration 呢?从个人经验来说应该是可以,因为 E

一 介绍

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

二 分析

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

    第一步:生成 Migration 文件;

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

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

  

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

  在使用 EF Core 的时候,我们都要通过继承 DbContext 来编写自己的 DbContext 子类。在 DbContext 类中我们找到了一个 Database 属性。如下图所示:

  

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

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

AutoMigration 2 { IServiceProvider _serviceProvider; 4 private InformationDbContext _context; AutoMigration(IServiceProvider serviceProvider) 7 { 8 _serviceProvider = serviceProvider; 9 _context = serviceProvider.GetService<InformationDbContext>(); 10 } Migrator() 13 { ); 15 if (!Directory.Exists(path)) 16 { 17 Directory.CreateDirectory(path); 18 } { 21 Directory.GetFiles(path).ToList().ForEach(File.Delete); 22 } (_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))); projectDir = Path.Combine(path, ); 33 var migrationAssembly = new MigrationsAssembly(new CurrentDbContext(_context), _context.Options, new MigrationsIdGenerator()); , BindingFlags.Instance | BindingFlags.NonPublic).SetValue(scaffolder, migrationAssembly); readonlyDic = new ReadOnlyDictionary<string,TypeInfo>(new Dictionary<string, TypeInfo>()); , BindingFlags.NonPublic | BindingFlags.Instance).SetValue(migrationAssembly, new LazyRef<IReadOnlyDictionary<string, TypeInfo>>(readonlyDic)); , ); 39 40 scaffolder.Save(projectDir, migration, path); 另外一种保存方式 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, } (_context = (InformationDbContext)_serviceProvider.GetService<IDbContext>()) 52 { 53 _context.Database.Migrate(); 54 } 55 } 56 }

  另外一个注意点:我们需要指定一下迁移文件所在项目。

1 services.AddDbContext<InformationDbContext>(opt => 2 { ]; 4 opt.UseSqlServer(connectionString, optionBuilder => 5 { ); 7 }); 8 });

 

三 总结

  通过上面的分析可以知道,其实我们就是把 CLI 的两个命令通过代码实现了一下。在 Startup 文件中进行调用即可。为什么想这么干?因为在实际开发的时候,来回切换窗口心里觉得不爽了呗。:)

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 总结一下公司项目使用各种较新的前端技术和 Api 的一些经验。 - B1ncer

    总结一下公司项目使用各种较新的前端技术和 Api 的一些经验。 - B1nc

    2016-09-02 17:00

  • 使用js制作一般网站首页图片轮播效果 - 骑猪敲代码

    使用js制作一般网站首页图片轮播效果 - 骑猪敲代码

    2016-08-30 16:00

  • 【高级功能】使用多媒体 - Luka.Ye

    【高级功能】使用多媒体 - Luka.Ye

    2016-08-27 11:00

  • 【高级功能】使用canvas元素(第一部分) - Luka.Ye

    【高级功能】使用canvas元素(第一部分) - Luka.Ye

    2016-08-27 10:00

网友点评