首页 > 解决方案 > 如何配置 EF Core 连接上下文以解耦包依赖关系?

问题描述

我使用 Entity Framework Core 创建了一个库来处理持久性。它由针对 SQL Server 数据库的 Web API 使用。此外,我针对 SQLite 数据库对其进行了测试(单元测试)。

我使用配置文件以简单的方式完成了它。因此,在我扩展 DBContext 的类中,我使用以下代码实现了 OnConfiguring:

if(isSqlServer) //don't mind where it comes from, it works fine
    optionsBuilder.UseSqlServer(connectionString);
else
    optionsBuilder.UseSqlite(connectionString);

它似乎工作正常,但它有一个不希望的效果。假设我有这个项目:

  1. 持久层
  2. 持久层测试
  3. 网络API

由于方法 UseSqlite 是包 Microsoft.EntityFrameworkCore.Sqlite 的类中的静态扩展方法,同样,方法 UseSqlServer 是包 Microsoft.EntityFrameworkCore.SqlServer 的类中的静态扩展方法,有两件事困扰我。

首先,我必须在三个项目中包含这两个依赖项,以避免在运行时出现错误“System.IO.FileNotFoundException:无法加载文件或程序集 Microsoft.EntityFrameworkCore.SqlServer (...)”。

其次,如果我需要支持新的 DBMS(Oracle、MySQL),我必须在这三个项目上包含新的依赖项。

我希望构建一个 PersistentLayer 项目没有这些依赖项的场景,而 PersistentLayerTests 将仅依赖于 Microsoft.EntityFrameworkCore.Sqlite,而 WebAPI 将仅依赖于 Microsoft.EntityFrameworkCore.SqlServer。

是否有另一种方法来配置连接上下文以解耦这些包依赖关系?

笔记:

  1. 我使用 NHibernate 做到了这一点,它为每个 DBMS 使用不同的驱动程序实现。
  2. 我尝试使用反射,但并不优雅,而且我注意到如果扩展方法具有不同的参数,它将无法工作。
  3. 我不需要完整的解决方案。如果有人能以另一种方式指出我,那将非常有帮助。

标签: c#.net-coreentity-framework-core

解决方案


您只需让 DbContext 的用户(PersistenceLayerTests 和 WebApi 项目)负责配置它,而不是DbContext本身。

DbContext 提供了一个接受DbContextOptions的构造函数。您需要公开此构造函数:

public class MyDbContext : DbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }

    // ...
}

然后,这使您能够执行以下操作:

var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();

if (isSqlServer) //don't mind where it comes from, it works fine
    optionsBuilder.UseSqlServer(connectionString);
else
    optionsBuilder.UseSqlite(connectionString);

using (var context = new MyDbContext(optionsBuilder.Options))
{
    // ...
}

推荐阅读