Ado Entity Framework when should you use attach/detach - entity-framework

In ADO.net EF, when should you call the context.Attach() and the context.Detach() methods and how do these calls affect the data being returned or being inserted?

This is one of those questions where, "If you have to ask, you probably should not be doing it." The Entity Framework will implicitly attach entities in cases where it is obvious that this needs to happen. You really only ever need to explicitly attach and detach entities in cases where you are using more than one ObjectContext at once. Because this can be quite confusing, due to the implicit attachment which happens in the course of normal Entity Framework operations, I strongly recommend that people new to the Entity Framework use only one ObjectContext at a time. If you do this, you should never need to explicitly call Attach or Detach.
Calling, say, Attach does not really affect the data returned, insofar as it's scaler properties are concerned. But if it refers to other entities which are already loaded into the context into which it is attached, then these properties will be pre-populated without explicit loading. That said, entities returned from a query are already attached, so you cannot attach them.

Attaching Objects (Entity Framework)
http://msdn.microsoft.com/en-us/library/bb896271.aspx
Detaching Objects (Entity Framework)
http://msdn.microsoft.com/en-us/library/bb738611.aspx

Related

Entity Framework Memory Management and Dispose?

I'm using EF (EF Core, actually, with ASP.NET Core on OSX, but I believe this is more of a general "newbie-style" EF question, so please read on...)
I built a little logging routine that uses EF to publish log entries to my database. Sort of like this, called from a repository class:
WebLog log = new WebLog(source, path, message);
Context.WebLogs.Add(log);
Context.SaveChanges();
Where WebLog is a simple model class, Context.WebLogs is a DbSet<WebLog> collection, and Context is obviously the DbContext. I believe this is quite straightforward.
But my question is this: if I continue to add new log entries to the Context.WebLogs collection and I never do anything like reboot my server, isn't the collection just going to grow without bounds? Is there some kind of "purge" or "flush" action I can take periodically to manage memory usage (without affecting the committed rows in the database, of course--I want those to persist). Or is DbSet some sort of a special collection that won't do this?
As mentioned by DevilSuichiro above, the recommended approach is to limit the lifetime of the instances of DbContext. E.g. in a Web application you typically use a DbContext instance per request, so an unbounded number of entities added doesn't become a problem.
The closest thing to a "flush" operation is SaveChanges() that method will not try to remove references to tracked entities, as DbContext is designed to be reused after SaveChanges().
In previous versions of EF we had a Detach() API that you could use to get rid of an individual tracked reference but we don't have that API in DbContext or anywhere in EF Core.
BTW, having an instance of DbContext that is shared between multiple requests is extremely problematic because DbContext is not thread safe.

Serializing Entity Framework objects for Azure Cache

