在Asp.Net Core中注入DbContext。具体类型还是界面?

Mig*_*ura 6 entity-framework-core asp.net-core

在Asp.Net Core项目中,我正在注入Entity Framework DbContext:

public MessageRepository(MyDbContext context) {
}
Run Code Online (Sandbox Code Playgroud)

且配置为:

services
  .AddEntityFramework()
  .AddSqlServer()
  .AddDbContext<Context>(x => x.UseSqlServer(connectionString);
Run Code Online (Sandbox Code Playgroud)

我应该创建一个接口IMyDbContext并注入它吗?

public class MyDbContext : DbContext, IMyDbContext { }

public MessageRepository(IMyDbContext context) {
}
Run Code Online (Sandbox Code Playgroud)

在所有ASP.NET Core示例中,我都看到了具体类型MyDbContext的注入,而不是接口。

我应该选择什么选项?

Cla*_*sen 8

目前我自己在做一个项目,在那里我决定使用 2 个这样的接口

public interface IDbContext : IDisposable
{
    DbContext Instance { get; }
}
Run Code Online (Sandbox Code Playgroud)

public interface IApplicationDbContext : IDbContext
{
    DbSet<MyEntity> MyEntities { get; set; }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我的具体 DbContext 然后将只实现应用程序上下文接口

public class ApplicationDbContext : DbContext, IApplicationDbContext
{
    public DbContext Instance => this

    public DbSet<MyEntity> MyEntities { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这允许我将应用程序上下文的实现作为应用程序上下文接口注入,同时还允许我通过 Instance 属性 getter 访问 DbContext 方法,而无需将 DbContext 类所需的方法添加到接口。

到目前为止,这很好用。

  • 我真的不记得了,我想我是有原因的。 (2认同)
  • @BernoulliIT 是的,但是直接注入上下文类也会暴露所有内容。这种方法简单地消除了使注入的接口与 DbContext 类方法和属性保持最新所需的工作。 (2认同)

Uli*_*Uli 5

我们总是注入一个接口,因为在单元和集成测试中更容易模拟。

  1. 你愿意改变MessageRepository构造函数的签名吗?它依赖于具体类型。
  2. 你为你的代码编写测试吗?使用 和 interface 可以更容易地模拟数据库上下文。

如果您对上述一项或多项回答“否”,请注入具体类型;否则,注入接口。

[编辑] 使用以下内容。

context services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
Run Code Online (Sandbox Code Playgroud)

  • 您能举例说明如何注册存储库接口吗?您使用“AddDbContext”或“AddScoped”吗? (2认同)