多个服务中的数据库上下文使用

Db context usage in multiple services

我必须重构一个有很多相互依赖的服务的应用程序。

我面临的问题是所有服务都使用实体,就好像它们是像这样的简单对象:

var lst = _context.chapters.Include(some condition).where(some condition).ToList();
foreach(var i in lst)
   i.somearray.removeall(some condition);
return _mapper.Map<datatype>(lst)

现在另一个服务调用该方法来获取数据并做一些与章节 table 完全无关的事情。(保存状态)其他服务调用 _context.SaveChanges() 的那一刻会发生什么?基本上擦了一半数据库,另一半不一致。

像这样重构服务的最佳做法是什么?什么是最优雅的解决方案,可以让我避免重写所有这些?

现在我只是在关键点刷新更改跟踪器中的所有内容,但这不是很可靠,大约需要 2 分钟才能完成。将数据库上下文设置为瞬态不起作用,因为某些服务似乎依赖于作用域上下文。

我考虑为每个服务创建 dto 并在它们被更改之前映射它们。但它是一个庞大的应用程序。这可能需要几天时间。

如果我没理解错的话,问题出在这一行:

foreach(var i in lst)
   i.somearray.removeall(some condition);

我同意,如果在服务之间共享相同的 DbContext,这可能会成为一个问题。正如我所见,您可以从不同的方向(无特定顺序)解决问题。

  1. 调整映射器中的逻辑。 确保 “减少” [=12] 中的项目=] 在 _mapper.Map 中完成并确保映射器不会影响实体本身。如果您将库用作 AutoMapper,这应该不会太难。这里的问题是你有一个条件,我认为这可能因服务而异,即使类型相同?在这种情况下 到您的地图,从而在服务之间使用相同的映射。

  2. 减少查询返回的项目。

    var lst = _context.chapters.Include(p=> p.somearray.Where(somecondition)).where(some condition).ToList();

    可以找到更具体的示例 here。这也有利于减少从数据库中获取的负载。

  3. 使用no tracking 启用后,实体实际上将是read-only。因此,对它们所做的任何更改都不会写回 db。任何其他服务都无法持久化从其他服务获取的实体(只要它未被跟踪)。这可能是最简单的解决方案。

    _context.chapters.Include(some condition).where(some condition).AsNoTracking().ToList();