[英]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);
似乎工作正常,但效果不理想。 假设我有这个项目:
由于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。
还有另一种方法来配置连接上下文以解耦这些程序包依赖性吗?
笔记:
你只需要让你的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.