How, after all, does the Tracking of objects of Entityframework?
First it is important to explain that a context exists during the life cycle of a Controller, in the specific case you are working using MVC. The values loaded by Controller are only expired when the Controller in question suffers a Dispose
, making the context also suffer a Dispose
.
When loading an object (in English they call entry, and I’ll call it a record), the record is loaded with the original values of the database, and they stay there even if you change the record. This makes it clear that when modifying a record, the Entity Framework knows that this record has already been loaded and knows what to change.
The record is usually located by its key. To understand this better, you need to understand the implementation of DbSet<T>
. He’s an observable collection (ObservableCollection
). By calling SaveChanges
, what is being done is:
- Check if any collection is marked as changed;
- For each record that has been marked as changed, the Entity Framework performs some logical operation to insert, update, or delete a record in the database. The executed instruction is linked to
EntityState
, one Enum
used to identify the state of the registry within the Entity Framework.
So, whenever I do a POST for an Action, which will bind a class according to the Action parameter, I know that I have an instance not monitored by the Entityframework, right?
Wrong. If the record has already been loaded previously (in a Edit
, for example), it is already being "observed". When applying a POST
to save the edit, the object coming from View is synchronized as follows:
context.Entry(obj).State = EntityState.Modified;
Note that the context here is a new context, without the information of the previous request. When I say "the record has already been loaded," I say it was loaded on screen, not on Controller. When performing the POST
, you are sending information and the context works optimistically, that is, the record is again loaded in Entry()
if it has not already been loaded.
In this line are made two things:
- Locate a record based on another;
- Update the values of the observed record based on the on-screen records.
The case of Add
is simpler. You are telling the context that the object does not exist, so the context considers the object as new.
As in the case of the question I referenced, because there were monitoring problems?
I’ll answer the question.
What would be the most "complete" way to deal with Inserts
and Updates
and have no problems with the Tracking object?
- Not implementing repositories (Entity Framework already implements repositories);
- Not implementing Service layer (Controller is already a different layer of services, but is);
- Not instantiating two contexts unnecessarily;
- Not selecting objects in one context and trying to save in the other;
- Using the simplest code possible, as (almost) all examples illustrated here and on other specialized websites.
Enable or Disable the LazyLoading
and creation of proxies and monitoring of changes (AutoDetectChangesEnabled
) affects how the Tracking?
Lazy loading and monitoring are independent things. One does not affect the other and vice versa.
AutoDetectChangesEnabled
does the tracking does not work. Any change has to be invoked by manual methods.
+1 by Graphdiff. Sensational the package.
– Leonel Sanches da Silva
Unfortunately I can no longer interact on the other issue. I can’t vote here either. Just mark the answer as accepted. Well, on the other question, about the method
AtualizarPrecoProdutoAsync
, truly get the one instance of the product there to then change the propertyPreco
and then record the change. However, error happens in the methodAddAsync
, at that time theAtualizarPrecoProdutoAsync
.– Severo
In fact, it is not a good practice to pass an instance of a context as a parameter in several layers of your application (controller, service, repository, etc.). Create your Dbcontext only in the implementation of your Repository. Unitofwork + Repository + Entityframework I do not recommend because you never know what was done in a Dbcontext in the other layers, you get lost very easy. http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/
– Jone Polvora
About the
AtualizarPrecoProdutoAsync
, reiterate, is what you said yes, exactly that! I messed up the debug with theasync's
of life. Thank you so much for your explanation.– Severo