What exactly does the LINQ-to-SQL method Table<T>.Attach() and Table<T>.AttachAll() and what is an example/situation for their proper usage?
Also, please check out this related question: How to detach a LINQ-to-SQL data object from the DataContext's tracking mechanism?
It is really useful in multi-tier applications that serialize/deserialize data to other layers.
Short version:
Attach() tells DataContext the entity is not new (for insert) but an updated entity that is meant to be updated in the DB.
Long version:
You have a DataContext where your entities exist. New entities get inserted, existing ones get updated. Now you need to send some entity to another tier, DataContext then detaches said entity and sends it away.
On the other tier the entity gets modified and sent back to your data layer. Now the former DataContext that had your entity may not exist anymore (eg. if it is stateless) or does not know your deserialized entity so what do you do? You create a new DataContext or use the existing one and use the Attach() method - this way the DataContext knows the entity is meant to be updated and should not be inserted into the database.
The same goes for AttachAll() but for multiple entities.
LINQ to SQL maintains the state of entities in a DataContext object. Entities that are loaded from the database are associated with a DataContext that is responsible for tracking any changes to the entity so when you save it the appropriate changes are made to the database.
Entities can become detached from the DataContext when they are serialized (for passing to a client for example in an n-tier application). When the client returns the entity back to your DA layer you will need to reattach it to a DataContext before it can be updated or deleted in the database. The Attach method performs this operation.
Related
I am using EF Core 3.1.26 with EntityFrameworkCore.Jet 3.1.1, using MS Access for the database. I would update EF Core, but then it wouldn't be compatible with EntityFrameworkCore.Jet.
My problem is that there seems to be some kind of static cache shared across instances. When after creating a instance I attach a entity, it throws an error because the entity is already being tracked, even though it is the first entity attached to that context (the queries are marked with AsNoTracking). I even checked with the debugger that there are no entities in the Entries property of the Change Tracker.
Even when I execute SaveChanges(), entities are updated that shouldn't exist in that context, since I made no query whatsoever. In the Entries property there is only the entity I attached with is navigation properties to null. And yet a bunch of entities of different tables are updated. Those entities I did query, but in another context and with AsNoTracking.
I have no idea where EF Core or EntityFrameworkCore.Jet are getting this entities from. It is like Attach and SaveChanges are accessing a static Change Tracker, and I don't know how to solve this problem.
Thank you.
Edit: It was my mistake, I didn't check correctly.
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 have a WPF application and am using entity framework. I was reading the tutorial
and the author was talking about disconnected entities, which is the first time I have heard of them. I am a little confused as to when disconnected entities are actually needed, as I have been using EF just fine to do CRUD operations on my business objects. If I am using the same context when I am doing CRUD operations on a business object, why do I need to ever manually track the entity state changes? Thanks for any help.
If you are always keeping around the originating context instance, then you probably do not need to worry about disconnected entities. Disconnected entities often come up in the context of web services or web sites, where the context from which an entity was originally retrieved (and, for example, placed into a Session) is no longer available some time down the road when that entity has been modified and needs to be saved back to the database.
I have created an editor that uses Entity Framework for db-access. The editor is a clientside editor that works via JavaScript. When the user clicks the save-button JavaScript calls my ASP.NET MVC method with the data as a JSON-string. The data is an object containing a list of nodes. I use inheritance in EF to allow the nodes to be of different types. The JSON that is sent from the browser is converted by MVC automatically to a DTO object. I then create EF-objects based on the DTO object. My question is how do I save the modifications to all the objects?
Right now I do the following:
// Convert my DTO object to a EF db object
Document dbDoc = dtoDoc.ToEFDocument();
using (MyEntities db = new MyEntities())
{
db.ApplyCurrentValues("Documents", doc);
db.SaveChanges();
}
This works but it only updates the properties in the document object (not the changes that was made in the nodes collection).
Is there a simple solution for this?
Your DTOs must also track information about changes an user did. You must track:
Which entities were updated
Which entities were removed
Which entities were added
Which independent associations (many-to-many or one-to-many without mapped FK) were added
Which independent associations were removed
Once you get this information on the server you must use it to correctly set state of every entity you want to save to database. There is no automatic mechanism for doing this in EF and ApplyCurrentValues only works for single entity (not for whole entity graph).
Doing this without information about changes usually requires loading all modified data from database and update them from DTOs instead of creating disconnected entities from DTO.
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.