Entity Framework and deferred execution on lazy loaded ICollection - entity-framework-4

I'm using Entity Framework 4.1 and I have a one to many relationship.
When I query the lazy loaded ICollection<T> on the one side of the relationship the whole recordset is returned and it doesn't defer the execution like when I'm querying direct from the Repository IQueryable interface.
Is there any way to make this use deferred execution so I can do a query like
Model.Childs.Where(x => !x.Deleted.HasValue).Skip(10).Take(5);
Thanks in advance,
Tom.

That is principle of lazy loading in EF. Your navigation property is defined in your code and any LINQ query defined on that property is LINQ-to-Objects - it is not translated to SQL. Lazy loading always loads whole collection (as well as eager loading). When you query your repository you are querying IQueryable and using LINQ-to-Entities which is translated to SQL.
As workaround use explicit loading:
dbContext.Entry(Model).Collection(m => m.Childs)
.Query()
.Where(c => !c.Deleted.HasValue)
.Skip(10)
.Take(5)
.Load();

Related

Populating child objects in SDN4 in a convenient way

In SDN3.4.0 when an entity is loaded from database, empty child objects (no #Fetch annotation) are populated with only ids present. In SDN4 this doesn't happen and child objects are not populated with ids (for depth 0). Wanted to understand the reason for this change ?
Is there a way to directly populate child objects in SDN4 when entities are queried using complex cypher queries either from session or repository (using #Query).
The default load level is 1 when using the session or repository load methods. This means all objects directly related to the entity are loaded.
You can override this depth.
#Query does not support depth specification at the moment.

How to prevent lazy loading of entities that were already manually loaded when navigating a property in EntityFramework

Background:
I am using EF4 and ObjectContext. To optimze retrieval of complex object hierarchies, I manually execute database queries and then use ObjectContext.Translatey<T>(DataReader, entitySetName, mergeOptions.AppendOnly) to turn data rows into entities. I then attach the entities to the ObjectContext with Attach method. This also fixes relations between entities.
The problem:
After everything is loaded and set up I try to navigate from parent entity to a child entity (for example Parent.Childs.First()), but EF hits the database to load the kids, even though all the child entities are already present in the ObjectContext and EntitySet. It looks like the reason for this is that parent.Childs.IsLoaded is set to false which makes EF think that it still needs to load the relation.
Question:
How can I tell EF that EntitySet has already been loaded?
Is there a supported way to set RelatedEnd.IsLoaded to true. I wouldn't like to mess with the calling the RelatedEnd.SetIsLoaded internal method.
I found a smilar question here but it relates to DbContext and has no satifying answer ;-)
Matra
It looks like this was implemented in this change:
http://entityframework.codeplex.com/workitem/269
You can now iterate through your entities and tell them that their child collections are already loaded:
foreach (var entity in loadedEntities)
context.Entry(entity).Collection(a => a.SomeChildCollection).IsLoaded = true;
This will prevent entities in SomeChildCollection from being loaded when they are accessed from entity.
I'm not exactly sure what version of EF this appeared in but I'm guessing 6.0.0.
The only way to solve this is to turn off lazy loading. The question you have found on MSDN asks about DbContext but the answer mentions that there is no way to change the value in underlying libraries - ObjectContext API (= EF4 in your case) is the underlying library. Even in .NET 4.5 (EF5) setting IsLoaded is still not available on public API.

POCO entities and IsLoaded() in EF 4.1

I'm working on an enterprise application that leverages the repository pattern on top of EF 4.1 with eager loading to POCO entities. Typically, a call will look like this:
public IEnumerable<SomeEntity> List(DateTime date)
{
using (var context = ContextFactory.CreateContext()) // Returns a DbContext
{
return CreateQuery<SomeEntity>(context)
.Include("PATH1")
.Include("PATH2")
.Where(...)
.AsNoTracking()
.ToList();
}
}
At some point, the business layer translates these entities into DTOs that are then transmitted via WCF to a web application.
As eager loading is rather expensive, I'm trying to keep .Include's to a minimum, so sometimes related properties are (eagerly) loaded and sometimes they're not. However, the business layer has no idea when related properties are present in the entity, so I get an ObjectContextDisposedException, the reason for which is perfectly clear to me and I don't intend to change the basic strategy (i.e. dispose the context right after eager loading the entities).
However, I need to check whether a particular related property is loaded or not, checking if the related object is null doesn't work (ObjectContextDisposedException), nor is there any kind of IsLoaded() method I could use.
Am I stuck with a try/catch block here or are there any other options?
Turn off lazy loading and check for null will work. Your current solution cannot use lazy loading because you dispose context immediately after running the query:
context.Configuration.LazyLoadingEnabled = false;

Can you map the results of a manual SQL query to objects in Entity Framework?

In LINQ, you can write a manual SQL query, take the results from it and have LINQ "map" those into the appropriate properties of your Model classes (or at least, I'm pretty sure I read you can do that).
Is it possible to do something like that in Entity Framework?
I have an web app that's using EF, and it's CPU usage is ridiculously high compared to the traffic it has, and profiling it in my machine, all that time is (predictably) spent in the DB functions, and the largest portion of that time (> 85%) is spent by EF "generating" SQL and doing stuff before actually executing a query.
So my reasoning is that I can just go in and hardcode the SQL queries, but still use my populated Model properties in my view.
Is this possible? If so, how would I do it?
Thanks!
Daniel
So what you want to do is hydrate an object from an IDataReader? It's pretty easy to write code to do this (hint: reflection! or you can get fancy and use a member initialization expression) or you can Google for myriad existing implementations on the Internet.
You can do this within EF using ObjectContext.ExecuteStoreQuery<T> or ObjectContext.Translate<T> if you already have a DbDataReader.
1 ObjectContext.SqlQuery in EF 4.0
As said #Jason, you can :
IEnumerable<MiniClient> results =
myContext.SqlQuery<MiniClient>("select name,company from client");
Reference : https://msdn.microsoft.com/en-us/library/dd487208.aspx
DbContext.Database.SqlQuery, in EF 4.1+
In Entity Framework 4.1+, DbContext is preferable to use to ObjectContext, so you'd better use :
DbContext myContext= new DbContext();
IEnumerable<MiniClient> results =
myContext.SqlQuery<MiniClient>("select name,company from client");
Reference : https://msdn.microsoft.com/en-us/library/jj592907(v=vs.113).aspx
dynamic and anonymous class
Too lazy to create a projection class like MiniClient ?
So you should use anonymous type and dynamic keyword :
IEnumerable<dynamic> results =
myContext.Clients.Select( c => new {Name = c.Name, Firstname = c.Firstname});
Note : In all the samples MiniClient is not an entity of the DbContext.
(=not a DbSet<T> property)

Eager Loading with Entity Framework and Asp .net mvc (From a rails background)

I have a few tables that reference the same table. For example:
Person has an address.
Business has an address.
When using the models I would like to do this in the controller:
person.Address.Zip
business.Address.Zip
I'm coming from a rails background where I can just declare a relationship and have all the above functionality. Force loading of the address when I get the object (person or business).
I'm new to entity framework, and I'm struggling with how to achieve that functionality. I can't include the table in both models (person and business). If I use repository pattern and add the objects to a partial for the class, then I'm using lazy loading.
Am I looking at this wrong? Any suggestions for patterns I could use?
If your using Entity Framework 4.0 with Visual Studio 2010 lazy loading is automatic.
If your using Entity Framework 1.0 your life just got harder...
To eager load with EF1 you have to use the Include() method on your ObjectQuery and specify which navigation properties ( address ). For example:
ModelContainer.Persons.Where(#p => #p.Id == 39 ).Include("Address")
For "lazy" loading you have to manually load all of the FK associations manually. For example:
var myPeople = ModelContainer.Persons.Where(#p => #p.Id == 39
if( !myPeople.Address.IsLoaded() )
myPeople.Address.Load()
Another option is to modify how EF1 generates your model types and include lazy loading out of gates.
http://code.msdn.microsoft.com/EFLazyLoading
Previously, I was creating an ADO.NET Entity Data Model for each controller.
Now I've created one Data Model for all tables (it's not a monstrous db). That way I can include the tables when I query for eager loading.
If anyone has a better suggestion. Let me know. If anyone knows the correct behavior with a large database, please comment. Would you want one large edmx file to represent the database?
Ideally you should be able to traverse the object model to get most of the data you need, starting with a reference to the current user object.

Resources