我可以在 ASP.NET Core 和 EF Core 中安全地使用非通用 DbContextOptions 吗?

gro*_*kky 3 c# asp.net-identity entity-framework-core asp.net-core

在 ASP.NET Core 中,EF Core 上下文是由内置 DI 容器创建的。在官方文档中,上下文是使用泛型创建的DbContextOptions<TContext>

public class MyContext : IdentityDbContext<User> {
  public MyContext(DbContextOptions<MyContext> options, ILogger<MyContext) logger) : base(options) { }
}
Run Code Online (Sandbox Code Playgroud)

然而,也有一些非泛型的例子:

public class MyContext : IdentityDbContext<User> {
  public MyContext(DbContextOptions options, ILogger<MyContext) logger) : base(options) { }
}
Run Code Online (Sandbox Code Playgroud)

从源码来看它们的区别是:

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

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

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

小智 5

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

这与 DI 容器配合得很好。它只查看最派生的类型,即它尝试实例化的类型。事实上,中间有一个基类是不相关的。

请注意,虽然您不能使用DbContextOptions<AbstractDbContext>,但您也不需要这样做。您可以使基类 take DbContextOptions,或使基类通用并 take DbContextOptions<ConcreteDbContext>

abstract class AbstractDbContext : DbContext
{
    protected AbstractDbContext(DbContextOptions options) : base(options)
    {
    }
}

class ConcreteDbContext : AbstractDbContext
{
    public ConcreteDbContext(DbContextOptions<ConcreteDbContext> options) : base(options)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

或者

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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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