we use Azure Caching directly (and not through one of the available Entity Framework wrappers). Apparently, for distributed caching, we need to serialize the objects. Unfortunately, this causes issues with lazy-loaded DbContext-based proxies used for navigation properties.
I see we can use a custom serializer in order to map proxies to empty collections (if not loaded) or to normal objects (if loaded), but I am not sure about the implementation. One possible implementation can be based on the one used by WCF, but I am not sure Azure works the same way.
The ideal solution (and that's why I point to ProxyDataContractResolver) would be one where, when serialization happens:
IF the navigation property has been already loaded the data would be serialized as if it were a normal Collection,
and if they are not loaded, they won't be serialized (I would like lazy loading to work back after deserialization for the latter case, but it's acceptable if it doesn't).
Has anyone manually fixed that problem in an elegant way?
Thanks in advance!
I will presume that if you are wanting to cache EF objects, you don't require lazy loading or change tracking on those entities.
I believe that both of those are enabled through object proxies that will cause serialization issues (since you don't want to serialize the proxy).
If you disable the property DbContext.Configuration.ProxyCreationEnabled then serialization of the actual object, not the proxy, should work fine. This is typically required when returning POCO objects over WCF but is likley the same for other serializations scenarios such as this.
If you detach the EF entity from the DbContext before serializing it, that disables lazy loading, so your custom serializer won't try to serialize anything that isn't already part of the entity's graph.
Then when you get it back from the cache, if you attach it to a new (identical) DbContext, that should reenable lazy loading.
(Caveat: once you detach the entity from the context, any new queries that include that same object will create a new, attached, copy, so you will need to code with some care to avoid running into trouble with multiple potentially-different versions of the same object running around. But that said, this should let you do what you want.)

How entity framework track the loaded entities? what are their life cycle?

I am relatively new to entity framework, all the documents or books I can find are talking about how to use the framework, or which model should be used, but short of explanation how the framework works in depth.
For instance, when I load the entities from the database via either LINQ query or framework methods, are those entities thread safe? In another words can they be shared with other threads? If so how EF controls the consistency?
When control goes out of context, are those entities gone or still in memory? After .SaveChanges are those entities gone? What is the life cycle?
Can an expert in EF explain the above points in details please.
Thanks in advance.
The life cycle of loaded entities is more-or-less tied to that of the Entity Context which loaded them. Hence in many examples you will see:
using (var ctx = new Context())
{
// ... do work
} // The context gets disposed here.
Once the context is disposed (at the end of the using statement, e.g.), you should no longer treat entities that were loaded inside the context as if you can load additional information from them. For example, don't try accessing navigation properties on them. To avoid problems, I usually find it best to create a DTO that has only the exact data that I expect people to be able to use, and have that be the only value that leaves the using statement.
using (var ctx = new Context())
{
var q = from p in ctx.People
select new PersonSummary{Name = p.Name, Email = p.Email};
return q.ToList(); // This will fully evaluate the query,
// leaving you with plain PersonSummary objects.
}
Entity Contexts are not thread-safe, so you shouldn't be trying to load navigation properties and such from multiple threads for objects tied to the same context, even within the context's lifecycle.
For instance, when I load the entities from the database via either LINQ query or framework methods, are those entities thread safe? In
another words can they be shared with other threads? If so how EF
controls the consistency?
The ObjectContext class is not tread safe. You must have one object context per thread or to create you own thread synchronization process. This way the consistency is managed by the ObjectContext since it tracks all the objects' state.
When control goes out of context, are those entities gone or still in memory? After .SaveChanges are those entities gone? What is the life
cycle?
ObjectContext class inherit from IDisposable interface so you can, and should, use USING statement when using Entity Framework. This way they're gone after you close the using statement. If you DO NOT dispose the context they keep being tracked, only their states are changed. Disposing ObjectContext instances will also make sure that the database connection is properly disposed and you are not leaking database connections.
So, the big question is:
Where and when should EF live?
Theses ORM should be treated as the Unit of Work pattern, that is, the ORM object should live until the business task is done.
In my specific scenarios I use an IoC container like Windsor that does the heavy lifting for me. In an ASP.NET MVC app for example, Windsor can create a Context per Web Request. With this you don't have to write a lot of using statements throughout your code. You can read more about it here:
Windsor Tutorial - Part Seven - Lifestyles
Here's a link that explains it in more details directly from the guy that helps build the framework at Microsoft:
Entity Framework Object Context Life Cycle compared to Linq to Sql Data Context Life Cycle
You can write a test application to observe the behavior of the context tracker.
If you retrieve an entity from a context, then dispose of that context, then create a new instance of the context and attempt to save a change to the entity you retrieved earlier, it will complain that it is already tracking an entity with that ID.

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.

EF 4: Problems understanding DetectChanges when using POCO (no self tracking ObjectContext)

I wonder if anyone can help me?
I am having problems understanding why i need to issues DetectChanges on my POCO (non proxy) entities.
Of course i have this line to ensure that proxies are not returned.
context.ObjectStateManager.GetObjectStateEntry(order).State
And doing some research it appears if i need to check the "state" of an object then i need to issue detechChanges But why would i need to check the State of an object?
Basically I send along my POCO entity to a method that SAVES the data to a new ObjectContext (I create and destroy ObjectContext on each method)
Hence, i am having problems understanding why i would need to have ObjectContext track or be aware of changes?
Is it because that if its not aware if will not be saved?
Maybe i am miss informed but it appears that if i am using an existing ObjectContext (which i am not i am creating and destroying each time) that ensure ObjectContext is aware would be beneficial but otherwise not?
So in 1 method I am updating an object by creating a new datacontext, saving it to the db and destroying ObjectContext . Hence i am not using 2 methods, 1 method to send the update or new record and then another method for SAVING.
I would really appreciate any quick explaanations of why its needed?
Thanks in advance
Your question is little bit confusing. You are writting about Entity Framework but using DataContext which is related to LinqToSql.
The behavior differs in the way you are using ObjectContext. When you load POCO entity from database ObjectContext holds its instance in internal Identity Map. By default POCO doesn't use any kind of change tracking. When you save that POCO entity to the same instance of ObjectContext it internally calls DetectChanges to compare current entity state with stored state. This comparision defines which columns have to be updated. Internal call to DetectChanges is default behavior which can be turned off so you will have to call this method manually.
In your scenario you not using the same instance of ObjectContext. In that case you first have to Attach POCO entity to the ObjectContext. MSDN strictly says that when attaching entity it is marked as Unchanged. For that reason you have to say ObjectContext that entity has changed. You can do that for whole entity or you can define exactly which properties have changed but you have to do it manually = you have to store that information somewhere (Self tracking entities can help you with that but they have ohter disadvantages).