EF Load Multiple Entity References in one call to Load() - entity-framework

Using EF6.
I have a list of entity items that are detached from a dbContext. I'd like to explicit load several of the entities related to them, sometimes with through 2 or 3 levels of navigation.
I'd also like to do all this object graph loading in a single DB call if possible.
If its not possible with explicit loading techniques, I will just re-query the database for those specific item Ids and use eager loading at that point (since there is no other state I need to worry about at this point).

Related

How does EntityFramework Core mange data internally?

I'm trying to understand how EntityFramework Core manages data internally because it influences how I call DbSets. Particularly, does it refer to in-memory data or re-query the database every time?
Example 1)
If I call _context.ToDo.Where(x => x.id == 123).First() and then in a different procedure call the same command again, will EF give me the in-memory value or re-query the DB?
Example 2)
If I call _context.ToDo.Where(x => x.id == 123).First() and then a few lines later call _context.ToDo.Find(123).Where(x => x.id == 123).Incude(x => x.Children).First(), will it use the in-memeory and then only query the DB for "Children" or does it recall the entire dataset?
I guess I'm wondering if it matters if I duplicate a call or not?
Is this affected by the AsNoTracking() switch?
What you really ask is how caching works in EF Core, not how DbContext manages data.
EF always offered 1st level caching - it kept the entities it loaded in memory, as long as the context remains alive. That's how it can track changes and save all of them when SaveChanges is called.
It doesn't cache the query itself, so it doesn't know that Where(....).First() is meant to return those specific entities. You'd have to use Find() instead. If tracking is disabled, no entities are kept around.
This is explained in Querying and Finding Entities, especially Finding entities using primary keys:
The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.
Find is different from using a query in two significant ways:
A round-trip to the database will only be made if the entity with the given key is not found in the context.
Find will return entities that are in the Added state. That is, Find will return entities that have been added to the context but have not yet been saved to the database.
In Example #2 the queries are different though. Include forces eager loading, so the results and entities returned are different. There's no need to call that a second time though, if the first entity and context are still around. You could just iterate over the Children property and EF would load the related entities one by one, using lazy loading.
EF will execute 1 query for each child item it loads. If you need to load all of them, this is slow. Slow enough to be have its own name, the N+1 selects problem. To avoid this you can load a related collection explicitly using explicit loading, eg. :
_context.Entry(todo).Collection(t=>t.Children).Load();
When you know you're going to use all children though, it's better to eagerly load all entities with Include().

Entity Framework + Web API, return Entities (Complex, collections, etc) outside DbContext

Here is my situation. I use Entity Framework 4 with the Web API
The structure of my code is quite simple, I have the Service layer where all my rest API is organized, I have my Business logic layer where I have business controllers to manage Transactions between the rest calls and the data layer. Finally, I have a data layer with generic repositories and a DAO to access the whole thing.
In my Business controllers, I use using to inject a non transactionnal (read only methods) OR a transactional (CRUD methods) DbContext.
When returning values to my REST API, I parse it into JSON.
The problem is that I keep having this exception: Newtonsoft.Json.JsonSerializationException
I return my entities / collections / lists outside of my using{} statement, which I think EF does not like by default.
In debug mode, sometimes, I will manage to retrieve all data, but not all the time. Since my entities come from a query within a DbContext, I think that the behavior is to remove loaded sub-properties after the context has been disposed of.
Fact is, I want to keep my structure as is, and I was wondering the following:
Is there a way of returning complete (not lazy-loaded) entities after leaving the using{} statement?
Thanks a lot
I actually read more about Entity Frameworks behavior. What I get is actually standard for EF. I have to force the context to Load() my refered entities in order to get them after leaving the context.

Eagerly load all entities in DbContext

Is there a way to configure a DbContext to eagerly load all of its entities? we have attempted:
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
We tried both with and without ProxyCreationEnabled being turned off.
I just happen to know that the DB we are loading in is not very large, doesn't change very often, and is referenced a lot. So keeping it all in memory will be very advantageous.
No, LazyLoadingEnabled disabled does not mean "EagerLoadingEnabled". It is: "not even lazy loading enabled, only loading explicitly requested by you". An EF context will never automatically do eager loading. Just think what could happen with many associations between entities and large databases.
You won't benefit much from pre-loading everything into your context unless you use methods to access the local entities only. You can access local entities by DbSet.Local or DbSet.Find.
Just accessing a DbSet (like context.Customers) will execute a database query anyway. If lazy loading is disabled it may use local entities for navigation properties (called relationship fixup) but otherwise accessing navigation properties will also cause database queries.
It sounds like you should populate an object graph from your database, using a context, and cache it outside the context. Note that if you fetch the data read-only you may want to use the AsNoTracking extension method. (Like context.Customers.AsNoTracking()).
Nope... but if you're looking for the most performant way to load bulk data into EF DbContext, I recommend writing a stored procedure that returns multiple result sets (one for each entity type). EF will automatically hook up the nav properties when the entities are loaded into the context.
Here's instruction on how to do it from both the DB first and code first perspectives:
http://msdn.microsoft.com/en-us/data/jj691402.aspx

