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
Related
I'm using breeze with EF6 and EFContextProvider.
On save changes I'm using :
{ TransactionType = TransactionType.TransactionScope };
I'd like to use lazy loading for validating my entities easier during the AfterSaveEntities delegate but I can't do that. Trying to set LazyLoadingEnabled = false during the transaction doesn't work. Entities still don't load relations when needed.
Is there any way to do that?
No, you'll need to load the entities manually. In fact, as explained in this SO answer, you should create a separate EF context for loading any additional entities.
When the SaveResult is sent back to the client, any additional entities that are attached via navigation properties will be serialized along with the original entities. So you should keep the original context clean unless this is your intent.
I'm trying to figure out how to cache EF query results in an Azure AppFabric cache. Currently I'm using the LoreSoft EntityFramework extensions to deal with the caching (http://bit.ly/LWSywm). It works perfectly with an in memory cache, but not so much with AppFabric across multiple VM's. The issue is that I've got virtual properties in my EF objects, and they're being serialized as Dynamic Proxy objects, which of course can't be deserialized on a different VM, or even after a single VM restarts the application.
I only have a few queries I need to cache, so I'd rather not load every single related object manually across the whole project. Is there any way I can serialize an EF object with virtual properties? I don't need the virtual properties to magically start lazy loading again after I deserialize them. I've tried turning off lazy loading the DbContext before serializing the results, but that doesn't work. The only way I've found to get a serializable EF object is the remove all virtual properties.
By the way I've looked at the Julie Lerman article here: http://bit.ly/LWToZT
Seems like a cool project, but I'm not entirely sure it's going to solve my problem of not being able to serialize EF objects. Don't want to go down that road if I'm just going to end up where I started.
Any ideas most appreciated!
You can configure your dbcontext (or object context) to not use proxy objects. Obviously, this means no change tracking and no lazy loading. If you don't eager load an object's navigation properties, they will simply be null instead of references to proxies. It's worth noting that you can toggle this on and off throughout the context's lifetime, so it's not an all or nothing decision.
If you are using DbContext, the syntax is:
context.Configuration.ProxyCreationEnabled = false;
We have had a similar problem. We had a service that returned data that was read from a database using EF. This data needed to be cached in Appfabric.
In our case the services returned DTO objects, so we mapped the EF objects to DTO objects, and then stored the DTO objects in Appfabric cache.
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.
I've just been talking with a colleague about Entity Framework change tracking. We eventually figured out that my context interface should have
IDBSet<MyPoco> MyThings { get; }
rather than
IQueryable<MyPoco> MyThings { get; }
and that my POCO should also have all it's properties as virtual.
Using the debugger we could then see the tracking objects and also that the results contained proxies to my actual POCOs.
If I don't have my POCO properties as virtual and have my context interface using IQueryable<> instead of IDbSet<> I don't get any of that.
In this instance I am only querying the database, but in the future will want to update the database via Entity Framework.
So, to make my life easier in the future when I come to look at this code as a reference, is there any performance penalty in having the tracking info/proxies there when I will never make use of them?
There is a performance penalty of tacking entities in EF. When you query using entity framework EF will keep a copy of values loaded from database. Also single Context instance keeps track of only single instance of an entity. So EF has to check whether it already has a copy of the entity before it creates an instance(ie. There will be lot of comparisons going behind the scenes).
So avoid it if you don't need it. You can do so as follows.
IQueryable<MyPoco> MyThings { get { return db.MyThings.AsNoTracking(); } }
MSDN page on Stages of Query Execution details the cost associated with each step of query execution.
Edit:
You should not expose IDBSet<MyPoco> MyThings because that tells the consumer of your API that your entities can be added, updated and deleted when in fact you intend to query the data.
Navigation properties in the model classes as declared as virtual so as to imply lazy load feature which means the navigation property will only be needed if required. As far as the Entity objects are concerned, there main aim is to load the specific table records from the database into the DbSet which comes from DbContext. You can't use IQueryable in this case. Also, it doesn't make any sense with the DataContext. IQueryable is an altogether different interface
There is no Detach(object entity) on the DbContext.
Do I have the ability to detach objects on EF code first?
This is an option:
dbContext.Entry(entity).State = EntityState.Detached;
If you want to detach existing object follow #Slauma's advice. If you want to load objects without tracking changes use:
var data = context.MyEntities.AsNoTracking().Where(...).ToList();
As mentioned in comment this will not completely detach entities. They are still attached and lazy loading works but entities are not tracked. This should be used for example if you want to load entity only to read data and you don't plan to modify them.
Both previous answers provide good instructions, however, both might leave you with the entities still loaded into EF's context and/or its Change Tracker.
This is not a problem when you are changing small data sets, but it will become an issue when changing large ones. EF would have increased memory and resource usage, which in turn would reduce the procedure performance as it uses more data/entities.
Both other approaches are valid but, In this case, Microsoft recommends cleaning the Change tracker instead of detaching the entities individually
Clearing the Change tracker on the data changing loop (which changes a chunk of data for instance) can save you from this trouble.
context.ChangeTracker.Clear();
This would unload/detach all entities and its related changeTracker references from the context, so use with care after your context.SaveChanges().