6

I know there is a Load method.

_dbContext.Entry(blog).Collection(b => b.Posts).Load()

But I'm try to handle concurrency conflicts, I've been add a post into blog.Posts. if call Load, it do not clear the blog.Posts, just append the existing Posts to it.

I had try:

blog.Posts = null;
_dbContext.Entry(blog).Collection(b => b.Posts).Load()

But blog.Posts become a empty collection (Zero Count).

So I want a Reload.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
huang
  • 919
  • 11
  • 22
  • It seems your basic issue is trying to use a `DbContext` in a multi-threaded manner. Each thread should have it's own instance of `DbContext` as [outlined in the "Avoiding DbContext threading issues" section of the EF documentation](https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext). – Sixto Saez Jul 16 '19 at 15:48
  • @SixtoSaez No, it's not multithead, I ensure. DbContext is from DI. I just use Class.Method to describe which class's instance and call which method. I change DbContext to _dbContext for clarifying this issue. – huang Jul 16 '19 at 16:08

1 Answers1

11

Unfortunately although EntityEntry has Reload method, there is no such method for ReferenceEntry and CollectionEntry (or in general, for NavigationEntry which the base of the previous two). And Reload methods refreshes just the primitive properties, so it can't be used to refresh the navigation properties.

Fortunately it's not that hard to create a custom one. It needs to detach (or reload?) all the current collection items, set IsLoaded to false and CurrentValue to null before calling Load.

Something like this (put it in a static class of your choice and add the necessary usings):

public static void Reload(this CollectionEntry source)
{
    if (source.CurrentValue != null)
    {
        foreach (var item in source.CurrentValue)
            source.EntityEntry.Context.Entry(item).State = EntityState.Detached;
        source.CurrentValue = null;
    }
    source.IsLoaded = false;
    source.Load();
}

so you can use the desired

_dbContext.Entry(blog).Collection(b => b.Posts).Reload();
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Is the `Detached` assign necessary ? If I only set the `source.CurrentValue = null;` then set `source.IsLoaded = false;` and `source.Load();`, is it safe ? – huang Jul 16 '19 at 18:12
  • 2
    Nope. My test shows all these are necessary. W/o detaching the items you'll get the cached items instead of fresh items from database plus added items but not deleted items. – Ivan Stoev Jul 16 '19 at 18:15
  • @IvanStoev This did not work for me. Please have a look here if you have time: https://stackoverflow.com/q/65723105/3850405 – Ogglas Jan 14 '21 at 18:00
  • I tested this solution, it works but be careful: If some elements of the reloaded collection are in lists of some other object, they will still be in those list in "Detached" state and the latest version will be added too. So you would have twice the same element, one being "Detached". – T.Trassoudaine Dec 03 '21 at 16:37