Problem with cloning

Posts   
 
    
olav78
User
Posts: 8
Joined: 14-Jun-2007
# Posted on: 19-Nov-2007 15:52:12   

Hello!

We are using llblgen Pro 2.0 (adapter) in a client/service scenario with a wcf service running on the server and windows forms on the client. We have a sircular relation in the sql server database like this: Order 1:m relation with OrderDetail Order 1:m relation with delivery OrderDetail m:n relation with Delivery

When trying to clone one order and then save the cloned order, we get problems. The problem occurs when we clone the orderDetailDelivery (the m:n table) more than once: The order we clone from get extra orderDetailDelivery entities each time we save the cloned order (the cloned order is fine). Can anyone explain why this happen?


OrderEntity order = new OrderEntity();
IServiceClass service = ProxyFactory.ServiceClass;
using (service as IDisposable)
{
    //fetches order.Delivery and OrderDetailDelivery for each delivery, Also fetches
    //order.OrderDetail and OrderDetailDelivery for each orderDetail
    order = service.GetOrderWithFetchedEntities("660100", string.Empty, string.Empty);
}

//each time we run this "application" the value get higher
Console.WriteLine("Number of orderDetailDeliveries: " + order.Delivery[0].OrderDetailDelivery.Count.ToString());

OrderEntity clonedOrder = new OrderEntity();
clonedOrder.Fields = order.Fields.CloneAsDirty();
foreach (DeliveryEntity delivery in order.Delivery)
{
    DeliveryEntity clonedDelivery = new DeliveryEntity();
    clonedDelivery.Fields = delivery.Fields.CloneAsDirty();
    foreach(OrderDetailDeliveryEntity odd in delivery.OrderDetailDelivery)
    {
    OrderDetailDeliveryEntity clonedOdd = new OrderDetailDeliveryEntity();
    clonedOdd.Fields = odd.Fields.CloneAsDirty();
    clonedDelivery.OrderDetailDelivery.Add(clonedOdd);
    }
    clonedOrder.Delivery.Add(clonedDelivery);
}
foreach (OrderDetailEntity orderDetail in order.OrderDetail)
{
    OrderDetailEntity clonedOrderDetail = new OrderDetailEntity();
    clonedOrderDetail.Fields = orderDetail.Fields.CloneAsDirty();
    foreach (OrderDetailDeliveryEntity odd in orderDetail.OrderDetailDelivery)
    {
    OrderDetailDeliveryEntity clonedOdd = new OrderDetailDeliveryEntity();
    clonedOdd.Fields = odd.Fields.CloneAsDirty();
    clonedOrderDetail.OrderDetailDelivery.Add(clonedOdd);
    }
    clonedOrder.OrderDetail.Add(clonedOrderDetail);
}

service = ProxyFactory.ServiceClass;
using (service as IDisposable)
{
    service.saveOrder(clonedOrder);
}

Olav

goose avatar
goose
User
Posts: 392
Joined: 06-Aug-2007
# Posted on: 19-Nov-2007 17:07:06   

Hi, Can you debug to know exactly in which line the originalOrder get extra orderDetailDelivery? What LLBLGen version and RuntimeLibraries version are you using?

olav78
User
Posts: 8
Joined: 14-Jun-2007
# Posted on: 19-Nov-2007 21:02:06   

The extra orderDetailDelivery for the original order is inserted in the database when you save the cloned order. So you won’t see it before you refetch the original order. By the way, the save method is just :


public OrderEntity saveOrder(OrderEntity order)
{
    using (DataAccessAdapter adapter = new DataAccessAdapter())
    {
    adapter.SaveEntity(order, true, true);
    }
    return order;
}

We are using the 2.0.0.0 final version and the SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll v2.0.50727.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 20-Nov-2007 04:06:52   
The extra orderDetailDelivery for the original order is inserted in the database when you save the cloned order. So you won’t see it before you refetch the original order.

Did you mean that right before the save routine the _originalOrder _is the same (there isn't in-memory extra orderDetailDelivery)?

BTW, what's the difference between originalOrder and clonedOrder?.. I mean: Where do you change the PK?

David Elizondo | LLBLGen Support Team
olav78
User
Posts: 8
Joined: 14-Jun-2007
# Posted on: 20-Nov-2007 09:10:02   

Did you mean that right before the save routine the originalOrder is the same (there isn't in-memory extra orderDetailDelivery)?

yeah, thats right.

BTW, what's the difference between originalOrder and clonedOrder?.. I mean: Where do you change the PK?

I do not change the pk, but the clonedOrder is cloned as dirty, so clonedOrder.IsNew==true. Anyway the same thing happen when I set clonedOrder.OrderId = 0; before I save.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 20-Nov-2007 10:10:59   

I bet the following count will get bigger each time too (maybe doubled)

Console.WriteLine("Number of orderDetailDeliveries: " + order.OrderDetail[0].OrderDetailDelivery.Count.ToString());

I think it's because of the way you clone the m:n relation between OrderDetail & Delivery.

For example the bellow code:

foreach (OrderDetailEntity orderDetail in order.OrderDetail) { OrderDetailEntity clonedOrderDetail = new OrderDetailEntity(); clonedOrderDetail.Fields = orderDetail.Fields.CloneAsDirty(); foreach (OrderDetailDeliveryEntity odd in orderDetail.OrderDetailDelivery) { OrderDetailDeliveryEntity clonedOdd = new OrderDetailDeliveryEntity(); clonedOdd.Fields = odd.Fields.CloneAsDirty(); clonedOrderDetail.OrderDetailDelivery.Add(clonedOdd); } clonedOrder.OrderDetail.Add(clonedOrderDetail); }

The cloned OrderDetailDelivery (added to the cloned OrderDetail Entity) will still hold a FK to the original Delivery Entity which belongs to the original Order Entity.

Instead you should traverse the Graph in one loop from one end to the other, rather than doing it in 2 separated for loops, one from each end.