代码之家  ›  专栏  ›  技术社区  ›  heringer

如何配置EF核心连接上下文来解耦包依赖关系?

  •  2
  • heringer  · 技术社区  · 6 年前

    我使用实体框架核心创建了一个库来处理持久性。 它由针对SQL Server数据库的Web API使用。 此外,我还针对SQLite数据库进行了测试(单元测试)。

    我用一个配置文件以一种简单的方式完成了它。因此,在扩展DBContext的类中,我实现了如下配置:

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

    1. 持久性图层测试
    2. 网络API

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

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

    我希望构建这样一个场景:项目PersistentLayer将不具有这些依赖项,而PersistentLayerTests将完全依赖于这些依赖项Microsoft.EntityFrameworkCore.Sqlite文件WebAPI将完全依赖于Microsoft.EntityFrameworkCore.SqlServer文件.

    有没有其他方法可以配置连接上下文来解耦这些包的依赖关系?

    1. 我试着使用反射,但并不优雅,我注意到如果扩展方法有不同的参数,它将不起作用。
    2 回复  |  直到 6 年前
        1
  •  2
  •   Stefan    6 年前

    这似乎有些过分,但在这种情况下,基本策略是放置一个公共接口,并将它们分离到不同的项目中。不确定这是否是这种情况下的最佳解决方案。

    然后不同的项目是独立的(除了公共接口),并且可以很容易地在以后扩展。

    FileNotFoundException factory .

    首先要做的是创建一个公共接口,以便与适当的数据库引擎进行通信,例如:

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

    接下来,只需为具体实现创建3个独立的项目,一个sqllite、一个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

    这实际上会在运行时加载依赖项,因此我最好为此保留一个特殊的路径来放置这些程序集。

        2
  •  2
  •   Adam Simon    6 年前

    您只需要创建 数据库上下文 负责配置它而不是 数据库上下文 它自己。

    provides a constructor 接受 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))
    {
        // ...
    }