65.9K
CodeProject 正在变化。 阅读更多。
Home

EF Core 5 .NET 5 中的数据迁移:在独立库和自动部署中

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.50/5 (2投票s)

2021 年 2 月 15 日

CPOL

7分钟阅读

viewsIcon

14030

如何在 .NET 5 中创建 Entity Framework Core 5 数据迁移

我一直在考虑写这个主题一段时间了。我过去曾用 EF 数据迁移做过一个项目,但事情已经发生了变化,它的库依赖关系也发生了变化。现在,我将在 .NET 5 项目和 EF Core 5 (5.0.3) 中进行操作。

1. 引言

这篇博文的主要思想是,您将使用 Entity Framework 编写一个 Web 应用程序,并且不仅如此,您还希望项目附带一个数据迁移计划。当您编写应用程序时,数据库可能会随着时间的推移而演变,并且您希望在活动的生产环境中平滑、逐步地迁移数据库。这就是 EF 数据迁移发挥作用的地方。本文将通过一系列步骤带您完成此操作。为了清晰地阐述核心问题——数据迁移,我们将跳过所有其他编码方面,例如配置、编码标准、验证等,甚至包括实体框架建模。

2. 前提条件

Microsoft 允许使用 Visual Studio IDE 模板或使用 dotnet 命令行 (CLI) 界面创建项目。在本文中,我们将使用 dotnet CLI 创建项目。此外,我们将使用 Visual Studio Code 而不是 Visual Studio IDE,但其使用将仅限于编辑文件和浏览项目文件夹。所有应用程序的构建和运行都将通过 dotnet CLI 命令完成。以下是需要满足的一些前提条件:

  • 在此处下载并安装 Visual Studio Code。
  • 运行 Visual Studio Code,并安装来自 OmniSharp 的 C# 扩展。要安装扩展,请单击左侧面板中的图标,或单击菜单 视图 --> 扩展
  • 在此处下载并安装 dotnet 5 SDSK,您可以下载任何 SDK 版本 v5.0.0 或更高版本。如果您使用的是 Windows 操作系统,请确保已将安装目录包含在您的计算机系统 PATH 中。
  • 确保您有一个已启用 Windows 身份验证的 MS SQL Server 本地实例。

2. 使用 Dotnet CLI 创建解决方案和项目骨架

我们将创建一个包含两个项目的解决方案,主项目将从空 Web 模板生成,另一个项目是库项目,其中包含我们的数据库模型、上下文,以及稍后我们的迁移文件。在这里,我们将通过命令行提示符使用 dotnet CLI 来完成此操作,或者您可以从 Visual Studio Code 中打开终端。

  • 创建一个目录用于我们的解决方案 'EFCoreMigration',并进入该目录
    mkdir EFCoreMigration
    
    cd EFCoreMigration
  • 运行 dotnet 命令创建一个新的解决方案文件
    dotnet new sln

    这将创建一个以当前目录命名的解决方案文件,或者您可以使用参数 -n 指定解决方案文件的名称。

     dotnet new sln -n EFCoreMigration
  • 创建两个项目,一个用于 WebApp,类型为 web;另一个用于 DataAccess,类型为 classlib
    dotnet new web -o WebApp
    
    dotnet new classlib -o DataAccess

    要查看所有可用的项目模板,您可以使用以下命令列出它们:

     dotnet new -l
  • 将这两个项目添加到解决方案中
    dotnet sln add WebApp
    
    dotnet sln add DataAccess

    注意,如果您不指定解决方案名称,它将使用默认名称,即当前目录的名称。完整的命令可以如下所示:

    dotnet sln [solution name] add  WebApp

    或者您也可以指定项目文件的完整路径,例如:

    dotnet sln [solution name] add  WebApp\WebApp.csproj
  • WebApp 项目中添加对 DataAccess 项目的引用
    dotnet add WebApp reference DataAccess

    或者您也可以指定项目文件的完整路径:

    dotnet add WebApp\WebApp.csproj reference DataAccess\DataAccess.csproj 

3. 在 DataAcess 中创建模型和数据上下文

