【问题标题】:Can I safely use the non-generic DbContextOptions in ASP.NET Core and EF Core?我可以在 ASP.NET Core 和 EF Core 中安全地使用非泛型 DbContextOptions 吗?
【发布时间】:2017-05-21 15:56:57
【问题描述】:

在 ASP.NET Core 中,EF Core 上下文由内置 DI 容器创建。在official documentation 中,使用通用DbContextOptions<TContext> 创建上下文:

public class MyContext : IdentityDbContext<User> {
  public MyContext(DbContextOptions<MyContext> options, ILogger<MyContext) logger) : base(options) { }
}

不过,也有非泛型的例子:

public class MyContext : IdentityDbContext<User> {
  public MyContext(DbContextOptions options, ILogger<MyContext) logger) : base(options) { }
}

根据源码他们的区别是:

类型参数:TContext:这些选项适用的上下文类型。

我想使用非泛型类型,因为在我的设计中我有一个抽象的上下文,这与 DI 容器不兼容。

那么,如果我使用非泛型类型,这到底意味着什么?我的上下文配置不正确?

【问题讨论】:

    标签: c# asp.net-core asp.net-identity entity-framework-core


    【解决方案1】:

    我想使用非泛型类型,因为在我的设计中我有一个抽象的上下文,这与 DI 容器不兼容。

    这与 DI 容器配合得很好。它只查看最派生的类型,即它试图实例化的类型。两者之间存在基类这一事实无关紧要。

    请注意,虽然您不能使用DbContextOptions&lt;AbstractDbContext&gt;,但您不需要这样做。您可以使基类采用DbContextOptions,或者使基类通用并采用DbContextOptions&lt;ConcreteDbContext&gt;

    abstract class AbstractDbContext : DbContext
    {
        protected AbstractDbContext(DbContextOptions options) : base(options)
        {
        }
    }
    
    class ConcreteDbContext : AbstractDbContext
    {
        public ConcreteDbContext(DbContextOptions<ConcreteDbContext> options) : base(options)
        {
        }
    }
    

    abstract class AbstractDbContext<TContext> : DbContext
        where TContext : AbstractDbContext<TContext>
    {
        protected AbstractDbContext(DbContextOptions<TContext> options) : base(options)
        {
        }
    }
    
    class ConcreteDbContext : AbstractDbContext<ConcreteDbContext>
    {
        public ConcreteDbContext(DbContextOptions<ConcreteDbContext> options) : base(options)
        {
        }
    }
    

    那么,如果我使用非泛型类型,这到底意味着什么?我的上下文配置不正确?

    采用非泛型DbContextOptions 的构造函数通常也可以工作。通常,您是对的,服务提供商无法解决这个问题。但是,EF Core 会在调用serviceCollection.AddDbContext&lt;ConcreteDbContext&gt;(...) 时专门通知服务容器,当请求DbContextOptions 实例时,应提供DbContextOptions&lt;ConcreteDbContext&gt; 实例。

    请注意,这仅在您具有单一上下文类型时才有效。如果您有多个,则服务提供商没有足够的信息来确定您需要哪一个。

    【讨论】:

      【解决方案2】:

      这是基类IdentityDbContext 的签名(通用和非通用)constructor

      public IdentityDbContext(DbContextOptions options)
      

      这对我来说意味着它可以毫无问题地与非通用 DbContextOptions 一起使用。

      事实上,DbContextOptions 类的genericnon generic 版本之间的唯一区别是通用版本实现了abstract 非通用版本。

      不过,将DbContextOptions&lt;YourDbContext&gt; 传递给YourDbContext 构造函数更安全,因为它确保调用者将传递抽象类的正确实现(基本上是ContextType 属性)。

      【讨论】:

      • 我认为使用非泛型可能是安全的,除非你的项目中有两个不同的上下文。然后您需要使用通用选项类,以确保正确配置每个上下文。
      猜你喜欢
      • 2022-01-16
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      • 2021-10-08
      • 2020-07-21
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多