I am coding a MVC 5 internet application with EF6 and I have a question about what happens when the context.SaveChanges() method is called.
Does the DbContext object store the CRUD actions that occur, such that if the SaveChanges() method is called, and none of the data in the database is updated, no action occurs?
Here is an example:
I create a simple model object, then add this to the database and call SaveChanges.
I retrieve this simple object, set one of the objects values to be the same as it currently is, and then call SaveChanges.
In the above example, are any changes made to the database? Do any database transactions occur?
I have done some research, but could not find the answer to this question.
Thanks in advance.
EF6 uses the change tracker to detect if there are any changes.
When you do a call to SaveChanges(), one of the first things EF6 is doing is calling DetectChanges() which will inspect the change tracker.
Now suppose you really want to know if something has changed you can look in the changetracker yourself too. This post shows how in the answer :
Entity Framework 6: audit/track changes
No, if entitys are not changed, it's state is unchanged, so EF is not interested in those.
You can force saving by changing state of entity manualy if required.
Related
I am using Entity Framework 6 where, for performance reasons, I load my entities into my DbContext up front and then use them locally. Up to now, all changes to the database have gone through the DbContext so my local entities and the database have been in sync. However, I now have to call a Stored Procedure on the database, which has the side effects of making changes to tables (outside of the DbContext) that need to be reflected in my entities. By changes, I mean it is adding new records and deleting / updating existing records.
I do not want to dispose of my DbContext and create a new one, as some of the entity instances are wrapped within ViewModel classes. So, deleting the DbContext in this way would lead to major problems in the UI.
It is my understanding that simply calling Load() on all my DbSets of the DbContext will just replace the existing instances. So, any objects using the old entities instances won't work.
So, I thought I could use the Reload method like:
context.Entry(entity).Reload();
which would update my local entities, but I can only do this for the entities that the DbContext already knows about. It doesn't cover any NEW entities or DELETED entities that were created / deleted as a result of the Stored Procedure executing.
So, I am looking for a way to:
Load, from the database, entities that are NEW to my DbContext
Reload existing entities in my DbContext
Remove any deleted entities from my DbContext
Here is the official documentation for Entity Framework.
Starting from the analysis of your database situation, it suggests smart and quick ways to obtain what you want, detailing when necessary data-read strategies (like eager or lazy loading) or providing tutorials to correctly use code generation and the Wizard GUI.
http://www.entityframeworktutorial.net/choosing-development-approach-with-entity-framework.aspx
Here some more detailed info and tutorial on data-read strategies:
https://www.c-sharpcorner.com/article/eager-loading-lazy-loading-and-explicit-loading-in-entity-framework/
As I already told you in comments, I would suggest a database-first approach and with lazy loading to avoid uncontrolled data behaviours (or reloading the whole db when running a stored procedure).
Talking about the SP, it can simply be mapped through the Wizard that comes with Entity Framework and wrapped by a method.
Hope you will find these resources helpful!
In general EntityFramework can not aware on change in database and update dbcontext .there is no optimized or EntityFramework built-in solution for it.
I think you can use CDC in SqlServer, push change to your application and update your dbcontext. But it not acceptable solution for all business and senario
I've read that in previous versions of the entity framework, you had access to a Reload() method, like this: Db.Entry<DatabaseModels.User>(_me).Reload();
I get an error from that saying that EntityEntry does not contain a definition for 'Reload'.
The reason why I even want to reload is from caching (or what I think is caching, and EF possibly not knowing when to invalidate the cache).
Example:
Load userA.
Create item that userA will own.
Try to access that new item through the relationship on the user.
userA.Items returns empty
re-fetch userA from the database, and call the relationship, and the newly created item is in the association.
Not sure why that's happening, or if there is a way to get EF to be smarted about cache invalidation.
It isn't supported, but you can do it through code, by inspecting the metadata. See here an example: https://weblogs.asp.net/ricardoperes/implementing-missing-features-in-entity-framework-core.
I'm using EF 4.1 in an MVC 3 application.
My goal is to save all changes in another database for logging purposes.
I have implemented the SavingChanges event for an EntityContext. In that event, I'm extracting changes via the GetObjectStateEntries() , that works fine.
Then, I have another EntityContext, that works against a different model and database, for the logging. I create that Context, create logging Entities, adding them to the logging Context. All seems to work fine. Then when I call SaveChanges() on the logging context, Exception occurs, that says that I cant insert because the Id is null (which I know for sure that it isn't).
Does anyone know if it's impossible to achieve this? Am I missing some important detail?
The case was that I had used "Model first" in my logging model, and "DB first" in all other models. That resulted in the mistake that the EF configuration was expecting take care of the Id (GUID) itself, but I was trying to supply one myself. I deleted the entities from the model, and instead, imported them from the DB, and that solved the problem!
Thanks to #Eranga for setting me in the right direction.
How NHibernate track changes made to the fields in my entity? If I use second level cache and I change my entity, How does it apply my changes to db?
When you change an entity, the entity becomes "dirty" and nhibernate knows the update the entity in your database when the session is flushed. That said, sometimes its possible for entities to get marked dirty even though you have made no change. This results in unnecessary update calls to your database.
It is best to isolate your entities from your views via view models. Once you pull an entity out of the database, convert it to a view model that you can mangle up.
This seems like it would be a common issue to be but I don't know the best way to solve it. I want to be able to send an Entity to a view, have changes be made to the entity in the view, but then cancel (remove) those changes if the user cancels out of the view. What is the proper way to do this.
Here are two options I have but I think there should be others that are better
1) Take an entity, create a clone, send the clone to the view...if changes are accepted, update the original entity with the clone's values
2) Send the entity to the view, if the user cancels, remove the entity from NHibernate's cache and reload it from the database
For (2), the issue for me would be that the old entity could still be referenced throughout my project after it has been removed from the cache.
Edit:
Ok, so the evict method is the way to go if I am implementing method (2). Thanks, I could not remember the details of that one. However, the issue of view objects referencing my old evicted entities makes the issue tough to deal with. I can't just have my view automatically update to a new entity without having custom code in each one to rebind when my custom eviction event is raised. And rebinding may not be trivial in certain cases. I need to think on this some more as I may be over complicating but at the moment, this method seems trickier.
I suspect I am going to be stuck with method (1) which has its own set of problems but will wait a bit longer to see if anyone else has some ideas.
Edit 2: Just found this. I think it pretty much covers the answer in detail and comes with a great demo project - Building a Desktop To-Do Application with NHibernate - http://msdn.microsoft.com/en-us/magazine/ee819139.aspx
In addition to this, NHibernate has a Session.Refresh(Object entity) function which seems to solve the exact problem. So, when an entity is changed but then cancelled before save, I can just call Session.Refresh to reload it from the database and discard the changes.
I'll go for option 1 and use what is called a ViewModel instead of your entity.
The ViewModel is representation of you model for a specific view. In the ViewModel you can mix data from different entities and pre-format values to fit the view. Is an elegant way of passing data to a view and you can accomplish what you want easily.
Using ViewModels is becoming the preferred way of working in ASP.net MVC and Silverlight / WPF.
To read more about Viewmodels: http://blogs.msdn.com/dphill/archive/2009/01/31/the-viewmodel-pattern.aspx
The best way to do this is to call the Evict method on the ISession used to load the object. This will remove the object from the session cache. and you can then reload and redisplay it.
Evicting the object from the session makes it transient detached so if there are still references to it in the project they will not be persisted when the session is flushed. How you deal with that depends on your application but I would suggest raising an event to notify subscribers that they need to re-load the object.