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

Databinding: Guide users to not bind against DbSet.Local directly #8898

Closed
divega opened this issue Jun 19, 2017 · 13 comments
Closed

Databinding: Guide users to not bind against DbSet.Local directly #8898

divega opened this issue Jun 19, 2017 · 13 comments
Labels
area-dbcontext closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@divega
Copy link
Contributor

divega commented Jun 19, 2017

In EF Core DbSet.Local is more efficient than in EF6 but doesn't have stable order, so it is not good for databinding. For databinding you are supposed to call ToObservableCollection (for the WPF flavor) or ToBindingList (for the WinForms flavor).

This is already in the XML documentation but nothing prevents users from binding directly to DbSet.Local.

We should consider implementing IListSource.GetList() to throw an informative exception like we do for query, but we also need to verify that doing so will help for WPF.

@ajcvickers
Copy link
Member

Leaving open to answer the WPF question.

@ajcvickers ajcvickers removed this from the 2.0.0 milestone Jun 28, 2017
@ajcvickers ajcvickers added this to the Backlog milestone Jun 30, 2017
@ajcvickers ajcvickers removed their assignment Jun 30, 2017
@divega divega removed this from the Backlog milestone Jan 12, 2019
@divega
Copy link
Contributor Author

divega commented Jan 12, 2019

Note for triage: This issue had one question pending: I tried binding in a WPF to an observable collection that implements IListSource and GetList was called.

Given that in 3.0 we want to have better WPF/WinForms support, I would like to discuss if we want to do this (if we decide not to do it, maybe we should close the issue?).

On the other hand, this reminded me of #14231, which was recently reported and says DbSet.Local isn't good for iterating either... I can't remember what DbSet.Local is good for :trollface:. Should we make changes?

@ajcvickers ajcvickers assigned ajcvickers and unassigned divega Jan 14, 2019
@ajcvickers ajcvickers added this to the 3.0.0 milestone Jan 14, 2019
@ajcvickers
Copy link
Member

We should look at this as part of the databinding experience for 3.0--see #14318

ajcvickers added a commit that referenced this issue Mar 4, 2019
Part of #8898
Fixes #14231

Investigation into DbSet.Local shows that:
* Iteration over tracked entities had a lot of LINQ code; fixed by un-LINQing
* Multiple composed iterators cause slow-down; fixed by giving LocalView it's only IStateManager method
* Filtering causes slow-down; fixed by splitting storage into multiple dictionaries. Makes lookup for entity instance slightly slower.
* Calculate Count lazily

This means that DbSet.Local iteration is now about 3x faster, although it depends a lot on what is being tracked. Getting an ObservableCollection and then iterating over that _once_ is slower than just iterating over the entries once. Iterating over the ObservableCollection multiple times is still faster than iterating over DbSet.Local multiple times. This seems like a reasonable trade-off. If the application does heavy iteration, then creating a new collection for that seems reasonable.

With regard to #8898, the layering we have still seems correct, so moving forward with the breaking changes there.
ajcvickers added a commit that referenced this issue Mar 4, 2019
Part of #8898
Fixes #14231

Investigation into DbSet.Local shows that:
* Iteration over tracked entities had a lot of LINQ code; fixed by un-LINQing
* Multiple composed iterators cause slow-down; fixed by giving LocalView it's only IStateManager method
* Filtering causes slow-down; fixed by splitting storage into multiple dictionaries. Makes lookup for entity instance slightly slower.
* Calculate Count lazily

This means that DbSet.Local iteration is now about 3x faster, although it depends a lot on what is being tracked. Getting an ObservableCollection and then iterating over that _once_ is slower than just iterating over the entries once. Iterating over the ObservableCollection multiple times is still faster than iterating over DbSet.Local multiple times. This seems like a reasonable trade-off. If the application does heavy iteration, then creating a new collection for that seems reasonable.

With regard to #8898, the layering we have still seems correct, so moving forward with the breaking changes there.
ajcvickers added a commit that referenced this issue Mar 5, 2019
Part of #8898
Fixes #14231

Investigation into DbSet.Local shows that:
* Iteration over tracked entities had a lot of LINQ code; fixed by un-LINQing
* Multiple composed iterators cause slow-down; fixed by giving LocalView it's only IStateManager method
* Filtering causes slow-down; fixed by splitting storage into multiple dictionaries. Makes lookup for entity instance slightly slower.
* Calculate Count lazily

