目录
在.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代码,然后从OmniSharp安装C#扩展。要安装扩展程序,请单击左侧面板上的图标,或单击菜单查看->扩展程序。
- 从此处下载并安装dotnet 5 SDSK ,您可以下载任何SDK版本v5.0.0或更高版本。如果您使用的是Windows操作系统,请确保已安装的目录包含在计算机系统PATH中。
- 确保您具有启用了Windows身份验证的MS SQL Server的本地实例。
3.使用Dotnet CLI创建解决方案和项目框架
我们将创建一个包含两个项目的解决方案,主项目将通过一个空的Web模板生成,另一个项目是一个库项目,其中包含我们的数据库模型,上下文以及稍后的迁移文件。在这里,我们将通过命令提示符使用dotnet CLI命令执行此操作,或者您可以从Visual Studio Code打开终端
- 为我们的解决方案“EFCoreMigration”创建目录,然后移至该目录:
mkdir EFCoreMigration
cd EFCoreMigration
- 运行dotnet命令来创建一个新的解决方案文件:
dotnet new sln
这将使用当前目录的名称创建一个解决方案文件,或者您可以使用参数-n指定解决方案文件的名称:
dotnet new sln -n EFCoreMigration
- 创建两个项目,一个针对web 类型的WebApp,另一个针对classlib类型的DataAccess:
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
4.在DataAcess中创建模型和数据上下文
在这里,我们使用实体框架的代码优先方法。使用了非常基本的模型。
- 在Visual Studio代码中,打开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代码中,在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
5.在WebApp中启动数据库
- 在终端中,转到WebApp目录,然后添加Microsoft.EntityFrameworkCore.SqlServer(版本5.0.3)。此步骤取决于您使用的数据库服务器,如果使用的不是MS SQL服务器,则为数据库服务器找到合适的提供程序包。
dotnet new package Microsoft.EntityFrameworkCore.Sqlserver -v 5.0.3
- 在Visual Studio代码中,打开WebApp目录,然后编辑Startup.cs。在该ConfigureServices部分中添加数据库上下文。
using Microsoft.EntityFrameworkCore;
.......
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataAccess.DataContext>(options =>
options.UseSqlServer(
"Server=localhost;Database=EFCoreMigration;Trusted_Connection=True;"));
}
UseSqlServer是Microsoft.EntityFrameworkCore.SqlServer中的扩展方法,要使用它,您需要在顶部添加using Microsoft.EntityFrameworkCore。该代码将使用登录的用户帐户连接到MS SQL Server的本地实例,并创建一个EFCoreMigration数据库。
- 除此之外,在Startup.cs中添加一个DataContexttoConfigure方法,并通过Database.EnsureCreated()在它们之前执行数据库相关中间件来确保已创建数据库。
public void Configure(
IApplicationBuilder app,
IWebHostEnvironment env,
DataAccess.DataContext dataContext)
{
dataContext.Database.EnsureCreated();
- 确保保存所有更改。在终端中,转到WebApp目录并键入:
dotnet run
- 通过使用服务正在监听的端口运行浏览器来检查应用程序是否正常运行(例如,在我的机器中为http://localhost:5000 和https://localhost:5001)。要取消服务,请 单击+ c。
- 通过使用例如Microsoft Server Management Studio检查数据库是否存在于MS SQL Server的本地实例中来实例化EFCoreMigration数据库。
- 我没有显示的是如何使用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()}");
});
});
}
6.添加数据迁移功能
到目前为止,我们已经在代码中使用了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 有两个方法,Up和Down。当将迁移应用于数据库时,将执行Up;当从数据库中删除迁移时,将执行Down。如果迁移应用到最新的迁移,则DataContextModelSnapshot包含数据库模型的快照。因此,如果添加或删除了新的迁移,则DataContextModelSnapshot.cs将被覆盖。
- 迁移功能可以通过在Startup.cs中进行设置来即时应用数据库更改。在Visual Studio代码中,打开WebApp目录,然后编辑Startup.cs。更改dataContext.Database.EnsureCreate()为dataContext.Database.Migrate()。
- 删除EFCoreMigration以前创建的数据库。确保保存所有更改,然后转到终端并运行Web应用程序。
dotnet run
- 成功运行该应用程序后,请检查数据库EFCoreMigration。该数据库将有一个名为dbo.__EFMigrationsHistory的表,该表的列为:MigrationId和ProductVersion。ProductVersion列由实体框架在内部使用并反映EntityFrameworkCore版本,其MigrationId 值的格式为[yyyyMMddHHmmss] _ [迁移名称]。
7.更改数据库模型
启用数据迁移后,下一个问题是必须对数据库模型进行更改时该怎么做。当然,数据库模型的变化范围很大,而且并非所有变化都具有相同的复杂性。但是,对于常见的更改情况,以下过程应该足够了。
- 可以对数据模型进行更改,请注意不要进行重大更改。
- 可以对DataContext中的OnModelCreating方法进行更改。
- 在终端中,转到DataAccess目录,键入:
dotnet ef migrations add [Your Own migration name]
- 如通常部署一样,Startup.cs中的Migrate方法将自动将迁移应用于最新更改。
- 如果要回滚上一次迁移,请键入:
dotnet ef migrations remove
然后,像平常一样部署。
https://www.codeproject.com/Articles/5294835/EF-Core-5-Data-Migration-in-NET-5-in-a-Separate-Li