Delete an object and all of its related entities in Entity Framework - entity-framework

Does anyone know how to delete an object and all of its related entities inside of EF without manually traversing the object graph and deleting each one?
For example, I've got SalesOrder and SalesOrderDetails with a 1:N relationship between them. When I delete a SalesOrder, I want all SalesOrderDetails to be deleted automatically.
Is this possible in EF?

You should not be doing this in the Entity Framework. All popular relational databases support ON CASCADE DELETE on foreign keys which is a lot more efficient as well. I suggest you just go with that.

in this article, Alex Jamese (who post his answer), has a complete article on the topic.
Link
The EF is responsible for the correctness of the ObjectContext after SaveChanges(). So the EF attempts to synchronize the ObjectContext, with the expected database state after the expected cascade in the database.
A tell tale sign of this is that if you open up something like SqlProfiler, you will notice the EF issuing DELETE requests for dependent entities that it knows about (i.e. that are loaded in the ObjectContext) when a principal is deleted.
Essentially what is happening here is that the Entity Framework expects that deleting the principal in the database, will delete all it’s dependents in the database. So it issues, what should be, a redundant DELETE to request itself so the dependents already loaded are deleted from the ObjectContext.
The key thing to note is that the EF does not retrieve all the dependent entities and issue deletes for them: It only deletes dependents that are already in memory.

Related

Entity Framework 6 AsNoTracking<TEntity>(), but for a single entity

I'm working on a unit of work and repository set-up for Entity Framework, where I want to make sure only changed entities, that have been through an Update method on the repository, are actually saved to the database.
The IQueryable extension, AsNoTracking, makes sure that all entities fetched from the IDbSet are not being tracked, but if I want to read a single entity, by it's primary key (using Find()), there seems to be no way to make sure the entity isn't tracked?
I don't want to Detach/Attach, as that ruins the options to, lazily, fetch complex properties.
What am I missing?
Nothing.
Find has no AsNoTracking. That's because Find first tries to find the requested entity in the (tracked!) context cache (the state manager). It goes to the database if it's not there, so for a subsequent second time Find it doesn't have to do this roundtrip again.
So, Find is all about tracked entities.
Use Single(OrDefault) (+ AsNoTracking) if you want to get one entity without tracking.

EntityFramework: Remove m2m association given only primary keys. How?

I've two entities a and b and an m2m association between them. Entities a and b are loaded in my DbContext, while the m2m associaiton is not. Now, in my program I know the primary keys of a and b and I need to remove the m2m association.
Of course, I could -reload a from the database and include its m2m association. However, this requires an additional round trip to the data base to get the entities from the database.
I could also first detach a from the DbContext, then add b to its BSet, then attach a again and then call remove something like:
context.Entry(a).State = EntityState.Detached;
a.Bset.Add(b)
context.Set(typeof(A)).Attach(a);
a.BSet.Remove(b)
However, by detaching a from its context and then attaching it, I loose the changes that have been made to a. Consequently, calling SaveChanges() may not persist all changes of a to the database.
My question is: how can I remove the m2m association between a and b without an additional round trip to the database and without loosing any changes made to a or b?
[edit: What I'm looking for is a method a.BSet.Attach that would enable me to attach an existing m2m association between a en b]
I'm using the latest version of Entity Framework and I'm using DbContext.
Any help is welcome.
PS. this is a repost of http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/5edea208-24cc-497b-8592-9cb025d558e4/
Thanks in advance,
Merijn
I was in the same problem a few days ago and the solution I came up is:
context.Entry(a).State = EntityState.Detached;
a.BSet.Add(b);
context.Entry(a).State = EntityState.Modified;
a.BSet.Remove(b);
with that code you should be removing the m2m association and preserving all the changes to the database.
EDIT:
I just realized that we have made almost the same code, just reattach your entity changing its state to 'Modified'.

EF 4.3.1 How adding affects related entities that exist already

Imagine this graph:
Device 1..* OperatingEnvironment 1..* NetworkEndpoint
If I construct a detached entity graph in-memory and the Device at the root of the graph is new while the OperatingEnvironment exists and the NetworkEndpoint exists but is assigned to a different OperatingEnvironment, will EF figure all this out?
When I say 'figure this out', its simply a case of walking the graph and doing (IfExist ? MergeValues : AddNew) Because the entities all have foreign keys, relationships should effectively get reassigned automatically during the property merge.
Is this how EF works or will I have to walk my own graph and apply this logic? If I do this, then my in-memory graph will have to be weakly linked, i.e. avoid linking via navigation properties and instead use the foreign key values, otherwise the whole graph will be added as as soon as I add one entity since EF will crawl the navigation properties.
Thanks - hope that's clear as mud.
You must do it yourselves. EF has no internal logic to detect if the entity exists in the database or not.

Delete object and all its child objects in Entity Framework?

I've been trying to find the answer to this question here. Several people seem to ask similar things, but I don't get the answers. I have an EF entity with a bunch of child entities (one-to-many relationship). I want to be able to delete the "parent" entity and have all the child entities deleted at the same time.
Some people mention "Cascade Delete" should be set on both EF model and database (Sql Server in my case). The problem is:
I have absolutely no idea how to do this (seems to be implied in those answers that you should know, but sorry...)
I have a feeling I've run into a similar problems before and found an answer somewhere that was simpler than setting this Cascade Delete. I may be wrong, maybe it is the only way, but if there is a simpler solution I'd like to know.
In either case, a clear example of how to get this working would be greatly appreciated!
In SQL Managment Studio go to your database and find the table where there should be a foreign key. Add a foreign key to the table pointing to the other table. I assume you know how to setup a foreign key. In the foreign key setup at the bottom of the dialog window you'll see a Delete property. Set it to Cascade. This will cause any dependent rows to be deleted whenever the parent row is deleted. Then go and update your data model in Visual Studio. Everything should be setup for you now.
Here is some relevant documentation on MSDN. Note though that there appears to be an error in the example. I received the following error from the EDMX designer when using this configuration.
Operations cannot be specified on ends with multiplicity '*'.
You should set the OnDelete property to Cascade for the end will be triggering deletes on the other end.
As an example, in a relationship involving customers and orders where you would like to have a customer's orders deleted along with the customer, you should set the OnDelete property for the Customer role to Cascade.
Note that only objects that have been loaded into the ObjectContext will be affected by a cascading delete. You will be relying on the cascading delete that you set in the database to look after any other records.

How to delete slave entity in entity framework poco in one line?

The following code:
order.Orderlines.Remove(orderline)
Means not only to remove relationship between Order and Orderline but also to remove orderline from persistence permanently. Many slave entities have this situation.
As I know, in entity framework have to write extra code:
context.DeleteObject(orderline);
Or,
context.Orderlines.DeleteObject(orderline);
So, the remove rule can't be encapsulated entirely in order itself.
Any better choice for one line deletion in entity framework?
It's not entirely clear to me what you are asking, but here is a very complete description of various scenarios for deleting related entities, which will hopefully answer your question.