清洁架构下如何在Infrastructure层创建EF Core迁移?
清洁架构下EF Core迁移的实现方案
核心思路
清洁架构要求Web层(外层)不直接依赖数据访问相关包,所有数据访问逻辑集中在Infrastructure层(最外层的基础设施实现)。要解决迁移问题,关键是让EF Core工具能在不污染Web层的前提下,在Infrastructure层创建UsersDbContext实例——使用EF Core的IDesignTimeDbContextFactory接口是标准且合规的方案。
具体步骤
1. 在Infrastructure层添加必要的NuGet包
Infrastructure层作为数据访问实现层,完全可以引用EF Core相关工具包,这符合清洁架构的依赖规则:
dotnet add src/BFF/BFF.Infrastructure/BFF.Infrastructure.csproj package Microsoft.EntityFrameworkCore.Design
2. 实现设计时DbContext工厂
在Infrastructure层新建一个类,实现IDesignTimeDbContextFactory<UsersDbContext>,用于在迁移时手动创建UsersDbContext实例(绕过依赖注入,直接加载配置并初始化上下文):
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using System.IO; namespace BFF.Infrastructure.Data { public class UsersDbContextDesignTimeFactory : IDesignTimeDbContextFactory<UsersDbContext> { public UsersDbContext CreateDbContext(string[] args) { // 加载Web项目的配置文件(保持配置集中管理,也可以用Infrastructure自己的配置) var configBuilder = new ConfigurationBuilder() .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../BFF.Web")) .AddJsonFile("appsettings.json") .AddJsonFile("appsettings.Development.json", optional: true); var configuration = configBuilder.Build(); var connectionString = configuration.GetConnectionString("UsersConnection"); var options = new DbContextOptionsBuilder<UsersDbContext>() .UseSqlServer(connectionString) // 根据你的数据库类型调整(如UseNpgsql、UseSqlite) .Options; return new UsersDbContext(options); } } }
注意:确保
UsersDbContext有接收DbContextOptions<UsersDbContext>参数的构造函数(这是EF Core的标准构造方式)。
3. 执行迁移命令
使用以下命令创建迁移,指定Infrastructure为目标项目,Web为启动项目(Web层无需引用任何EF Core工具包):
dotnet ef migrations add UsersMig --context UsersDbContext --project src/BFF/BFF.Infrastructure/BFF.Infrastructure.csproj --startup-project src/BFF/BFF.Web/BFF.Web.csproj
为什么之前的命令会报错?
- 直接以Web为启动项目执行迁移:EF工具需要
Microsoft.EntityFrameworkCore.Design包来生成迁移,但你不想让Web层依赖此包,因此报错。 - 以Infrastructure为启动项目执行迁移:类库项目没有宿主环境,EF工具无法通过依赖注入解析
UsersDbContext的构造参数(如IConfiguration),导致无法创建实例。
而设计时工厂的作用就是告诉EF工具:不用依赖注入,直接用这个工厂方法创建DbContext,完美规避了上述两个问题,同时严格遵守清洁架构的依赖规则。
内容的提问来源于stack exchange,提问作者Szyszka947
相关产品推荐
相关产品推荐

