美文网首页程序员
基于非源码的EFCore数据库迁移

基于非源码的EFCore数据库迁移

作者: voxer | 来源:发表于2018-03-06 11:40 被阅读54次

EFCore不再像EF6.x那样支持代码级别的完全自动的数据库迁移。不过EFCore提供了很方便的通过命令的方式来实现数据库的模型同步。
迁移方式主要是二种,基于Visual Studio带的包管理器的控制台和基于命令行的dotnet ef命令。前提是执行命令都需要有项目的源码,这个是有弊端的,我们一般开发项目发布到生产环境,开发者不允许直接访问,我们也不应该把源码发布到生产环境。
本文主要尝试只有dotnet publish发布的dll的基础下实现数据库的迁移。

1. 创建一个ASP Net Core的测试项目

我这里用的是Visual Studio 2017,创建一个Web API项目,连接本地的MySQL数据库。需要添加几个Nuget 包

<ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" />
    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.0.1" />
  </ItemGroup>

还有一个是需要右键项目编辑csproj文件,然后添加一个DotNetCliToolReference,否则执行dotnet ef会报错

image.png
代码的修改也很简单,增加2个类User和DataContext:
public class DataContext : DbContext
 {
        public DataContext(DbContextOptions<DataContext> options)
            : base(options)
        {
        }
       
        public DbSet<User> User { get; set; }
  }
 public class User
  {
        public string Id { get; set; }
        public string Name { get; set; }
        //一开始先注释调Age这个属性,用于测试模型变化后的数据库迁移
        //public string Age { get; set; }
  }

在Startup里添加数据库连接的代码:

public void ConfigureServices(IServiceCollection services)
    {
            services.AddMvc();
            var connection = "Server=localhost;Port=3306;Database=TestMySql; User=root;Password=123456;Charset=utf8";
            services.AddDbContextPool<DataContext>(options => options.UseMySql(connection));
    }

2. 定义初始化迁移

这个操作还是在源码目录下执行的,这个操作是定义数据库模型初始化迁移文件的,不能脱离源码。

 D:\MigrationsSample\MigrationsSample> dotnet ef migrations add InitialCreate
Done. To undo this action, use 'ef migrations remove'

执行后,在源码目录会创建一个Mirgrations目录:


image.png

再执行dotnet publish命令:

PS D:\work\temp\MigrationsSample\MigrationsSample> dotnet publish
用于 .NET Core 的 Microsoft (R) 生成引擎版本 15.5.180.51428
版权所有(C) Microsoft Corporation。保留所有权利。

  Restore completed in 94.18 ms for D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj.
  Restore completed in 113.93 ms for D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj.
  Restore completed in 126.06 ms for D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj.
  MigrationsSample -> D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.dll
  MigrationsSample -> D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\publish\

3. 迁移应用到数据库

接下来我们把publish的目录所有文件拷贝到另外一个目录d:\temp\publish,模拟一次发布过程。
我们需要在这个目录下执行数据库迁移。
需要额外在这个目录下创建一个bat文件,内容如下:

set EfMigrationsNamespace=%1
set EfMigrationsDllName=%1.dll
set EfMigrationsDllDepsJson=%1.deps.json
set DllDir=%cd%
set PathToNuGetPackages=%USERPROFILE%\.nuget\packages
set PathToEfDll=%PathToNuGetPackages%\microsoft.entityframeworkcore.tools\2.0.0\tools\netcoreapp2.0\ef.dll

dotnet exec --depsfile .\%EfMigrationsDllDepsJson% --additionalprobingpath %PathToNuGetPackages% %PathToEfDll% database update --assembly .\%EfMigrationsDllName% --startup-assembly .\%EfMigrationsDllName% --data-dir %DllDir% --verbose --root-namespace %EfMigrationsNamespace%  

执行这个bat+dll的文件名

 ./databaseupdate MigrationsSample
image.png

执行成功后,我们去数据库查看一下,可以看到数据库和相应的表都创建完成。


image.png
4. 修改表模型后再次尝试数据库迁移

上个步骤后,数据库里的user表有2个字段,接下来我们修改一下User.cs,放开注释,相当于增加了一个字段Age:

public class User
  {
        public string Id { get; set; }
        public string Name { get; set; }
        //一开始先注释调Age这个属性,用于测试模型变化后的数据库迁移
        public string Age { get; set; }
  }

