Pet*_*ter 8 entity-framework entity-framework-core .net-core asp.net-core
我正在ASP.NET Core 1.1中构建Web API.
我有许多不同的数据库(针对不同的系统),这些数据库具有配置项,例如配置,用户和组(总共约25个表)的公共基本模式.我试图通过继承基类来避免为模型的共享部分复制相当广泛的EF配置,如图所示.
但是,这不起作用,因为实体框架(EF)要求DbContextOptions<DerivedRepository>作为参数传递给构造函数,其中DerivedRepository必须匹配调用构造函数的存储库的类型.然后必须通过DbContext调用将参数传递给基数:base(param).
因此,当(例如)InvestContext初始化时DbContextOptions<InvestContext>,它调用base(DbContextOptions<InvestContext>)并且EF抛出错误,因为对ConfigurationContext构造函数的调用正在接收类型的参数DbContextOptions<InvestContext>而不是所需的类型DbContextOptions<ConfigurationContext>.由于DbContext上的选项字段定义为
private readonly DbContextOptions _options;
Run Code Online (Sandbox Code Playgroud)
我无法看到解决这个问题的方法.
定义共享模型一次并多次使用它的最佳方法是什么?我想我可以创建一个辅助函数并从每个派生的上下文中调用它,但它不像继承那样干净或透明.
Mar*_*ark 45
我想把这篇来自 OP 的 GitHub issue 的帖子引起大家的注意:
通过提供一个使用 DbContextOptions 而没有任何类型的受保护构造函数,我能够在没有黑客的情况下解决这个问题。保护第二个构造函数确保它不会被 DI 使用。
public class MainDbContext : DbContext {
public MainDbContext(DbContextOptions<MainDbContext> options)
: base(options) {
}
protected MainDbContext(DbContextOptions options)
: base(options) {
}
}
public class SubDbContext : MainDbContext {
public SubDbContext (DbContextOptions<SubDbContext> options)
: base(options) {
}
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*ter 16
好的,我的工作方式仍然使用继承层次结构,如下所示(以InvestContext上面的例子为例):
如上所述,InvestContext类接收类型的构造函数参数DbContextOptions<InvestContext>,但必须传递DbContextOptions<ConfigurationContext>给它的基础.
我编写了一个方法,用于从DbContextOptions变量中挖掘连接字符串,并构建所需类型的DbContextOptions实例.InvestContext使用此方法在调用base()之前将其options参数转换为正确的类型.
转换方法如下所示:
protected static DbContextOptions<T> ChangeOptionsType<T>(DbContextOptions options) where T:DbContext
{
var sqlExt = options.Extensions.FirstOrDefault(e => e is SqlServerOptionsExtension);
if (sqlExt == null)
throw (new Exception("Failed to retrieve SQL connection string for base Context"));
return new DbContextOptionsBuilder<T>()
.UseSqlServer(((SqlServerOptionsExtension)sqlExt).ConnectionString)
.Options;
}
Run Code Online (Sandbox Code Playgroud)
和InvestContext构造函数调用此更改:
public InvestContext(DbContextOptions<InvestContext> options):base(options)
Run Code Online (Sandbox Code Playgroud)
对此:
public InvestContext(DbContextOptions<InvestContext> options):base(ChangeOptionsType<ConfigurationContext>(options))
Run Code Online (Sandbox Code Playgroud)
到目前为止,InvestContext和ConfigurationContext都适用于简单的查询,但它似乎有点像黑客,可能不是EF7的设计者所想到的.
当我尝试复杂的查询,更新等时,我仍然担心EF会陷入困境.看来这不是问题,见下文)
编辑:我已经记录了此问题,因为与EF7队的问题在这里,和团队成员曾建议更改了EF核心的核心如下:
"我们应该更新检查以允许TContext成为从当前上下文类型派生的类型"
这样可以解决问题.
在与该团队成员(您可以在问题上看到)进行进一步交互并进行一些挖掘EF Core代码之后,我上面概述的方法看起来是安全的,并且是实施建议更改之前的最佳方法.
| 归档时间: |
|
| 查看次数: |
5319 次 |
| 最近记录: |