【问题标题】:Inject DbContext in Asp.Net Core. Concrete type or interface?在 Asp.Net Core 中注入 DbContext。具体类型还是接口?
【发布时间】:2016-08-03 15:59:07
【问题描述】:

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

public MessageRepository(MyDbContext context) {
}

而配置是:

services
  .AddEntityFramework()
  .AddSqlServer()
  .AddDbContext<Context>(x => x.UseSqlServer(connectionString);

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

public class MyDbContext : DbContext, IMyDbContext { }

public MessageRepository(IMyDbContext context) {
}

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

我应该选择什么选项?

【问题讨论】:

  • 在某一时刻,你必须做出一些决定,因为你无法抽象任何东西(或者你会浪费很多时间......)。我认为 EF 是我的基础设施组件的一部分,例如 Json.Net:如果我必须离开 EF,我很确定这将在十年后......所以不要想太多 ^^ 祝你好运跨度>

标签: asp.net-core entity-framework-core


【解决方案1】:

目前我自己正在做一个项目,我决定使用 2 个这样的界面

public interface IDbContext : IDisposable
{
    DbContext Instance { get; }
}

public interface IApplicationDbContext : IDbContext
{
    DbSet<MyEntity> MyEntities { get; set; }
    ...
}

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

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

    public DbSet<MyEntity> MyEntities { get; set; }
}

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

到目前为止,这很好用。

【讨论】:

  • 为什么不把两个接口结合起来呢?
  • 我真的不记得了,我想我是有原因的。
  • 这种方法公开了 DBContext 的所有方法,尽管它们可以通过使用存储库模式(结合工作单元类型)抽象出来
  • @BernoulliIT 是的,但是直接注入上下文类也会暴露所有内容。这种方法简单地消除了使用 DbContext 类方法和属性使注入的接口保持最新所需的工作。
  • 感谢您救了我的命。我正是需要这个。我必须访问 context.Entry() 方法并且无法从接口访问它(当然)。
【解决方案2】:

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

  1. 您愿意更改MessageRepository 构造函数的签名吗?它依赖于具体类型。
  2. 您是否为您的代码编写测试?使用和接口可以更轻松地模拟数据库上下文。

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

[编辑] 使用以下内容。

context services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

【讨论】:

  • 您能否举例说明如何注册您的存储库接口?你用AddDbContext还是AddScoped
  • 像往常一样使用 services.AddDbContext 添加 dbcontext。然后为数据库上下文注册服务和实现 services.AddScoped(provider => provider.GetService());检查链接jerriepelser.com/blog/…
【解决方案3】:

在我看来,您应该始终像@Uli 所说的那样依赖接口,但是当涉及到 DbContext 时,您需要记住您正在公开 EntityFramework Core 的 DbContext 的所有方法

公共类 MyDbContext : DbContext, IMyDbContext { }

在这种情况下,您不需要实现任何要公开的方法,因为 DbContext 会为您处理。

但是,如果 EF 代码更改了 DbContext 并且您对项目进行了更新,那么您将面临每次更新 IMyDbContext 以及所有单元测试的痛苦境地。在我看来,这会让你很头疼。

这个答案/问题可以帮助你理解为什么https://stackoverflow.com/a/6768712/819153

Unit testing EF - how to extract EF code out from BL?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多