I have an MSSQL storedproc, which I'm executing via EF4 through the context. This results an IEnumerable<T>, which returns and deserializes all the result from the SP.
The problem is, that I want to do eager loading on some of the navigation properties.
Calling .AsQueryable().Include("Navigation_Property_Path").ToArray() does not help.
Is there any way to eager load navigation properties of entities already in the context?
I don't really want to alter my SP, to return IDs of my entities (basically int array), and then execute select on the EF.Context using the ID for WHERE, and then using the Include.
No, because SP invocation is not composable at the SQL level. EF does not support eager loading for that.
Maybe you can switch from an SP to an inline TVF?
Related
In entity framework 6 is it possible to mix raw SQL generated dynamically with IQueryable like this:
IQueryable<Tree> tree_query = context.Trees.Where(t=>t.Height> 2);
IEnumerable<int> tree_additional_filter = context.Database.SqlQuery<int>("SELECT Id FROM TREE_VIEW WHERE Width < 1");
IQueryable<Tree> final_query = from tree in tree_query
join filtering_tree in tree_additional_filter on filtering_tree.id equals tree.id
select tree;
This produces a result as is, but the "tree_additional_filter" is executed in the database in order to construct the final_query. How can I make entity framework construct only one query from this?
I need this to create dynamic filter fields which work together with static ones.
I also tried creating TREE_VIEW entity with only Id column, which I know to always be there.
Used System.Linq.Dynamic to construct "where" clause dynamically on a TREE_VIEW entity which has only Id property, but apparently expressions can't be built if properties do not exist in the Type.
In entity framework 6 is it possible to mix raw SQL generated dynamically with IQueryable like this:
No. Notice that Database.SqlQuery returns an IEnumerable<T>, not an IQueryable<T>. Therefore any additional query expressions will be executed against the query results using LINQ to Objects.
Query Composition with raw SQL queries was introduced in EF Core.
I managed to do it.
Using Dynamic type generation to create a type (NewDynamicType) from fields which I got selecting top 1 from my TREE_VIEW. Attached the NewDynamicType to the db context via DbModelBuilder.RegisterEntityType in OnModelCreating.
With System.Linq.Dynamic then I could construct IQueryable selecting from context.Set(NewDynamicType) any fields the user wants to filter by.
Join into final_query like in my question.
Now my HTML form gets fields from the database view and in each distibution I can have different filters defined without having to write any c#.
Eager Loading:
context.Cars.Include(c=>c.Orders)
Explicit Loading:
context.Entry(c).Collection(x => x.Orders).Load();
what's the differences between Eager Loading and Explicit Loading? is it just syntax differences like Eager Loading uses Include while Explicit Loading uses Load?, but isn't that using Include is also an "explicit" way to load navigation properties, so why Eager Loading is not considered the same as Explicit Loading?
Eager loading is the opposite of Lazy loading, but Explicit loading is similar to lazy loading, except that: you explicitly retrieve the related data in code; it doesn't happen automatically when you access a navigation property.
You load related data manually by getting the object state manager entry for an entity and calling the Collection.Load method for collections or the Reference.Load method for properties that hold a single entity.
EntityFramework returns IQueryable objects, which essentially contain the query to the database. But these are not executed until the first time they are enumerated.
Load() executes the query so that its results are stored locally.
Calling Load() is the same as calling ToList() and throwing away that List, without having the overhead of creating the List.
Eager loading loads related entities as part of the query, i.e. the enties are loaded when the query is actually executed. This is the opposite of lazy loading where the related entities are loaded when you access them through a navigation property.
Calling Load() explicitly loads the entities on your request instead of waiting for you to access the navigation properties. It's for example useful when the initial query doesn't return any related entities (because you didn't use eager loading) and you have disabled lazy loading for whatever reason.
Currently I do obtain the user with:
ApplicationUser currentUser = await _userManager.GetUserAsync(User);
but I found that in this way it doesn't hold custom properties, for example:
public virtual UserImage UserImage { get; set; }
so every time that I need to get such property I write a method to get from the db with entity-framework, like:
public async Task<UserImage> GetUserImage(string userId) =>
await _dBcontext.UserImage.SingleOrDefaultAsync(u => u.ApplicationUserId == userId);
I would like to cache within the application(on the server, not cookie) all the user properties by only calling await _userManager.GetUserAsync(User);
There is such a way?
I'm going to assume that you're actually using Entity Framework Core, even though your question is tagged with just entity-framework. The reason is that what you have would just naturally work with Entity Framework, whereas, it will definitely not work at all with Entity Framework Core.
The key difference between the two is that EF Core does not support lazy-loading. With EF virtual navigation properties, a proxy class is dynamically created that derives from your entity class. The navigation properties are then dynamically overridden to add EF's lazy-loading logic to the getters. This causes an access of the property getter to invoke said lazy-loading logic and issue a query to the database to materialize the related entity or entities.
Since EF Core does not support lazy-loading, none of this occurs. As a result, unless you eagerly or explicitly load the relationship, it remains null. However, lazy-loading is a bad idea in the first place. It can lead to huge inefficiencies such as the 1+N query issue, where for example, you iterate over a list and end up issuing a query per item in the list to materialize some relationship on that item. If you have a lot of items, you can end up issuing a ton of queries, particularly if there's other relationships involved further in the tree. Say for example that you have a list of items with a related entity and then that related entity itself has a related entity you need to access. Now, you're issuing even more queries fetch that related entity each time. It can get out of control very quickly.
Long and short, it's far better to eagerly load the relationships you need. That will actually cause JOINs to issued in the initial query to fetch all the relationships at the same time, in just that one query. Short of that, explicit loading is still superior, as at least you are then aware of specific queries you are issuing and can clearly see if things start to get out of hand.
UserManager, however, does not give you any opportunity to do eager loads. As a result, if you use it to get the user, your only option is an explicit load of the related entity. That's not necessarily a bad thing, though, as it's only one additional query.
var currentUser = await _userManager.GetUserAsync(User);
await _dbContext.Entry(currentUser).Reference(u => u.UserImage).LoadAsync();
Now, you can access the related image.
Alternatively, you can query the user from the context, instead, and then eagerly load the image at the same time:
var currentUser = await _dbContext.Users.Include(u => u.UserImage).SingleOrDefault(u => u.Id == User.Identity.GetUserId());
That will issue just one query with a join on the image relationship.
Have a look at this thread: asp.net forum
Rules for lazy loading:
context.Configuration.ProxyCreationEnabled should be true.
context.Configuration.LazyLoadingEnabled should be true. Navigation
property should be defined as public, virtual. Context will NOT do
lazy loading if the property is not defined as virtual.
I hope this will help ;)
There is an Entity with many relationships, when i say to EF load a query on a Entity, it loads all properties(OK) with relationships(i don't want)!
This is a big penalty on performance, because i just need some properties not All relationships.
How to say EF that just load entity's property and Don't load relationships (EntityCollection<TEnitity>) ?
I want load relationships's properties by hand!
Are you sure the navigation properties are being eagerly loaded? They shouldn't be by default. Are you using POCO or Code First? If you are, then you need to make sure your navigation properties are marked "virtual". Virtual properties will be lazy loaded.
To check whether navigation properties are lazy loading or eager loading, you'll want to use a tool like SQL Profiler.
JohnnyO is correct; The default value for ObjectContextOptions.LazyLoadingEnabled is false. However, when I create a model from the database, the default value for the model is true. If you are using the generated EF classes, try setting this to false.
I'm using ObjectQuery.CreateQuery() to create eSQL query.
I want to use the ObjcetQuery.Include to load related data, like Customer => Orders so let the EF to load all the orders for customer at the same time.
The issue is that i don't want all the related objects and i want to fetch the result with condition.
Any idea?
Include will not work if you intend to materialize a master entity (Customer) with only some of the related child entities (Orders). The Entity Framework will not materialize a partially-complete type. Instead, I would recommend projecting into a new, anonymous type. Then you can include whichever Orders you like.