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

发布于 2025-01-21 03:07:06 字数 594 浏览 0 评论 0原文

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

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

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)

现在另一个服务调用该方法来获取该数据并执行与章节表完全无关的操作。(保存状态)当其他服务调用该方法时会发生什么服务调用 _context.SaveChanges()?基本上擦除了一半的数据库,而另一半则不一致。

重构这样的服务的最佳实践是什么?允许我避免重写所有这些的最优雅的解决方案是什么?

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

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

I have to refactor an application that has a lot of services that depend on each other.

The problem I face is that all services use entities as if they were simple objects like this:

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)

Now another service calls that method to get that data and do something completely unrelated to the chapter table.(saving a status) What happens the moment that other service calls _context.SaveChanges()? Basically a wipe of half the database and the other half is inconsistent.

What would be the best practice to refactor services like that? And what would be the most elegant solution that allows me to avoid rewriting all of them?

For now im just refreshing everything in the change tracker at critical points, but thats not very reliable and takes about 2 Minutes to complete. Setting the db context to transient doesnt work as some services seem to depend on the scoped context.

I think about creating dtos for every service and mapping them before they are altered. But its a massive application. That could take days.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盛夏尉蓝 2025-01-28 03:07:06

如果我正确理解,问题是这样的行:

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

我确实同意,如果服务之间共享相同的dbContext,这可能是一个问题。如我所见,您可以从不同的方向解决问题(没有特定顺序)。

  1. 调整映射器中的逻辑。确保在i.somearray中的项目的“减少” 是在中完成的_mapper.map,并确保映射器不会影响实体本身。如果您使用库作为automapper这不应该很难。这里的问题在于您有一个条件,我认为这可能会因服务而有所不同,甚至艰难的类型是相同的?在这种情况下

  2. 减少查询中返回的物品。

    var lst = _context.chapters.include(p =&gt; p.somearray.where(somecondition))。其中(某些条件).tolist().tolist();

    可以找到一个更具体的示例在这里。这也具有减少从数据库获取的有效载荷的好处。

  3. 使用无跟踪强>启用后,实体实际上将仅阅读。因此,对他们进行的任何更改都不会写回DB。任何其他服务都无法坚持从另一个服务获取的实体(只要没有跟踪)。这可能是最简单的解决方案。

    _context.Chapters.include(某些条件).ASNOTRACKING().tolist();

If I understand correctly, the problem is this line:

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

I do agree that this can be a problem if the same DbContext is shared between services. As I see it you can approach the problem from different directions (in no particular order).

  1. Adjust the logic in the mapper. Make sure that the "reduction" of items in i.somearray is done in _mapper.Map and make sure that the mapper doesn't affect the entity itself. If you are using a library as AutoMapper this shouldn't be to hard. The problem here is that you have a condition, which I assume may be vary from service to service even tough the types are the same? In such a case you can pass mapping-instructions to your map and thus use the same mapping between services.

  2. Reduce the items returned in the query.

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

    A more concrete example can be found here. This also has the benefit of reducing the payload fetched from the database.

  3. Use no tracking. When enabled, entities will practically be read-only. Thus, any changes made to them will not be written back to db. Any other service will not be able to persist an entity fetched from another service (as long as it wasn't tracked). This is probably the easiest solution.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文