New Posts New Posts RSS Feed: Possible incorrect entity state after save interceptor
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Possible incorrect entity state after save interceptor

 Post Reply Post Reply
Author
midnit View Drop Down
Senior Member
Senior Member
Avatar

Joined: 22-Jun-2009
Location: Charlotte
Posts: 112
Post Options Post Options   Quote midnit Quote  Post ReplyReply Direct Link To This Post Topic: Possible incorrect entity state after save interceptor
    Posted: 01-Apr-2011 at 9:55am

I have a SaveInterceptor that can massage an entity and add children to it. This is working as expected. The problem arrises when after such a save, a save where the interceptor added children. I correctly get the list of entities back and they are added to my EM. If I edit one of these and save it works fine. If I edit one of these, then cancel (RejectChanges), and then edit it again and try to save it, I get a concurrency error. This only happens on the entities that were added during the SaveInterceptor and only if I edit one of those entities and then RejectChanges. So I noticed when the entites are returned in the save callback these entities have a value for OriginalValuesMap. These entities are "Unchanged", if you call RejectChanges before editing them it has no effect, but if you edit them and then call RejectChanges it appears they are being returned to some state that causes a concurrency error when later saved. I have tried refetching the entities after the save (without removing them). I have tried accepting the changes, no change.

This is using 6.0.7. I cannot upgrade versions without thorough testing as our application is prepared to release - except for this issue.
 
Has this been fixed in 6.0.8 or 6.0.9? What can I do to work around this? I need to work around this very quickly.
Back to Top
midnit View Drop Down
Senior Member
Senior Member
Avatar

Joined: 22-Jun-2009
Location: Charlotte
Posts: 112
Post Options Post Options   Quote midnit Quote  Post ReplyReply Direct Link To This Post Posted: 01-Apr-2011 at 10:12am
Also, if I do use RemoveEntities and then Refetch it does "work" but the testing to verify this doesn't add memory leaks or other issues since these are new entities on almost every save - this is not a simple workaround. Is there any way to make these entities have a null OriginalValuesMap (or whatever else needs to be done to assure cancel returns values to the expect state).
Back to Top
midnit View Drop Down
Senior Member
Senior Member
Avatar

Joined: 22-Jun-2009
Location: Charlotte
Posts: 112
Post Options Post Options   Quote midnit Quote  Post ReplyReply Direct Link To This Post Posted: 04-Apr-2011 at 10:31am

Any ideas?

Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 04-Apr-2011 at 12:33pm
Hi midnit;

I wasn't able to repro this in the latest version. But I don't want to jump to conclusion saying that this has been fixed so I've provided my test case below. Please take a look and see whether my code is similar in concept to yours.


  class CustomSaveInterceptorAddsChildren : EntityServerSaveInterceptor {

    protected override bool ExecuteSave() {

      var customers = this.EntityManager.FindEntities<Customer>(EntityState.AnyAddedModifiedOrDeleted);
      if (customers.Count() > 0) {
        var aCustomer = customers.First();
        var anOrder = new Order();
        anOrder.ShipName = "TestShip";
        aCustomer.Orders.Add(anOrder);
      }

      return base.ExecuteSave();
    }
  }




    var em = new DomainModelEntityManager();

      var aCustomer = CreateNewCustomer(em);
      DoAsyncAction(() => {
        em.SaveChangesAsync(op => {
          Assert.IsTrue(op.CompletedSuccessfully);

          //var savedCustomer = em.FindEntities<Customer>(EntityState.AllButDetached).First();
          //var savedOrder = em.FindEntities<Order>(EntityState.AllButDetached).First();

          var savedCustomer = op.Entities.OfType<Customer>().First();
          var savedOrder = op.Entities.OfType<Order>().First();

          Assert.IsTrue(savedCustomer.Orders.First().OrderID == savedOrder.OrderID);
          Assert.IsTrue(savedOrder.CustomerID == savedCustomer.CustomerID);

          var oldShipName = savedOrder.ShipName;
          savedOrder.ShipName += DateTime.Now.Millisecond.ToString();
          savedOrder.EntityAspect.RejectChanges();
          Assert.IsTrue(savedOrder.ShipName == oldShipName);

          var newShipName = savedOrder.ShipName + DateTime.Now.Millisecond.ToString();
          savedOrder.ShipName = newShipName;
          em.SaveChangesAsync(op2 => {
            Assert.IsTrue(op2.CompletedSuccessfully);
            var theSavedOrder = (Order)op2.Entities.First();
            Assert.IsTrue(theSavedOrder.ShipName == newShipName);
            Exit();
          });
        });
      });

Back to Top
midnit View Drop Down
Senior Member
Senior Member
Avatar

Joined: 22-Jun-2009
Location: Charlotte
Posts: 112
Post Options Post Options   Quote midnit Quote  Post ReplyReply Direct Link To This Post Posted: 05-Apr-2011 at 3:51am
Yes I was able to try this in 6.0.9 after some work and I can confirm it is fixed. I ran into some strangeness getting the service to work after upgrading but it seems to be ok now.
 
That test looks as if it would reproduce the problem.
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 05-Apr-2011 at 10:46am
Sounds good midnit. Thanks for the confirmation.
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down