Aggregate Root support in Entity Framework

How can we tell Entity Framework about Aggregates?
when saving an aggregate, save entities within the aggregate
when deleting an aggregate, delete entities within the aggregate
raise a concurrency error when two different users attempt to modify two different entities within the same aggreate
when loading an aggregate, provide a consistent point-in-time view of the aggregate even if there is some time delay before we access all entities within the aggregate
(Entity Framework 4.3.1 Code First)
EF provides features which allows you defining your aggregates and using them:
This is the most painful part. EF works with entity graphs. If you have an entity like Invoice and this entity has collection of related InvoiceLine entities you can approach it like aggregate. If you are in attached scenario everything works as expected but in detached scenario (either aggregate is not loaded by EF or it is loaded by different context instance) you must attach the aggregate to context instance and tell it exactly what did you changed = set state for every entity and independent association in object graph.
This is handled by cascade delete - if you have related entities loaded, EF will delete them but if you don't you must have cascade delete configured on the relation in the database.
This is handled by concurrency tokens in the database - most commonly either timestamp or rowversion columns.
You must either use eager loading and load all data together at the beginning (= consistent point of view) or you will use lazy loading and in such case you will not have consistent point of view because lazy loading will load current state of relations but it will not update other parts of aggregate you have already loaded (and I consider this as performance killer if you try to implement such refreshing with EF).
I wrote GraphDiff specifically for this purpose. It allows you to define an 'aggregate boundary' on update by providing a fluent mapping. I have used it in cases where I needed to pass detached entity graphs back and forth.
For example:
// Update method of repository
public void Update(Order order)
{
context.UpdateGraph(order, map => map
.OwnedCollection(p => p.OrderItems);
}
The above would tell the Entity Framework to update the order entity and also merge the collection of OrderItems. Mapping in this fashion allows us to ensure that the Entity Framework only manages the graph within the bounds that we define on the aggregate and ignores all other properties. It supports optimistic concurrency checking of all entities. It handles much more complicated scenarios and can also handle updating references in many to many scenarios (via AssociatedCollections).
Hope this can be of use.

Entity Framework Detach an entity and the related entities gone

When I use Entity Framework, I want to query out a record in a context and add it to another context with the same schema, after query out the record, I detach it from the context, but the related entities are all away, is there any way to solve it?
Thanks in advance!
This is "by design". EF can detach entities only one by one but in the same time EF doesn't support object graphs composed of attached and detached entities. Because of that when you detach entity it will break all relations to the rest of attached object graph. Detaching whole object graph is currently not supported but you can vote for this feature on Data UserVoice.
As a workaround you can turn off lazy loading on your context, use eager loading described by #CodeWarrior to load exactly data you need to pass to other context. Once you have data loaded serialize them to stream and immediately deserialize them to the new instance of the object graph. This is the way how to make deep clone of entity graph which is detached but has all relations intact (turning lazy loading off is needed otherwise serialization will load all other navigation properties as well which can result in much bigger object graph then expected). The only requirement is that your entities must be serializable by serializer of your choice (be aware of circular references which usually require some special handling or additional attributes on your entities).
Are you asking how to load the child entities? If so, you can do eager loading with the .Include method. Given a Person class and a PhoneNumber class where Person has a collection of PhoneNumber, you could do the following:
List<Person> People = db.People.Where(p => p.Name = "Henry")
.Include("PhoneNumbers")
.ToList();
Or you can do what is called explicit loading where you load your entities and call the .Load method on the collections of child and related entities that you want to load. Generally you do this when you do not have LazyLoading enabled (and LazyLoading is enabled by default in 4.0+ don't recall in previous versions).
Regardless of how you query and load them, you will have to detach entities that you want to attach to a different context.
Here is a link to a pretty good MSDN article on loading entities.