This means that DbSet.Local iteration is now about 3x faster, although it depends a lot on what is being tracked. Getting an ObservableCollection and then iterating over that _once_ is slower than just iterating over the entries once. Iterating over the ObservableCollection multiple times is still faster than iterating over DbSet.Local multiple times. This seems like a reasonable trade-off. If the application does heavy iteration, then creating a new collection for that seems reasonable.

With regard to #8898, the layering we have still seems correct, so moving forward with the breaking changes there.
ajcvickers added a commit that referenced this issue Mar 5, 2019
Part of #8898
Fixes #14231

Investigation into DbSet.Local shows that:
* Iteration over tracked entities had a lot of LINQ code; fixed by un-LINQing
* Multiple composed iterators cause slow-down; fixed by giving LocalView it's only IStateManager method
* Filtering causes slow-down; fixed by splitting storage into multiple dictionaries. Makes lookup for entity instance slightly slower.
* Calculate Count lazily

This means that DbSet.Local iteration is now about 3x faster, although it depends a lot on what is being tracked. Getting an ObservableCollection and then iterating over that _once_ is slower than just iterating over the entries once. Iterating over the ObservableCollection multiple times is still faster than iterating over DbSet.Local multiple times. This seems like a reasonable trade-off. If the application does heavy iteration, then creating a new collection for that seems reasonable.

With regard to #8898, the layering we have still seems correct, so moving forward with the breaking changes there.
ajcvickers added a commit that referenced this issue Mar 5, 2019
Part of #8898
Fixes #14231

Investigation into DbSet.Local shows that:
* Iteration over tracked entities had a lot of LINQ code; fixed by un-LINQing
* Multiple composed iterators cause slow-down; fixed by giving LocalView it's only IStateManager method
* Filtering causes slow-down; fixed by splitting storage into multiple dictionaries. Makes lookup for entity instance slightly slower.
* Calculate Count lazily

This means that DbSet.Local iteration is now about 3x faster, although it depends a lot on what is being tracked. Getting an ObservableCollection and then iterating over that _once_ is slower than just iterating over the entries once. Iterating over the ObservableCollection multiple times is still faster than iterating over DbSet.Local multiple times. This seems like a reasonable trade-off. If the application does heavy iteration, then creating a new collection for that seems reasonable.

With regard to #8898, the layering we have still seems correct, so moving forward with the breaking changes there.
@ajcvickers
Copy link
Member

I started to work on this, but it turns out that we already did this for 2.0. See #9003

The only reason this issue was still open was to check if WPF calls the method, which has now been done., so closing.

@ajcvickers ajcvickers removed this from the 3.0.0 milestone Mar 23, 2019
@ajcvickers ajcvickers removed this from the 2.0.0 milestone Feb 13, 2022
@ajcvickers ajcvickers reopened this Feb 13, 2022
@ajcvickers
Copy link
Member

@roji I think this is a consequence of ConfigureAwait false. Fixup can now happen in a different thread, and this then means that events in the observable collection (or other notifications) are triggering calls into the U.I. on the non-U.I. thread.

/cc @AndriySvyryd

@roji
Copy link
Member

roji commented Feb 14, 2022

@ajcvickers we did do #23971 to preserve the synchronization context when accepting changes - is there something here with Local.ToObservableCollection that goes beyond that (am not too familiar with that...)?

@ajcvickers
Copy link
Member

@roji Yes, it gets called when materializing entities/doing fixup after queries.

@roji
Copy link
Member

roji commented Feb 14, 2022

Ok. Just to make sure given the issue title: is this something we want to recommend/support? (I have no opinion here whatsoever, just asking)

@ajcvickers
Copy link
Member

Let's discuss in triage. This issue is unrelated--just where the comment was made.

@AndriySvyryd AndriySvyryd added type-bug and removed closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. labels Feb 15, 2022
@AndriySvyryd AndriySvyryd assigned roji and unassigned ajcvickers Feb 15, 2022
@AndriySvyryd AndriySvyryd added this to the 7.0.0 milestone Feb 15, 2022
@roji
Copy link
Member

roji commented Feb 15, 2022

Triage: I'll take a look to see if it could make sense to do ConfigureAwait(true) for this path, like we did for SaveChanges. Otherwise we could consider some sort of per-query or context option to just do true everywhere, if we think that's important.

@OlegFj17
Copy link

EnableCollectionSynchronization helped me! sorry to stir up your issue.. )

@ajcvickers
Copy link
Member

Opened #27533

@ajcvickers ajcvickers added closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. and removed breaking-change labels Mar 1, 2022
@ajcvickers ajcvickers modified the milestones: 2.0.6, 2.0.0 Mar 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dbcontext closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

No branches or pull requests

6 participants