【问题标题】:How to handle DBContext instancing in Entity Framework Core如何在 Entity Framework Core 中处理 DBContext 实例化
【发布时间】:2020-10-21 14:34:57
【问题描述】:

来自 Java 环境,我遇到了一些关于可继承 DBContext 类的问题。我曾经使用 Java EE:

  1. 设置一个或多个数据库上下文(如果受影响的独立实体集群);
  2. 将上下文添加到通过 DI 处理查询执行的各个 DataAccessor 类中;

现在使用 EF Core,我看到的几乎所有示例都通过调用默认构造函数来创建 MyDBContext 的实例:

 using (var db = new myContext()){...}

这向我提出了几个问题:

  • 使用此方法,调用构造函数的每个 DataAccessor 类都有自己的 Context 实例。只 ave 一个并在需要时使用 DI 注入不是更好吗?
  • 如果我没有重载OnConfiguring(...) 来传递选项,而是使用AddDbContext 作为Startup.cs 中的服务,我该如何调用构造函数?现在,带有选项的重载构造函数期望在每次调用构造函数时传递它们。
  • 每个应用程序/Db 拥有多个 DBContexts 甚至是使用 EF Core 的好习惯吗?

【问题讨论】:

  • DbContext 是一个工作单元。它收集所有更改并仅在调用 SaveChanges 时保存它们。这就是为什么所有示例和教程都使用using,你也应该这样做。
  • 至于配置,示例展示了如何从外部进行配置,如何传递选项,或者如果你使用.NET Core DI,如何使用@ 987654327@ 带有构建器操作

标签: c# entity-framework-core


【解决方案1】:

通常您希望每个请求范围只有一个实例

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        // use options as you would use them in the .OnConfiguring
        options.UseSqlServer("your connectionString");
    );
}

如果您在服务中使用构造函数注入,ASP.NET 服务提供者会将 db 上下文解析为构造函数参数。以这种方式具有数据库上下文的所有服务都将共享同一个实例。

public class ServiceDependentOnContext
{
    private readonly ApplicationDbContext dbContext;

    public ServiceDependentOnContext(ApplicationDbContext dbContext)
    {
        this.dbContext = dbContext;
    }
}

确保你也为依赖注入配置了你的服务

// This method gets called by the runtime. Use this method to add services to the container.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer("your connectionString")
    );

    services.AddScoped<ServiceDependentOnContext>();
}

【讨论】:

  • 谢谢。有了这个和@Darem 的评论,我现在可以弄清楚了;我将 DBContext 注入到控制器使用的存储库中。但这再次提出了剩下的问题:让 DBContext 实现多个接口是否有必要/良好做法取决于使用它的不同存储库具有哪些职责?而且,参考 Darem 的评论:AddScoped 会有线程问题还是应该使用瞬态?
  • transient 就像你每次都在做new DbContext 一样。范围生命周期不会有任何线程问题,因为每个请求不会使用超过 1 个线程(除非代码有意)。我不明白第一个问题,为什么不同的仓库需要多个接口。如果您需要 db 上下文的动态选项,您可以在运行时使用 IServiceProvider 对其进行配置。在stackoverflow.com/a/64444899/7313094查看我的回答
  • 作用域生命周期用于确保创建/列出的所有实体都属于同一个DbContext.EntityTracker。因此,如果您在不同的服务中做事,您可以使用单个 DbContext.SaveChanges() 调用一次提交所有更改。这看起来很像事务行为 - 全部提交或还原。
  • 假设我有三个不同职责的存储库。然后,我将让单个 DBContext 实现三个不同的接口,其中包含通过 repo 访问数据库所需的方法子集。另一种方法是让 DBContext 只包含一个接口,其中包含所有三个 repos 使用的所有方法。我认为这可能是一个主观问题,但我想知道 ASP.NET 是否有通常的做法。
  • 这取决于你。我看不到向 DbContext 添加接口的意义,您需要的所有方法都是 Set&lt;T&gt;SaveChanges,所以通常我最终将 db context 直接插入到 repositories/services/handlers 中
猜你喜欢
  • 1970-01-01
  • 2018-11-20
  • 2017-06-13
  • 2022-11-21
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多