如何在EF7 / .NET Core中为多个数据库实现DbContext继承 [英] How do I implement DbContext inheritance for multiple databases in EF7 / .NET Core

查看:889
本文介绍了如何在EF7 / .NET Core中为多个数据库实现DbContext继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在ASP.NET Core 1.1中构建Web API。

I am building web APIs in ASP.NET Core 1.1.

我有许多不同的数据库(用于不同的系统),它们具有用于配置项的通用基本架构作为配置,用户和组(总共约25个表)。我试图通过从图中的基类继承来避免为模型的共享部分复制相当广泛的EF配置。

I have a number different databases (for different systems) which have common base schemas for configuration items such as Configuration, Users and groups (about 25 tables in all). I am trying to avoid duplicating the quite extensive EF configuration for the shared part of the model by inheriting from a base class as shown in the diagram.

但是,这不起作用,因为实体框架(EF)要求传递 DbContextOptions< DerivedRepository> code>作为构造函数的参数,其中 DerivedRepository 必须与调用构造函数的存储库类型匹配。然后必须通过调用:base(param)将参数向下传递到基本 DbContext

However, this does not work because of the Entity Framework (EF) requirement to pass DbContextOptions<DerivedRepository> as a parameter to the constructor, where DerivedRepository must match the type of the repository the constructor is called on. The parameter must then be passed down to the base DbContext by calling :base(param).

因此,当(例如)使用 DbContextOptions< InvestContext> 初始化InvestContext时,它将调用 base(DbContextOptions< InvestContext>)和EF引发错误,因为对 ConfigurationContext 构造函数的调用接收到类型为 DbContextOptions< InvestContext>的参数; 而不是必需的类型 DbContextOptions< ConfigurationContext> 。由于DbContext上的options字段定义为

So when (for example) InvestContext is initialised with DbContextOptions<InvestContext>, it calls base(DbContextOptions<InvestContext>) and EF throws an error because the call to the ConfigurationContext constructor is receiving a parameter of type DbContextOptions<InvestContext> instead of the required type DbContextOptions<ConfigurationContext>. Since the options field on DbContext is defined as

    private readonly DbContextOptions _options;

我找不到解决方法。

一次定义共享模型并多次使用的最佳方法是什么?我想我可以创建一个辅助函数并在每个派生上下文中调用它,但是它不像继承那样干净或透明。

What is the best way to define the shared model once and use it multiple times? I guess I could create a helper function and call it from every derived context, but it's not nearly as clean or transparent as inheritance.

推荐答案

好的,我的工作方式仍然使用继承层次结构,例如(以上面的 InvestContext 为例):

OK, I have got this working in a way which still uses the inheritance hierarchy, like this (using InvestContext from above as the example):

如上所述,InvestContext类接收类型为 DbContextOptions< InvestContext> 的构造函数参数,但必须传递 DbContextOptions<

As stated, the InvestContext class receives a constructor parameter of type DbContextOptions<InvestContext>, but must pass DbContextOptions<ConfigurationContext> to it's base.

我编写了一种方法,该方法从 DbContextOptions 变量,并构建所需类型的DbContextOptions实例。 InvestContext使用此方法在调用base()之前将其options参数转换为正确的类型。

I have written a method which digs the connectionstring out of a DbContextOptions variable, and builds a DbContextOptions instance of the required type. InvestContext uses this method to convert its options parameter to the right type before calling base().

转换方法如下:

    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;
    }

和InvestContext构造函数调用从以下更改:

and the InvestContext constructor call changes from this:

  public InvestContext(DbContextOptions<InvestContext> options):base(options)

为此:

  public InvestContext(DbContextOptions<InvestContext> options):base(ChangeOptionsType<ConfigurationContext>(options))

到目前为止,InvestContext和ConfigurationContext都可用于简单查询,但似乎有点像黑客一样,可能不是EF7设计师想到的。

So far both InvestContext and ConfigurationContext work for simple queries, but it seems like a bit of a hack and possibly not something the designers of EF7 had in mind.

我仍然担心当我尝试复杂的查询,更新等操作时,EF会陷入困境。这似乎不是问题,见下文)

I am still concerned that EF is going to get itself in a knot when I try complex queries, updates etc. It appears that this is not a problem, see below)

编辑:我已将此问题记录为EF7团队的问题这里,并且一个团队成员建议对EF Core核心进行如下更改:

I've logged this problem as an issue with the EF7 team here, and a team member has suggested a change to the EF Core core as follows:


我们应该更新检查,以允许TContext为从当前上下文类型派生的类型

"We should update the check to allow TContext to be a type that is derived from the current context type"

这可以解决问题。

与该团队成员进一步互动(您可以在此问题上看到)并进行一些挖掘通过EF Core代码,我上面概述的方法看起来是安全的,并且是在实施建议的更改之前最好的方法。

After further interaction with that team member (which you can see on the issue) and some digging through the EF Core code, the approach I've outlined above looks safe and the best approach until the suggested change is implemented.

这篇关于如何在EF7 / .NET Core中为多个数据库实现DbContext继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