在这里,我们使用 Entity Framework 的代码优先方法。使用了非常基础的模型。

  • 在 Visual Studio Code 中,打开 DataAccess 目录,并将 Class1.cs 重命名为 Book.cs,然后键入以下代码:
    using System;
    
    namespace DataAccess
    {
        public class Book
        {
            public int Id { get; set; }
            public string Name { get; set; }
    
            public string Description {get;set;}
        }
    }
  • 在终端中,转到 DataAccess 目录,并添加 Microsoft.EntityFrameworkCore 包(版本 5.0.3)。
    cd DataAccess 
    
    dotnet new package Microsoft.EntityFrameworkCore -v 5.0.3 
  • 在 Visual Studio Code 中,在 DataAccess 项目中创建 DataContext.cs
    using System;
    using Microsoft.EntityFrameworkCore;
    namespace DataAccess
    {
        public class DataContext: DbContext
        {
            public DbSet<Book> Books { get; set; }
    
            public DataContext(DbContextOptions options) : base(options)
            {           
            }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                //Can add constraint, index, check, data type, and even data seed
            } 
        }
    }
  • 请务必保存所有更改,并在终端中键入以编译 DataAccess 项目,以确保其成功构建。
    dotnet build

4. 在 WebApp 中初始化数据库

  • 在终端中,转到 WebApp 目录,并添加 Microsoft.EntityFrameworkCore.SqlServer(版本 5.0.3)。此步骤取决于您使用的数据库服务器;如果您使用的不是 MS SQL Server,请查找适合您数据库服务器的提供程序包。
    dotnet new package Microsoft.EntityFrameworkCore.Sqlserver -v 5.0.3 
  • 在 Visual Studio Code 中,打开 WebApp 目录,并编辑 Startup.cs。在 ConfigureServices 部分添加 DB 上下文。
     using Microsoft.EntityFrameworkCore;
    .......
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<DataAccess.DataContext>(options =>
                    options.UseSqlServer(
              "Server=localhost;Database=EFCoreMigration;Trusted_Connection=True;"));
            }

    UseSqlServerMicrosoft.EntityFrameworkCore.SqlServer 中的一个扩展方法,要使用它,您需要在顶部添加 using Microsoft.EntityFrameworkCore。该代码将使用登录用户账户连接到 MS SQL Server 的本地实例,并创建一个 EFCoreMigration 数据库。

  • 此外,在 Startup.csConfigure 方法中添加一个 DataContext,并在执行数据库相关中间件之前确保数据库已创建,方法是在它们前面放置 Database.EnsureCreated()
            public void Configure(
                IApplicationBuilder app, 
                IWebHostEnvironment env, 
                DataAccess.DataContext dataContext)
            {
                dataContext.Database.EnsureCreated();
  • 请务必保存所有更改。在终端中,转到 WebApp 目录并键入:
    dotnet run
  • 通过在浏览器中运行服务正在监听的端口(例如,在我的机器上是 https://:5000 和 https://:5001)来检查应用程序是否正在工作。要取消服务,请按 + c
  • 通过检查 MS SQL Server 的本地实例中是否存在 EFCoreMigration 数据库(例如,使用 Microsoft Server Management Studio)来验证数据库是否已实例化。

  • 我没有展示如何使用 DataContext。通常,要使用 DataContext,您只需在控制器构造函数中添加 DataContext 并将其分配给控制器中的一个变量。之后,您可以在控制器中的任何位置使用它。由于此项目只是一个基础的 Web 应用程序,并且没有配置 WebAPI、MVC、Razor 或 Blazor 中间件和终结点,因此您可以通过调用中间件中传递的 HttpContext 对象来获取在服务中注册的 DataContext。以下是示例,请参阅 context.RequestServices.GetService<DataAccess.DataContract>()。您可以重新运行应用程序,然后在浏览器中检查,现在它将显示书籍的数量。请注意,您不能使用传递给 Configure 方法的 DataContext,因为该对象是在中间件构建时传递的,并且早已被释放。

            public void Configure(
                IApplicationBuilder app, 
                IWebHostEnvironment env, 
                DataAccess.DataContext dataContext)
            {
                dataContext.Database.EnsureCreated();
    
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();            
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGet("/", async context =>
                    {                    
                        using var dataContext = context.RequestServices
                            .GetService<DataAccess.DataContext>();
                        await context.Response.WriteAsync(
                            $"Book Count : {dataContext.Books.Count()}");
                    });
                });
            }

