如何在具有 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);
我一直在尝试在线学习 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);