Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entry.Reload doesn't reload owned object. #16186

Closed
IvanZheng opened this issue Jun 21, 2019 · 11 comments · Fixed by #18434
Closed

Entry.Reload doesn't reload owned object. #16186

IvanZheng opened this issue Jun 21, 2019 · 11 comments · Fixed by #18434
Assignees
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. punted-for-3.0 type-bug
Milestone

Comments

@IvanZheng
Copy link

Entry.Reload doesn't reload owned object.

Further technical details

EF Core version: 3.0.0-preview5.19227.1
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Visual Studio 2019 16.1.3

@IvanZheng
Copy link
Author

@AndriySvyryd I think this issue still exists. Please try the following steps:

  1. load a entity from dbcontext and hold/suspend the thread processing.
  2. Change owned object value in the database (mssql).
  3. entry.reload(). I found the entity's owned object's values are not updated.

@smitpatel
Copy link
Member

@AndriySvyryd - Can you suggest where and how should I add a test for this?

@AndriySvyryd
Copy link
Member

@smitpatel Optimistic concurrency tests would be an appropriate place, there should already be owned types in the model.

smitpatel added a commit that referenced this issue Oct 17, 2019
Specifically for owned entities

Resolves #16186
Resolves #18366
@smitpatel smitpatel added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Oct 17, 2019
smitpatel added a commit that referenced this issue Oct 17, 2019
Specifically for owned entities

Resolves #16186
Resolves #18366
smitpatel added a commit that referenced this issue Oct 18, 2019
Specifically for owned entities

Resolves #16186
Resolves #18366
@IvanZheng
Copy link
Author

@AndriySvyryd Which nuget package of the EFCore has included this fix? I have tried Microsoft.EntityFrameworkCore v3.1.0-preview1.19506.2 and it doesn't work for my case.

@AndriySvyryd
Copy link
Member

@IvanZheng You need to get the nightly build of v3.1.0-preview2

@IvanZheng
Copy link
Author

@AndriySvyryd I tried 3.1.0-preview2.19522.3 just now. It still doesn't work. Only the root level properties will be reloaded but the owned objects won't.

@AndriySvyryd
Copy link
Member

@IvanZheng You need to call Reload on the owned entry, not the root:

entry.Reference(e => e.Address).TargetEntry.Reload();

#13890 tracks reloading the aggregate as a whole

@IvanZheng
Copy link
Author

IvanZheng commented Oct 24, 2019

@AndriySvyryd Thank you! It works well for owned object now. I use a recursive method to reload all aggregate's entities and value objects as below. But I find another issue. If the number of the entities in CollectionEntry changed, is there a way to reload the entities in CollectionEntry? Currently it only reloads the loaded entities. I will track #13890 and hope it provide a better way to reload whole aggregate.

   `private async Task ReloadAsync(EntityEntry entityEntry, bool includeSubObjects, CancellationToken cancellationToken)
    {
        await entityEntry.ReloadAsync(cancellationToken)
                         .ConfigureAwait(false);

        if (includeSubObjects)
        {
            foreach (var referenceEntry in entityEntry.Members.OfType<ReferenceEntry>())
            {
                if (referenceEntry.IsLoaded)
                {
                    await ReloadAsync(referenceEntry.TargetEntry, 
                                      true, 
                                      cancellationToken).ConfigureAwait(false);
                }
            }

            foreach (var collectionEntry in entityEntry.Members.OfType<CollectionEntry>())
            {
                if (collectionEntry.IsLoaded)
                {
                    foreach (var entity in collectionEntry.CurrentValue)
                    {
                        await ReloadAsync(Entry(entity),
                                          true,
                                          cancellationToken).ConfigureAwait(false);
                    }
                }
            }
        }

        (entityEntry.Entity as AggregateRoot)?.Rollback();
    }`

@AndriySvyryd
Copy link
Member

@IvanZheng Reloading collections is tracked by #13620 You might be better off just querying the whole aggregate again.

@IvanZheng
Copy link
Author

@AndriySvyryd Thanks again! Follow the post of stackoverflow in #13620, I can reload collections.

   `private async Task ReloadAsync(EntityEntry entityEntry, bool includeSubObjects, CancellationToken cancellationToken)
    {
        if (includeSubObjects)
        {
            foreach (var referenceEntry in entityEntry.Members.OfType<ReferenceEntry>())
            {
                if (referenceEntry.IsLoaded)
                {
                    await ReloadAsync(referenceEntry.TargetEntry, 
                                      true, 
                                      cancellationToken).ConfigureAwait(false);
                }
            }

            foreach (var collectionEntry in entityEntry.Members.OfType<CollectionEntry>().ToArray())
            {
                if (collectionEntry.IsLoaded)
                {
                    foreach (var entity in collectionEntry.CurrentValue.OfType<object>().ToArray())
                    {
                        var subEntityEntry = Entry(entity);
                        await ReloadAsync(subEntityEntry,
                                          true,
                                          cancellationToken).ConfigureAwait(false);
                        subEntityEntry.State = EntityState.Detached;
                    }

                    collectionEntry.CurrentValue = null;
                    collectionEntry.IsLoaded = false;
                }
            }
        }
        await entityEntry.ReloadAsync(cancellationToken)
                         .ConfigureAwait(false);
        (entityEntry.Entity as AggregateRoot)?.Rollback();
    }` 

@ajcvickers ajcvickers modified the milestones: 3.1.0, 3.1.0-preview2 Oct 24, 2019
@ajcvickers ajcvickers modified the milestones: 3.1.0-preview2, 3.1.0 Dec 2, 2019
@Laurianti
Copy link

I think this issue it was underestimated. I think that is counter-intuitive that I have to explicitly reload the owned types.
When at the same time they are included automatically in queries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. punted-for-3.0 type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants