繁体   English   中英

如何配置EF Core连接上下文以解耦程序包依赖关系?

[英]How to configure EF Core connection context to decouple packages dependencies?

我制作了一个使用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. PersistenceLayerTests
  3. 的WebAPI

由于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. 我不需要完整的解决方案。 如果有人可以用另一种方式指出我,那将非常有帮助。

你只需要让你的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))
{
    // ...
}

这似乎有些矫kill过正,但是在这种情况下,基本策略是放置一个公共界面,并将其分隔在不同的项目中。 不知道这是否是这种情况的最佳解决方案。

然后,不同的项目是独立的(除了通用界面之外),并且很容易随时间扩展。

关键部分是,在您的主项目中,仅引用接口组件,而不引用其中之一。 如果要避免FileNotFoundException则必须在运行时加载混凝土(装配体):此外:您需要一种机制来选择合适的模型(通常称为factory

让我们考虑一下其中有3种(sql,sqllite和oracle)的情况:

首先要做的是创建一个公共接口以与适当的Db enginge通信,例如:

//separate assembly
public interface IDbEningeSelector
{
    //added the option builder for simplicity: one could do better.
    void Configure(string connectionString,IOptionsBuilder optionsBuilder);
}

接下来,仅针对具体实现创建3个单独的项目,一个sql-lite,一个sql和一个oracle。

下一步:在三个项目中创建一个实现此目的的类:

//3 of these.
public class SqlEnging : IDbEngineSelector
{
    public void Configure(string connectionString,IOptionsBuilder optionsBuilder)
    {
         optionsBuilder.UseSqlServer(connectionString);
    }
}

好的,现在您可以选择其中之一。

//the "thing"
IDbEngineSelector selector = null;

selector = //resolve through factory, possibly based on a flag. 

selector.Configure(connectionString, optionsBuilder);

基本上,您已经完成了可扩展的,动态引用的数据库提供程序系统。

对于动态程序集解析器,您需要按照本文中的描述进行加载: https : //www.codeproject.com/Articles/1194332/Resolving-Assemblies-in-NET-Core

这实际上将在运行时加载依赖项,为此目的,我建议保留一个特殊路径以放置这些程序集。

我省略了工厂实现的详细信息,我需要首先检查在.net Core中执行此操作的正确方法,继续...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM