asp.net 不同服务之间依赖同一DbContext示例

ghhkc1vu  于 5个月前  发布在  .NET
关注(0)|答案(2)|浏览(94)

我正在处理一个遗留的ASP.NET MVC 5项目。我们没有一个合适的数据访问层,我们的业务层类直接与注入的DbContext交互。我面临着一个问题,我已经在一个简单的示例中捕捉到了这个问题的本质。
我有类ServiceAServiceBServiceC(在这个例子中我省略了接口)。它们都通过DI在构造函数中接收相同的DbContext示例。在ServiceC中,我想围绕几个数据库操作 Package 一个事务,这些操作由其他服务执行。这是可行的。因为这些服务都接收DbContext的相同示例。“

public class ServiceC
    {
      public ServiceC(DbContext context, ServiceA serviceA, ServiceB serviceB)
      {
        _context = context;
        _serviceA = serviceA;
        _serviceB = serviceB;
      }
      
      public DoSomething()
      {
        using var transaction = context.Database.BeginTransaction()
        try
        {
          _serviceA.DoSomethingThatInvolvesDbContext1();
          _serviceB.DoSomethingThatInvovlesDbContext2();
          
          transaction.Commit();
        }
        catch
        {
          transaction.Rollback();
          throw;
        }
      }
    }

字符串
我在这个设计中看到的问题是,ServiceC的设计方式,它要求ServiceAServiceB共享同一个DbContext示例。如果我决定以不同的方式配置我的DI容器,它将无法工作。如果实现依赖于特定的DI容器配置,这不是一个糟糕的设计吗?
我唯一能想到的另一件事,就是引进工厂提供服务:

public class ServiceC
    {
      public ServiceC(DbContext context, IServiceAFactory serviceA, IServiceBFactory serviceB)
      {
        _context = context;
        _serviceA = serviceAFactory.Get(context);
        _serviceB = serviceBFactory.Get(context);
      }
      
      // Rest of implementation
    }


但这似乎过于复杂。

dxpyg8gm

dxpyg8gm1#

在不了解整个背景的情况下提出建议有点困难,但是。
从技术上讲,如果您将DBContext注册为Scoped以及所有3个服务,则在解析前一个服务时,您将向所有服务注入相同的DBContext示例。您唯一需要确保的是之前创建一个范围。取决于已经为true的用法。
另一个选择是将DBContext作为参数传递给服务方法。在我看来,这是一个更可靠的解决方案。
或者你可以重构。
您的示例中的手动解析也可以工作。

jchrr9hc

jchrr9hc2#

您应该以一种对您的应用程序有意义的方式配置DI服务。
一般来说,配置dbcontext的正确方法是将它们构造为Scoped依赖项,这意味着您将为每个请求获得一个新的dbcontext示例 *,但 * 同一示例将由请求生命周期内的所有服务共享。
因此,这里的简单答案是坚持使用作用域级别的数据库上下文。Singletons/Transient依赖项对数据库上下文没有多大意义。

相关问题