-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
EF Core doesn't lazy-load virtual navigation properties #3312
Comments
The short answer is that EF7 does not currently support automatic lazy loading in the same way that EF6 did. I've seen it discussed in a few places and if anyone is better informed feel free to correct me but as far as I am aware it is fairly far down their priority list and if some posts I have read are to be believed, that's if they choose to implement it at all. |
@HenryGarle is right. There is no automatic lazy loading support in EF7, and we don't have a clear outlook on its priority. Lazy loading can make data access easier to deal with but it has pitfalls such as potentially producing very inefficient query patterns that cause many more database roundtrips than necessary. By comparison eager loading (i.e. the |
Wow. I am surprised - while far from perfect, removing Lazy Loading is a pretty major change that I've not seen explicitly stated in any of the docs, nor in the ASPNET/Announcements repo, no mention of it in the Guiding Principles, etc. Can you point me at any docs where this is stated? @divega: You state that EF7 doesn't support lazy loading, but in #3318 you state that "... and if lazy loading is enabled it will work the same for collection and reference properties." which indicates that LazyLoading can be enabled, no? |
Edited that last sentence to make it clearer that I was referring to EF6 behaviors. |
Thanks. Assume there's currently no statement on the removal of Lazy Loading? Any chance the EF team could add Announcements and/or document breaking changes like these - it'd be a huge help to those of us trying to get started (and help others do so) on the new bits? |
@bitcrazed Thanks for the feedback. Since we are still pre-release, there is no documentation on what is a "breaking" change from EF6 to EF7. As EF7's features stabilize, we will write more docs. I've added dotnet/EntityFramework.Docs#40 to help capture this feedback. |
Agreed, we will have some "Should I be using EF7" documentation and the "What's new in EF7" and "What's removed in EF7" content will be a large part of that. |
@natemcmaster Many thanks. I know it's early days for the EF team but when developing in the open like this, timely release of breaking changes vs. a previous version is pretty important. I think that official guidance on issues like this (along with no automatic many-to-many support) will be crucially important for many who need to decide between using EF7 or EF<=6 for new projects that may be shipping in the next 6-8 months. I'll be blogging on subjects like this as I find them anyhow, but an official position would be most useful. |
@rowanmiller For me, this is just another example why I think this project should have been called something other than EntityFramework - because it's not EF. While EF7 retains some vestiges of EF concepts, I think it's sufficiently (so very) different from EF that it'd be easier to explain what it is if it wasn't called EF! |
@divega, @rowanmiller |
@JeffGillin - here is the backlog item tracking Lazy Loading #3797 |
I'm using Identity and EF7. I have extended my ApplicationUser class with a navigation property like so:
In the account controller, the user is loaded via the Identity framework like so:
How would you get the additional data to load? I thought lazy loading would take care of this. |
Lazy loading is not implemented in EF7 (backlog item is #3797). When you query, you can use the Include method to bring in related data:
|
Understood @rowanmiller , but that does mean I have to query the entire object twice, in this case, right? First time, the Identity _userManager does the query. Then, if it comes back gtg, I need to query the object AGAIN to load the nav property, if I'm understanding you correctly. Is there also currently no way to hydrate specific properties on an object? Like "LoadProperty", for instance? Seems that without lazy loading, that would be a minimum requirement, considering I might not always have control over the initial query. [Edit] Nevermind. I guess I'm a bit ignorant on how objects are tracked. It looks like that line of code you sent adds the additional property data to the originally queried object, not just a newly returned one. |
Correct, or if you just query for the related object then EF will also join things up in-memory for you.
|
Thanks @rowanmiller this is very helpful. I'm having trouble with using an include to bring in the related data. var _gifts = _context.Gifts.Include(g => g.Image).Where(g => g.Registry.ApplicationUser.Id == usrId) throws the error: Unable to cast object of type 'System.Linq.Expressions.FieldExpression' to type 'System.Linq.Expressions.ParameterExpression' I don't understand this error - my code seems to be the same as that above. If I remove the Include it works, but I then need to have: await _context.Images.ToListAsync(); to load the Images (which is bad because this loads all images, not just those for the selected gifts). How can I just load the Images selected in _gifts? The models are:
}
|
Hey, I asked this question on Stack Overflow: http://stackoverflow.com/questions/34790533/how-do-i-simplify-the-access-of-a-has-many-relationship-with-the-entity-framewor It seems that implementing lazy loading would solve the root of my problem. But If there was a dynamic work around to achieve something similar, I'd be up for that as well. //This is what I have so far
public object RelationshipFor(string relationship)
{
using (var db = User.DbContext())
{
var myTable = (DbSet<DatabaseModels.User>)db.Send(RelationshipName);
var myInclude = myTable.Include(i => i.Send(relationship));
var meWithRelationship = myInclude.First(MatchesIdFor);
return meWithRelationship.Send(relationship);
}
}
public bool MatchesIdFor(object item)
{
return (long)item.Send(IdColumn) == Id;
} but I get the error:
|
Also, is there a way to dynamically cast an object of a DbSet? |
@dwdickens and @NullVoxPopuli the bug being tracked by this issue has been resolved. Please open new issues for the problems you are encountering. |
@dwdickens when you open a new issue can you include a full code listing (or project) that we can use to reproduce the issue. There is probably a specific pattern in your model that is causing the error to occur. |
This code
in sql query genarate two joins "Products". Is it possible optimize this expression? |
I am also missing lazy loading in EF7 👎 |
@christophedemey , why? It's helpful mainly when querying for entities that have lengthy string properties. |
I appreciate the performance reasons for discouraging lazy loading. Developing an app now with EF, it gets confusing if a bug is due to bad db data or a failure to properly load - null is ambiguous. Why doesn't EF throw an error if you try to access data that hasn't been loaded? On 7 Mar 2016, at 6:05 AM, Doron Grinzaig notifications@github.com wrote: @christophedemey , why? It's helpful mainly when querying for entities that have lengthy string properties. — |
@gdoron if you put it this way you are definitly right ! |
@dwdickens, you will get a null reference exception if you don't load the navigation property (and you didn't init the property in the ctor), and an empty list if you did, so it is already easy to understand. I'm happy with the current implementing o navigation properties in EF core. |
@rowanmiller I had the same problem as he did, but my issue isn't solved yet. When I try to reference the "context" I am using ApplicationDBContext and though it has an option called "Users" That doesn't include a method called "Include" I'm using ASP5, MVC6. So I either need a different method, or a way to get the right context so I can use this:
|
@willotheblessed make sure you have a using for the |
That did it! Thanks! |
@rowanmiller Could I ask you a tangentially related question? I noticed VS doesn't offer hints to add missing using namespace statements for extension methods the way it does for other references (right click on red-lined code -> Quick Action). It seems like with this version of ASP.NET there's more extension method stuff going on, so it's been much more noticeable lately. Could you suggest an appropriate place for me to submit that feature request? |
@SimonOrdo you can submit VS ideas at http://connect.microsoft.com/VisualStudio That said, quick actions does offer to add namespaces for extension methods for me: |
here movie class is having public virtual ICollection Reviews { get; set; } . Don't know why it is not getting printed properly. |
|
My Mistake done. Here is the completed code var model = UOW.Movies.GetAll().Include(x => x.Reviews).OrderByDescending(m => m.Reviews.Count) |
If using .NET Core and Entity Framework Core, and [Stackoverflow Answer]((https://stackoverflow.com/questions/43127957/include-not-working-in-net-core-returns-one-parent) Also, in Startup.cs make sure you have this at the top: using Microsoft.EntityFrameworkCore; *For older .NET you can use the [JsonIgnore] attribute as well. |
@joehoeller The Stackoverflow page is removed! |
The jerks at Stack removed it bc they have serious control issues, even though I answered the ques, see here: https://www.linkedin.com/pulse/include-working-net-core-only-returns-one-parent-entity-joe-hoeller- |
Also, Im not sure that this will help, but try placing "app.UseResponseBuffering();" inside public void Configure located in Startup.cs. |
@joehoeller They closed it because that's not how you answer your own question. You first post the question and then answer it otherwise it's confusing to future readers. If you had actually read the guidelines for posting before posting you would have known this and not got upset. |
@joehoeller not work form me Iam using .NET Core 2.0 and Entity Framework Core, and .Include(x => x.TableName ) returning one row of data i try:
Exists another alternative ? |
The GroupEditModel is part of a CRUD for editing a Group. First the object is declared and annotated Then in OnGetAsync() it is filled. Then the object comes back in the OnPostAsync(). Here the object is filled by the binder, but the Navigation properties are null. How do I get these filled by the binder, or fill them easily after that occurs? |
@lukemason76 - Did you enable lazy loading proxies? EF Core does not lazy load virtual navigations by default. See https://docs.microsoft.com/en-us/ef/core/querying/related-data#lazy-loading If you are still having issues after following the documentation, please file a new issue with detailed repro steps. |
I am developer that has ran into this issue with EF7 and I have long since decided to just build implement DAL that gets around the issue. this lazy loading issue was the driving decision to resurrect subsonic for me. https://github.com/kccarter76/SubSonic-Core |
@kccarter76 You realize that EF7 doesn't actually exist, right? |
Issue: EF7 may not be lazy-loading all entities in a graph of related entities, despite all entities' navigation properties being virtual:
I built a basic blog atop EF6. It behaves as expected and correctly models many-to-many relationships - in this case, the fact that posts may have zero or more authors.
I then rewrote this basic blog atop EF7.
This is where I found out that EF7 doesn't currently support modelling many-to-many relationships (see #1368) and requires one to manually create and handle the join entity itself.
So, I added the PostAuthor type to the app's model.
When querying the model, I was found that EF wasn't populating the
Blog
'sPosts
collection requiring me to.Include(blog => b.Posts)
and then didn't populate thePost
'sPostAuthors
collection, requiring me to.ThenInclude(p=>p.PostAuthors)
. Imagine my surprise, then, when I also found that I had to.ThenInclude(pa=>pa.Authors)
. The net result? This:My expectation is that since all the entities' navigation properties are virtual (
Post
,PostAuthor
and Author ) that they'd be lazy-loaded on demand.What am I doing wrong here?
TIA,
The text was updated successfully, but these errors were encountered: