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



在ASP.NET Core中,EF Core上下文由内置的DI容器创建。在官方文档中,使用通用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容器中不太好用。

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

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

这对DI容器来说很好。它只查看最派生的类型,即它试图实例化的类型。介于两者之间有一个基类这一事实并不相关。

注意,虽然你不能使用DbContextOptions<AbstractDbContext>,但你不需要。你可以让基类使用DbContextOptions,也可以让基类通用并使用DbContextOptions<ConcreteDbContext>:

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的构造函数通常也能工作。通常情况下,你是对的,服务提供商无法解决这个问题。但是,当您调用serviceCollection.AddDbContext<ConcreteDbContext>(...)时,EF Core特别通知服务容器,当请求DbContextOptions实例时,应该提供DbContextOptions<ConcreteDbContext>实例。

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

这是基本IdentityDbContext类(泛型和非泛型)构造函数的签名:

public IdentityDbContext(DbContextOptions options)

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

事实上,DbContextOptions类的泛型版本和非泛型版本之间的唯一区别是泛型版本实现了abstract非泛型版本。

尽管如此,将DbContextOptions<YourDbContext>传递给YourDbContext构造函数更安全,因为它可以确保调用者传递抽象类的正确实现(基本上是ContextType属性)。

相关内容

  • 没有找到相关文章

最新更新