简体   繁体   中英

Db context usage in multiple services

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.

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM