New Posts New Posts RSS Feed: Problem with 3 level table relationship
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Problem with 3 level table relationship

 Post Reply Post Reply
Author
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Topic: Problem with 3 level table relationship
    Posted: 05-Mar-2013 at 9:46am
We have an annoying table structure (that we unfortunately have to live with for legacy reasons) and we are running into some odd problems when we use it in certain ways.  I'm not sure whether we are just trying to do something that isn't support or what.

To reproduce the problem in a simpler context, I took the NorthwindIB database and added an extra table so that I could have a 3-level relationship.  The model now looks like this:



With a model like that, the following unit test will fail:
        public void TestThreeLevels()
        {
            var em = new EntityManager(shouldConnect: false);

            //Make two products - '100' and '200'
            var product1 = em.CreateEntity<Product>();
            product1.EntityAspect.AddToManager();
            product1.ProductID = 100;

            var product2 = em.CreateEntity<Product>();
            product2.EntityAspect.AddToManager();
            product2.ProductID = 200;

            //Create an Order
            var order = em.CreateEntity<Order>();
            order.EntityAspect.AddToManager();
            order.OrderID = 1;

            //And one detail that is currently pointing to Product 100
            var detail = em.CreateEntity<OrderDetail>();
            detail.EntityAspect.AddToManager();
            detail.ProductID = 100;

            order.OrderDetails.Add(detail);

            //Make an extra detail entity
            var extra = em.CreateEntity<OrderDetailExtraDetail>();
            extra.EntityAspect.AddToManager();
            extra.DetailID = 3;

            detail.OrderDetailRevisions.Add(extra);

            //Sanity check to make sure the extra entity is how we expect it
            Assert.AreEqual(1, extra.OrderID);
            Assert.AreEqual(100, extra.ProductID);
            Assert.AreEqual(3, extra.DetailID);

            //Now switch the detail to Product 200.  I would expect this change to cascade 
            //  to its child (the extra detail).  It sort of cascades but not in any sensible way...
            detail.ProductID = 200;

            //This fails:  the order ID somehow got set to 200?  But that was the Product ID not the Order ID
            Assert.AreEqual(1, extra.OrderID);

            //This also fails: The Product ID wasn't changed - it is still 100
            Assert.AreEqual(200, extra.ProductID);
            Assert.AreEqual(3, extra.DetailID);
        }

That behavior seems very, very strange (and in fact took us a long time to track down why the OrderID was all of a sudden pointing to something very wrong).

Once I tracked down the problem, I tried to use the navigation property to change the product.  So instead of detail.ProductID = 200, I used detail.Product = product2.  (Note in our app, we don't even have that navigation so it's not really an option but I wanted to try it anyway in my smaller app).  When I did that, I got the following error:

System.InvalidOperationException: You may not change the entity’s EntityKey (currently ‘OrderDetail: 1,100’) while any of its related, dependent entities are in the entity cache. Are you sure you want to change the EntityKey? Consider reordering your operations such that you set the EntityKey first. Alternatively you could detach the entity or remove its dependent entities before trying again but be aware that you risk orphaning the dependent entities.

So that got me thinking that I might just be doing something wrong?  Maybe this isn't a supported scenario for DevForce (which would be very sad - and combined with the other limitation of 3-level relationships I ran into previously, means 3 level relationships can be very fragile and dangerous to use).  I'm hoping this is just a bug or I'm doing something small wrong.  I really hope this isn't the expected behavior.

A couple of extra things:
  1. If this scenario is really not supported, I think that exception should be thrown if you change the FK value in addition to the navigation property.  If I hadn't tried to reproduce this in a separate project where there was a navigation property, I would have never known that I was doing something bad.
  2. The exception message seems a bit oversimplified.  I know there are plenty of times when the PK can be changed and it correctly updates related entities.  The whole idea of temporary ID fixup pretty much relies on the fact that changes to the PK will cascade around the object graph.  Also, in my test code above, if I replace detail.ProductID = 200 with detail.OrderID = 42, that does correctly cascade the new value down to the extra detail....so I know it can work in some cases.
Thanks.
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 06-Mar-2013 at 7:31pm
A couple of things going on here.
 
First, the odd results when setting the FK ID field directly (detail.ProductID = 200) is a bug, due to incorrect handling of the multi-part key. 
 
Second, the exception when setting the nav property (detail.Product = product2) - The exception is clumsily trying to stop a cascade to dependent entities, even though, as you note, this can be done via other code paths.
 
We should have both problems fixed in the upcoming 6.1.12 release. You should then be able to modify the key field in either way and have the change cascaded to multiple levels of dependent entities.
Back to Top
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Posted: 07-Mar-2013 at 10:14am
That is great news Kim!  To be honest, I was half expecting this to just be a 'limitation' of the system.  I'm glad it will work as expected in the next release.

Is there any chance that these fixes could affect other problems I've had with 3-level table relationships...specifically issue #1 in this post.  I know it's a long shot but I have to ask :-).
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 07-Mar-2013 at 11:13am
Yes.   Changes should now cascade to grandchildren (and beyond - but that would be a very odd model).  
Back to Top
stephenmcd1 View Drop Down
DevForce MVP
DevForce MVP


Joined: 27-Oct-2009
Location: Los Angeles, CA
Posts: 166
Post Options Post Options   Quote stephenmcd1 Quote  Post ReplyReply Direct Link To This Post Posted: 25-Mar-2013 at 1:57pm
Everything seems to be working in 6.1.12.  The (failing) code I presented above works perfectly in the new version.  Many thanks!
Back to Top
kimj View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 09-May-2007
Posts: 1391
Post Options Post Options   Quote kimj Quote  Post ReplyReply Direct Link To This Post Posted: 25-Mar-2013 at 2:03pm
Excellent! Thanks for the update.
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down