Print Page | Close Window

How do I determine if a related entity is removed from an entity

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=2839
Printed Date: 13-May-2026 at 10:41pm


Topic: How do I determine if a related entity is removed from an entity
Posted By: CJBriers
Subject: How do I determine if a related entity is removed from an entity
Date Posted: 20-Jul-2011 at 3:48am

Let's say I have a one-to-many relationship between Person and Pet entities (linked with a simple table with fields PersonID, PetID). If I do this:

aPerson.Pets.Remove(aPet);    
bool result
= aPerson.EntityAspect.HasChanges();

result is false after the call to HasChanges. How do I check if a related entity has been removed?

===EDIT===

Stupid typo: This question relates to a many-to-many relationship, not one-to-many




Replies:
Posted By: sbelini
Date Posted: 20-Jul-2011 at 9:33am
Hi CJBriers,
 
When you add/remove a Pet from a Person entity, the Person entity is not itself modified. That's why HasChanges is false.
 
Try the CollectionChanged event of the Pets navigation property instead:
 
aPerson.Pets.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Pets_CollectionChanged);
 
Regards,
   Silvio.


Posted By: CJBriers
Date Posted: 22-Jul-2011 at 7:09am
Great thanks, makes sense

===EDIT===

Actually, I changed my mind.  It does not make sense.  If the collection changed, its parent entity should be marked as having changes.  There's no other entity that would be marked as having changes (unless I add payload to the linking table).  Not marking the entity as changed requires me to explicitly keep track of every collection in that entity.  That's no fun.  


Posted By: WardBell
Date Posted: 26-Jul-2011 at 2:12pm
Hi CJBriers - You may be right that the parent entity should be marked as having changed if one of its child entities changes ... in your scenario.
 
For example, I favor your business logic with respect to an Order and its OrderDetails; any change to an Order's details ... including add or deleting a detail ... is a change to the Order. How do I know this? Because I know about the business rules that govern the relationship between Orders and their details; an order is substantially defined by its details.
 
Consider instead the relationship between a Customer and its Orders. Should a change to any order ... or the addition / deletion of an order ... constitute a change to the Customer who placed the order? One cannot say a priori. In most systems, the Customer would NOT be changed.
 
So you have two structurally identical parent/child relationships - Order/OrderDetail and Customer/Order - with different rules for modifying the parent when a child changes. Structure alone does not tell us what to do. DevForce takes the parsimonious approach and doesn't touch the parent. We leave it to the developer to decide what to do ... and implement that decision.
 
I have long felt that we should make it easy for the developer to express a parent-update rule declaratively and have DevForce enforce it. We don't have that feature at this time ... and you won't find it in similar systems either because the implementation is not necessarily as obvious as it first seems. One must, for example, decide what to do when the parent Order is not in cache ... and what to do when the developer calls "UnDo" on the order or any of its details.
 
You are welcome to implement the logic that suits your purpose. There are hooks to facilitate. Some popular approaches - often combined:
 
- add OrderDetail PropertyChanged event handler that calls the parent Order.EntityAspect.SetModified().
 
- use EntityManager.Saving event handler to ensure that the parent of every OrderDetail about to be saved is also in cache and listed among the entities to be saved; for each missing parent Order, get it, set it "Modified" and add it to the list of entities to be saved. p.s..: unless you have concurrency turned on, Entity Framework won't actually save the Order to the database because it won't see any actual change to the Order data.
 
You will have to think through what it means to undo changes either to parent orders or their children.
 
More could be said about the subject. For now I hope this explains why we do what we do and gets you thinking about what you will do.
 


Posted By: CJBriers
Date Posted: 03-Aug-2011 at 6:46am
Thanks for your explanation Ward,

I just realised my question had a very ugly typo.  I agree 100% for a one-to-many relationship that you would not want the parent entity to be marked as changed if a child entity changes.  I was actually referring to a many-to-many relationship (doh!).  I suppose I could still go with the approach of using the CollectionChanged event and SetModified.  

In the case of many-to-many relationship would it still not make sense to set the entity to modified?

Jaco


Posted By: WardBell
Date Posted: 03-Aug-2011 at 1:00pm
@CJBriers - That DOES make a difference ... although the question is an important one for 1-M relationships and I'm glad we had a chance to talk about it.
 
A canonical M-to-M is User-Permission: many Users have the same Permission and a given Permission has many associated Users.
 
Example: Bob, Sally, Jim can "Read"; Bob can "Update". Bob has two Permissions (Read, Update). Sally also has "Read"; the "Read" permission has three Users (Bob, Sally, Jim).
 
The effect of any change is always a business decision. In my experience, however, few would say that the  User is changed when a permission is added/removed and fewer still would say that a Permission is changed when adding/removing a User with that Permission.
 
By the same reasoning for 1-M relationships, DevForce can't infer that a related entity's state has changed. Only you can make that call.
 
I still think we could make the related-entity-update process easier for you in a future release of DevForce. Until we do, you'll have to handle it yourself with the tools provided.
 
All the best ... W



Print Page | Close Window