kianryan / kianryan.github.io

www.kianryan.co.uk
2 stars 0 forks source link

Entity Framework Gotchas – Strategies for Orphaned Child Objects #52

Open kianryan opened 1 year ago

kianryan commented 1 year ago

Written on 17/03/2013 12:04:01

URL: http://www.kianryan.co.uk/2013/03/orphaned-child/

kianryan commented 1 year ago

Comment written by Julie Lerman on 17/03/2013 13:48:31

This one definitely confuses people a lot. Removing something from a collection is totally different than calling REMOVE on a DbSet. The collection has nothing to do with EF. It's just a .NET collection and has no clue about the mysteries of EF's relationship management. I wish they had left the DbSet method name "DELETE" like it was for ObjectSet. That way there is an obvious difference between "DbSet.DELETE" and "Collection.REMOVE". FWIW, if you can call context.Children.Remove(child), then entity framework will also fix the relationship problem and delete at the same time. If you are using aggregate root, however, you may only have context.Parents and not even have a context.Children property and would then have to go even deeper to context.Entry(child).State=EntityState.Deleted. So the real problem is that REMOVE is on the .NET collection. Now I'm wondering if there is a way to make the savechanges smarter... like checking for null but required FK properties and deleting the entities before EF sees the p roblem and throws an exception?

kianryan commented 1 year ago

Comment written by Kian Ryan on 18/03/2013 02:22:02

Well, using reflection it should be possible to check which attributes are marked as required, and call Delete on them.

However, I see this as being a little bit nasty, and potentially quite expensive on large data sets.

MS have identified their preffered stragey (Identifying Relationships) and it does make some sense, but only really works if you have control over the schema.

kianryan commented 1 year ago

Comment written by Lambolez Paul on 07/04/2013 17:38:46

This doesn't work as the field is marqued as required when you use [Key, Column(Order = 2)] ...

kianryan commented 1 year ago

Comment written by Raffaele Garofalo on 03/10/2014 12:58:09

This is such a stupid behaviour that breaks all the DDD rules.
First we have to options here: 1) make the Domain Entity aware of the ORM (so bad) 2) Encapsulate the BL inside a third component that removes the item from the collection and then mark the child object as deleted.
With other ORM like NHibernate we don't need to track this, the proxy is smart enough to understand that a child item has been removed from the collection and mark it as deleted. With EF we must

Person.Child.Remove(child)
context.Entry(child).State = EntityState.Deleted

what does it mean? It means that as always happens, MS implemented an ORM which is not fully domain agnostic ...

kianryan commented 1 year ago

Comment written by Kian Ryan on 06/10/2014 12:51:10

It's not great, I admit. I have also now got another solution, that involves making a change to the context. This way when you mark the entity as deleted, you stop caring until SaveChanges kicks in and it checks for the orphaned object itself and cascades the delete state. I was pretty sure I had written it up, but apparently not...

kianryan commented 1 year ago

Comment written by ozbob on 05/03/2015 08:01:57

hi @kianryan - have you written up your new solution? I am interested to hear about it.

kianryan commented 1 year ago

Comment written by Kralizek on 12/07/2015 17:55:12

this still violates some's desire to have only aggregate roots exposed by the context