然后再执行定义迁移和publish

注意这里迁移的名称要变了,不能再叫InitialCreate,我这里叫update1

 D:\MigrationsSample\MigrationsSample> dotnet ef migrations add update1
Done. To undo this action, use 'ef migrations remove'

PS D:\MigrationsSample\MigrationsSample> dotnet publish
用于 .NET Core 的 Microsoft (R) 生成引擎版本 15.5.180.51428
版权所有(C) Microsoft Corporation。保留所有权利。

  Restore completed in 87.98 ms for D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj.
  Restore completed in 116.2 ms for D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj.
  Restore completed in 126.37 ms for D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj.
  MigrationsSample -> D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.dll
  MigrationsSample -> D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\publish\

再次发布到d:\temp\publish目录,在这个目录下再次执行bat文件,执行完我们去查看数据库,发现user表的字段变成3个了,表示数据库迁移成功。

image.png

4.分析和总结

实现基于dll的数据库迁移核心就是那个bat文件,这个文件的来源是参考这里
实际上,你可以在dotnet ef database update后增加一个-v参数就可以发现这个命令分2个部分,第一步部分是build,第二个部分就说类似那个bat文件里的dotnet exec:

PS D:\MigrationsSample\MigrationsSample> dotnet ef database update -v
......
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\liuyin\AppData\Local\Temp\tmp71D2.tmp /verbosity:quiet /nologo D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj
dotnet build D:\MigrationsSample\MigrationsSample\MigrationsSample.csproj /verbosity:quiet /nologo

已成功生成。
    0 个警告
    0 个错误

已用时间 00:00:04.76
dotnet exec --depsfile D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.deps.json --additionalprobingpath C:\Users\liuyin\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.runtimeconfig.json "C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.entityframeworkcore.tools.dotnet\2.0.1\tools\netcoreapp2.0\ef.dll" database update --assembly D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.dll --startup-assembly D:\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.dll --project-dir D:\MigrationsSample\MigrationsSample\ --verbose --root-namespace MigrationsSample
Using assembly 'MigrationsSample'.
Using startup assembly 'MigrationsSample'.
......

最后再提醒一下,如果是基于协同的开发,那个自动生成的Mirgrations目录最后和源码一起提交到源码管理服务器上,确保不会删除和遗漏。
所有源码可以从git上下载。

相关文章

  • 基于非源码的EFCore数据库迁移

    EFCore不再像EF6.x那样支持代码级别的完全自动的数据库迁移。不过EFCore提供了很方便的通过命令的方式来...

  • 2020-03-28 EFCore 的教程 -- 提纲2

    EFCore入门配置数据库连接字符串EFCore 如何自动获知数据库主键将项目的变动更新到数据库安装 EFCore...

  • nest.js 集成数据迁移方案 sequelize、umzug

    ORM采用sequelize迁移采用umzug数据库基于mysql不说废话,上干货。 数据库迁移配置 databa...

  • Spring Boot进阶 之 DB Migration

    本文的示例代码参考FlywayDemo 目录 开始 迁移 部署 开始 本文数据库迁移基于Flyway 类型方案还有...

  • Android 数据库

    sqlite详解 sqlite升级,增加字段的语句 数据库框架对比和源码分析 数据库的优化 数据库数据迁移问题

  • 阿里GitHub

    阿里Git数据库相关工具:愚公,数据库迁移工具cannal,row模式binlog解析otter,基于数据库增量日...

  • 2018-04-15 迁移学习的度量准则

    迁移学习的方法主要包括:基于样本的迁移,基于特征的迁移,基于模型的迁移和基于关系的迁移。 “迁移学习的总体思路可以...

  • Android基础(10)数据库

    1)如何导入外部数据库?2)数据库数据迁移问题3)数据库框架对比和源码分析 GreenDao、Realm4)sql...

  • 0—flyway介绍

    Flyway是一个开源的数据库迁移工具。 它基于只有6个基本命令: 迁移, 清理, 信息, 验证, 基准和 修复。...

  • Kettle (6) - 跨数据库数据迁移几个细节

    本篇基于假设的场景:将 SQL Server 数据库的表迁移到 MySQL 数据库。之前写过一篇从 SQLite ...

网友评论

    本文标题:基于非源码的EFCore数据库迁移

    本文链接:https://www.haomeiwen.com/subject/aqdlfftx.html