【问题标题】:Repository pattern sharing changes across scoped instances跨范围实例的存储库模式共享更改
【发布时间】:2022-08-19 16:51:14
【问题描述】:

我正在使用一个非常标准的通用存储库模式(例如https://codewithmukesh.com/blog/repository-pattern-in-aspnet-core/#What_would_happen_if_we_didnt_have_an_UnitOfWork_Abstraction

程序.cs我将我的通用存储库服务定义为范围。

services.AddScoped(typeof(IGenericRepository<,>), typeof(GenericRepository<,>));

在工作服务中,我在代码执行期间创建了两个作用域实例;

using (var serviceScope = _serviceProvider.CreateScope())
{
  var personDataService = serviceScope.ServiceProvider.GetRequiredService<IGenericRepository<Person, MyDbContext>>();
  var auditLogDataService = serviceScope.ServiceProvider.GetRequiredService<IGenericRepository<AuditLog, MyDbContext>>();
  ...
}

例如,当我在第一个服务上生成 SQL 异常的调用时,我想在第二个服务中记录错误;

try {
   await personDataService.InsertAsync(myNewPerson);
} 
catch (Exception ex)
{
   var newAuditLog = new AuditLog(\"Exception occurred inserting a new user\", ex);
   await auditLogDataService.InsertAsync(newAuditLog);
}

但是,当personDataService 生成SQLException 时,例如;

SqlException:无法将值 NULL 插入列 \'Name\'\"

然后catch 块触发,当我在第二个auditLogDataService 服务上运行InsertAsync() 时再次遇到相同的错误。

SqlException:无法将值 NULL 插入列 \'Name\'\"

似乎第一个服务的更改也在第二个服务中。我假设MyDbContext 是共享的。

如何创建auditLogDataService 的独立实例,这样我就可以在没有第一个更改的情况下保存第二个更改?

  • 请不要将存储库模式与实体框架一起使用。它已经通过 DbSet<T> 公开了一个存储库。你将如何支持 Include()s?投影(选择)?分组?但是,如果您将存储库注册为瞬态,它们应该获得自己的 DbContext 实例,而您不应该遇到遇到的问题。请显示minimal reproducible example,包括您的 DI 设置。
  • 也许最简单的解决方案是为日志记录创建一个单独的上下文。无论如何,我认为这不是一个坏主意。在应用程序中保持分离。这允许您为一个工作单元拥有一个共享(范围)上下文。
  • @CodeCaster 当然,但问题是关于 DI 配置。我的问题很好,准备充分。

标签: c# entity-framework-core


【解决方案1】:

您可以尝试通过构造函数调用为每个存储库发送 DBContext 对象吗?例如,每当泛型存储库用于任何类类型时,将其作为构造函数调用并立即传递 DBContext 对象。因此,每次调用为该接口定义的存储库对象时,您都会获得当前的 DBContext。

【讨论】:

    【解决方案2】:

    您可以将 dbContextFactory 注入到您的存储库中,并从那里的工厂创建一个新的 DbContext。

    【讨论】:

      猜你喜欢
      • 2015-02-21
      • 2022-11-11
      • 1970-01-01
      • 2014-04-17
      • 2021-02-17
      • 1970-01-01
      • 2022-10-24
      • 2011-11-08
      • 1970-01-01
      相关资源
      最近更新 更多