如何在具有 ASP.NET 核心应用程序的 N 层架构中使用 EF Core DBContext?

How can I EFCore DB Context in an N-Tier architecture with an ASP.NET Core application?

我一直在尝试在线学习 asp.net mvc 核心教程,我注意到在使用 entity framework 时,您可以在应用程序启动文件的 ConfigureServices 中启用它,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<MyContext>(cfg => cfg.UseSqlServer());
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

但是,如果我打算使用域层和数据层具有不同项目的 n 层架构怎么办?

所以我不会在我的 API 层中引用 EntityFramework 或 DBContext,因为它们会被域层分隔?

想到的唯一解决方案是将 Context 添加到 "Common" 项目,但感觉这不是正确的做法?

你们会如何解决这个问题?

这个问题在架构方面可以忽略不计,但如果你真的关心将 EF 依赖项分离到一个单独的项目中,那么你可以将依赖注入层全部分离到单独的项目中,并仅在多个项目中使用引用其他项目。

编辑: 我可能对此不够详细,所以这里是我的意思的一个例子。我假设您的 Example.Domain 有一些存储库引用了您的 EF YourDbContext

public class YourDomainRepository
{
    private readonly YourDbContext _context;

    public YourDomainRepository(YourDbContext context)
    {
        _context = context;
    }

    ...Other repository methods
}

您描述的问题是仅在 Example.Api 中引用 Example.Domain 是不够的,因为为了使 DI 工作,您需要将其添加到服务中,并且您需要添加 YourDomainRepository 和它所依赖的其他服务(如 YourDbContext),这又需要您引用 EF 库。

所以我尝试提出的方法是:

  • 选项 1 - 您为 DI 等常见内容创建另一个项目。该项目将包含如下功能:

    public static class YourDomainDIExtensions
    {
        public static void AddDomainDataServices(this IServiceCollection services)
        {
            services.AddDbContext<YourDbContext>(...);
            services.AddTransient<YourDomainRepository>();
        }
    }
    
  • 选项 2 - 您不创建新项目,只是在您的域项目中具有相同的扩展名 class。

无论哪种方式,这都会从您的 Example.API 中抽象出 EF 依赖项,您只需调用:

services.AddDomainDataServices();

它可以有效地跨多个项目重用。

您只需要 entity framework 在实际接触数据库的项目(即层)中。解决方案中的其他项目可以添加对封装entity framework项目的引用。例如:

这是一个简单的示例,但 Data 项目引用了 EF。 UI 项目引用了数据项目。在较大的项目中,我什至可能在数据层和 UI 层之间有一个 API 项目。在这些情况下,UI 项目不会引用数据或 API 项目,因为它完全是 UI。也就是说,UI 项目不会像简单示例那样有控制器。

我目前正在做的是在我的业务逻辑项目中创建一个扩展,它引用了封装 EF Core 的数据访问项目。 结构如下:

  • API(ASP.NET 核心 API - 参考服务)
  • 服务(业务逻辑 - 参考数据访问)
  • DataAccess(此处为 EF Core)

在我的服务项目中,我有这样的扩展:

public static class AppExtensions
{
    public static IServiceCollection SetUpAppDependencies(this IServiceCollection serviceCollection,
        string connectionString)
    {
        serviceCollection.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
        return serviceCollection;
    }
}

然后在 ConfigureServices 中我这样做:

// connectionString should come from KeyVault or Configuration
services.SetUpAppDependencies(connectionString);