【问题标题】:How can I EFCore DB Context in an N-Tier architecture with an ASP.NET Core application?如何使用 ASP.NET Core 应用程序在 N 层架构中使用 EF Core DBContext?
【发布时间】:2019-10-23 16:50:14
【问题描述】:

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

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

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

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

想到的唯一解决方案是将上下文添加到“通用​​”项目中,但这感觉不是正确的做法?

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

【问题讨论】:

  • 我在两个项目中都添加了 EF。在我看来,这不是一个糟糕的设计。
  • @EKOlog 但是您的 dbContext 驻留在哪里?
  • @Prime By Design 在我的数据库项目中。
  • @PrimeByDesign 我不确定你所说的域和数据层分离是什么意思,因为 EF 是数据层,你在上面声明的任何其他东西都是域层,所以你真的只需要一个项目.
  • @AvinKavish 我将我的图层保存在单独的项目中,以便可以引用域/数据逻辑,而无需专门与 web api 对话。它可以被其他项目使用。

标签: c# asp.net-core .net-core entity-framework-core n-tier-architecture


【解决方案1】:

这个问题在架构方面可以忽略不计,但如果你真的担心将 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 - 您无需创建新项目,只需在域项目中使用相同的扩展类即可。

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

services.AddDomainDataServices();

这可以有效地在多个项目中重复使用。

【讨论】:

  • 不只是依赖关系,我想将上下文保留在数据层中。 API 层由域层分隔。
  • 您将通过这种方式使 DbContext 类和 EF 依赖项远离 API,因为在您的 API 中,您将仅引用 DI 层,该层将具有像 AddMyDataServices() 这样的抽象,而后者又封装了添加 EF 的东西。
  • 我认为选项 1 是我需要的。我现在就试试!
  • 选项 1 是一个很好的建议。我也这样做,但每个项目都负责自己的依赖项。
  • @WilliamXifaras 是的,这实际上取决于您需要多少可重用性和分离度。在可重用库的单独项目中这样做是很常见的。您可以看到许多示例,例如 Automapper 和 Automapper.DependencyInjection(我不记得 AM 是否真的这样做,但其他人肯定这样做)
【解决方案2】:

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

  • API(ASP.NET Core API - 参考服务)
  • 服务(业务逻辑 - 引用数据访问)
  • 数据访问(此处为 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);

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 当然,但是如果您有一个域层将数据层与 UI 层分开会发生什么?
    • 而且你需要在你的数据层暴露 DI 方法,否则仅仅引用数据层是不够的,因为你不能在你的 UI 中实际设置 DI 注入。至少这是我试图用我的回答来解释的。
    • @PrimeByDesign 同样适用。 EF 只进入数据层(或项目)。领域层将引用数据项目。这样,所有的数据库访问内容都暴露给领域层,但“存在”在数据层中。
    • @Kevingy 对不起,我知道 EF Stuff 只进入数据层,并且域会引用是肯定的。那不是我的问题。
    • @PrimeByDesign 是的,正是我的意思,你可以将依赖注入方法分离到一个单独的层来实现你想要的。这就是我试图在回答中解释的内容。这样做并不少见。
    猜你喜欢
    • 2022-01-08
    • 2016-05-26
    • 2019-03-22
    • 2018-09-22
    • 2021-11-23
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多