2

I have been trying to build a CMS using .NET Core 2.1 with a feature to stage web content changes, therefore I have three sites in my system architecture:

  1. CMS Site - User could propose changes to web content through the CMS, and the changes will be pushed to the Staging/Production Site after being approved by admin.
  2. Staging Frontend - The frontend web for internal UAT purposes, displays all approved/unapproved web content.
  3. Production Frontend - The frontend web facing the public, displays only approved web content.

I have three DbContext instances injected for achieving the above:

  1. CmsContext - Stores first-round web content changes proposed by a user.
  2. StagingContext - Where the staging web frontend reads web content
  3. ProductionContext - Where the production web frontend reads web content

The problem I encountered was, when I try to do the following (with lazy-loading enabled):

var entity = await stagingContext.FindAsync(entityType, entityId);
productionContext.Update(entity);
await productionContext.SaveChangesAsync();

navigation properties are not updated as what I have expected.

I have also tried the ChangeTracker.TrachGraph approach, but it does not iterate through navigation properties.

I understand that the reason might be, even though lazy-loading is enabled, the navigation properties are never accessed before, so they are not filled up with values for productionContext to update.

I have read through the Microsoft Docs before I post this question, but could not figure out the correct way to do this. May I have your kind help on this guys? thanks

clifflau1120
  • 188
  • 1
  • 1
  • 8
  • Why having separate DbContext? Do those contexts have a different database or you're doing it for "DDD bounded contexts"? – Konrad Oct 15 '18 at 07:25
  • @Konrad The idea is like: 1. User proposes web content changes via the CMS, and the CMS saves these new content to `CmsContext` 2. Admin do a preliminary check on these changes, and push these to `StagingContext`, so that the Staging Frontend Web could display these proposed but not final-checked content. 3. Admin do a final check on these changes, and push these changes to 'ProductionContext', so that the Production Frontend Web could only show so-called 'launched and approved' changes. – clifflau1120 Oct 15 '18 at 09:42
  • So my problem is, I need to duplicate an entity and its related data from one context to another (`StagingContext` -> `CmsContext`), but when I do this using the codes above, related data are not saved to CmsContext. – clifflau1120 Oct 15 '18 at 09:43
  • `StagingContext` and `ProductionContext` are different databases that shares a same structure, while `CmsContext` has some more metadata than those. – clifflau1120 Oct 15 '18 at 09:46
  • You say that you use lazy loading but properties are never accessed before, so I think you have to eager load them with `Include`. You have to replace `FindAsync` call with `Include` to eager load all navigation properties you need, and then use `SingleOrDefaultAsync` or `SingleAsync`. Because properties are lazily loaded, they never get loaded because you never access them and EF Core has nothing to track. – Konrad Oct 15 '18 at 11:31

1 Answers1

0

You say that you use lazy loading but properties are never accessed before, so I think you have to eager load them with Include.

You have to replace FindAsync call with Include to eager load all navigation properties you need, and then use SingleOrDefaultAsync or SingleAsync. Because properties are lazily loaded, they never get loaded because you never access them and EF Core has nothing to track when you call productionContext.Update(entity);

I don't think calling Update accesses any properties for lazy loading to work, it just sets EntityState. I'm not sure if call to SaveChangesAsync change that. But if it doesn't work then it's possible that it's not lazily loaded.

If you just want to eager load everything you can take a look at Entity Framework Core 2.0.1 Eager Loading on all nested related entities

Konrad
  • 6,385
  • 12
  • 53
  • 96