【问题标题】:.NET Core DbContextPool vs DbContextFactory - for implementing repository.NET Core DbContextPool 与 DbContextFactory - 用于实现存储库
【发布时间】:2021-11-08 05:27:37
【问题描述】:

我尝试在我的基础架构层中实现一个存储库。我不使用 dbContext 作为工作单元——而是每个 repo 方法都做并完成它的工作。我将在上面的一层中实现事务以将 repo 方法结合在一起。

在我的前世(不在 .NET Core 中)我的 repo 方法通常如下:

class MyRepo:IMyRepo
{
   public void Save(MyObject p)
   {
     using(var ctx = new MyDbContext())
     {
         ctx.MyTable.Add( ...);
         ctx.SaveChanges();
     }

在酷炫的 Core 和 DI 世界中,我尝试按如下方式实现该方法:

方式 1 - 将 DbContextOptions 添加到 DI

class MyRepo : IMyRepo
{
    private readonly DbContextOptions<MyDbContext> Options;
    public MyRepo(DbContextOptions<MyDbContext> options)
    {
      Options = options;
    }
    public void Save(MyObject p)
    {
       using var ctx = new MyDbContext(this.Options);
       ...

方式 2 - 将 DbContextFactory 添加到 DI

class MyRepo:IMyRepo
{
    private readonly DbContextFactory<MyDbContext> Factory;
    public MyRepo(DbContextFactory<MyDbContext> factory)
    {
      Factory = factory;
    }
    public void Save(MyObject p)
    {
       using var ctx = Factory.CreateDbContext();
       ...

方式 3 - 将 DbContextPool 添加到 DI

class MyRepo:IMyRepo
{
    private readonly DbContextPool<MyDbContext> Pool;
    public MyRepo(DbContextPool<MyDbContext> pool)
    {
      Pool = pool;
    }
    public void Save(MyObject p)
    {
       using var ctx = Pool.GetCtxInstance(); ? ???
       ...
      

  

我想以两种方式对我的存储库进行单元测试:

  • 在本地 .mdf 文件上,连接到它并执行真正的 sql 操作并检查它们的结果
  • 我计划使用假存储库测试域服务。我读到有一种方法可以使用“内存表”来伪造存储库,在这种情况下,我认为我必须在测试期间以某种方式替换我的 DbContext 实例

我的问题:

  • 第三种方式如何获取一个新的上下文实例(当使用pool时?)?还是像ctx = new MyDbContext()这么简单?
  • 这是一个真实的例子来伪造 MyDbContext 本身,而不仅仅是改变它的“选项”?如何伪造它?为什么?
  • 在这种情况下,我认为工厂是最好的,因为我可以实现其他方法来创建 dbcontext 以供以后测试。是吗?
  • 那么,在存储库本身以及使用伪造存储库的域服务上执行单元测试的最佳方法是什么?

您对实施存储库有什么建议?提前致谢!

【问题讨论】:

  • 对于实例化 DbContext,new() 总是创建新对象,这里没有池,也没有魔法。但是,如果您使用 AddDbContextPool 为特定 DbContext 注册了一个池,则可以通过 DI、构造函数注入或 ServiceProvider 从池中获取任何此类 DbContext。顺便说一句,如果您更喜欢工厂方法,还有AddPooledDbContextFactory 方法。
  • 谢谢。那么需要第 4 种方式,应该在哪里提供 ServiceProvider 类并将其存储在 repo 中?

标签: c# dependency-injection entity-framework-core repository-pattern


【解决方案1】:

您对实施存储库有什么建议?

  1. 不要。您的 DbContext 是一个非常好的存储库。就用那个吧。

  2. 如果您这样做,请在您的额外存储库中注入您的 DbContext 子类型的实例。然后 DI 可以处理 DBContext 的生命周期,您将能够按照您的设想管理事务,因为范围内的所有 repos 将共享一个 DbContext 实例。

【讨论】:

  • 可能为时过早,但先生无法理解您。 “我的 dbcontext”不是一个 repo,它是一个 dbcontext。我知道使用 DI 是一种编写代码的方式——但我不喜欢它。当我需要任何东西的实例时——我必须编写“魔法”构造函数来获得一个。我认为存储和使用 serviceProvider 是一种反模式。我有一种不好的感觉:(
  • DbContext 既是存储库又是工作单元。
  • 哦,我现在明白你的意思了……嗯。 :) 谢谢。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多