5. 添加数据迁移功能

到目前为止,我们已经在代码中使用了 Entity Framework,但没有使用数据迁移功能。在大多数项目中,数据库可能会随着时间的推移而演变,因此我们可能需要制定一个随时间更改数据库的策略。Entity Framework Core 具有数据迁移功能,以下是其中一种方法。

  • 首先,我们需要将 EF 工具链安装到 dotnet 命令中。在终端键入:
    dotnet tool install --global dotnet-ef --version 5.0.3

    这将允许我们运行 dotnet ef 命令。

  • Microsoft.EntityFrameworkCore.Design 添加到 DataAccess 项目。在终端中,转到 DataAccess 目录,然后键入:
    dotnet add Microsoft.EntityFrameworkCore.Design -v 5.0.3
  • 在 Visual Studio Code 中,转到 DataAccess 目录,并创建 DataContextFactory.cs
    using System;
    using Microsoft.EntityFrameworkCore.Design;
    using Microsoft.EntityFrameworkCore;
    
    namespace DataAccess
    {
        public class DataContextFactory : IDesignTimeDbContextFactory<DataContext>
        {
            public DataContext CreateDbContext(string[] args)
            {
                var builder = new DbContextOptionsBuilder<DataContext>();
                //this code will be never executed in runtime only in design time
                builder.UseSqlServer(
             "Server=localhost;Database=EFCoreMigration;Trusted_Connection=True;");
                return new DataContext(builder.Options);
            }
        }
    }
  • 在终端中,转到 DataAccess 目录,键入:
    dotnet ef migrations add InitialSchema

    这将创建一个包含三个文件的 Migrations 目录:

    • [yyyyMMddHHmmss]_InitialSchema.cs
    • [yyyyMMddHHmmss]_InitialSchema.Design.cs
    • DataContextModelSnapshot.cs

    InitialSchema 包含两个方法:UpDownUp 在将迁移应用于数据库时执行,Down 在从数据库中删除迁移时执行。DataContextModelSnapshot 包含在将迁移应用于最新迁移时数据库模型的快照。因此,如果添加或删除了新的迁移,DataContextModelSnapshot.cs 将会被覆盖。

  • 迁移功能能够在运行时应用数据库更改,方法是在 Startup.cs 中进行设置。在 Visual Studio Code 中,打开 WebApp 目录,并编辑 Startup.cs。将 dataContext.Database.EnsureCreate() 更改为 dataContext.Database.Migrate()
  • 删除之前创建的 EFCoreMigration 数据库。请务必保存所有更改,然后转到终端并运行 Web 应用程序。

    dotnet run
  • 成功运行应用程序后,请检查 EFCoreMigration 数据库。数据库将拥有一个名为 dbo.__EFMigrationsHistory 的表,其中包含列:MigrationIdProductVersionProductVersion 列供 Entity Framework 内部使用,并反映 EntityFrameworkCore 版本,而 MigrationId 的值格式为 [yyyyMMddHHmmss]_[Migration name]。

6. 修改数据库模型

启用数据迁移后,下一个问题是如何处理数据库模型更改。当然,数据库模型更改的范围很广,并非所有更改的复杂程度都相同。但是,对于常见的更改场景,以下过程应该足够了。

  • 可以对数据模型进行更改,但请注意不要进行破坏性更改。
  • 可以在 DataContextOnModelCreating 方法中进行更改。
  • 在终端中,转到 DataAccess 目录,键入:
    dotnet ef migrations add [Your Own migration name]
  • 照常部署,Startup.cs 中的 Migrate 方法将自动将迁移应用于最新更改。
  • 如果您想回滚上次迁移,请键入:
    dotnet ef migrations remove

    之后,照常部署。

历史

  • 2021 年 2 月 15 日:初始版本
© . All rights reserved.