PrefetchPath with Context fetches deleted Entities

Posts   
 
    
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 08-Feb-2016 14:32:59   

Hi guys

I'm using the adapter model. I fetch an order with prefetchpath to orderdetails with a context, then delete some of the details using LLBLGen code. Then I do the fetch again into a new order but using the same context .

In the 2nd order's orderdetail I now have the same details as in the first, with the deleted details marked as such. Since this results from a separate DB-fetch I'd expect the deleted details not to be in the collection at all...

Is this really how a prefetchpath with context is intended to work?

Thanks for any enlightenment simple_smile

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 08-Feb-2016 16:18:25   

Could you please post some code snippet, especially those showing how you deleted the OrderDetails.

JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 08-Feb-2016 17:10:27   

For Northwind-DB:


[TestMethod]
public void PrefetchPathContextTest()
{
    const int orderID = 11077;

    var pp = new PrefetchPath2(EntityType.OrderEntity);
    pp.Add(OrderEntity.PrefetchPathOrderDetails);

    var ctx = new Context();
    var count = 0;

    using (var daa = new DataAccessAdapter())
    {
        var orders = new EntityCollection<OrderEntity>() { ActiveContext = ctx };
        daa.FetchEntityCollection(orders, new RelationPredicateBucket(OrderFields.OrderId == orderID), pp);

        count = orders[0].OrderDetails.Count();

        daa.DeleteEntity(orders[0].OrderDetails[3]);
        daa.DeleteEntity(orders[0].OrderDetails[1]);

        orders.Dispose();
    }

    // now repeat with all new variables, but keep the context
    using (var daa = new DataAccessAdapter())
    {
        var orders = new EntityCollection<OrderEntity>() { ActiveContext = ctx };
        daa.FetchEntityCollection(orders, new RelationPredicateBucket(OrderFields.OrderId == orderID), pp);

        Assert.IsTrue(orders[0].OrderDetails.Count() == count - 2);
    }
}

To simplify a bit I'm loading just one order, but in any case I'd not expect to have fetched the deleted details with the 2nd FetchEntityCollection.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 08-Feb-2016 20:23:43   

You need to either refresh (use a new) context. Or remove them from the context when deleting them from the database.

ctx.Remove(orders[0].OrderDetails[3]);
ctx.Remove(orders[0].OrderDetails[1]);

daa.DeleteEntity(orders[0].OrderDetails[3]);
daa.DeleteEntity(orders[0].OrderDetails[1]);
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 09-Feb-2016 09:42:22   

OK thank you.

I thought this woud be done automatically, as Context.Get removes deleted entities...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Feb-2016 10:31:32   

What version are you using? I have to check but pulling the entity instance during the fetch from the context by the engine will use Get under the hood and thus will not re-use a deleted entity.

I agree it's inconsistent behavior, even though Context shouldn't be used as a cache.

Frans Bouma | Lead developer LLBLGen Pro
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 09-Feb-2016 11:38:23   

I tested this with current 4.2.

As to using the context as cache: our problem here is, we have loads of code that wasn't really designed to work together. Now that we have to make it work together, adding a common context to all involved functions of a complex operation mostly has a beneficient effect wink So caching isn't our intent. No time for a big refactoring, however... rage

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Feb-2016 15:15:31   

I thought it was a bug but it's not and has actually little to do with the context. simple_smile

The thing is that the delete statement to delete the entity won't remove it from the collection. So after


daa.DeleteEntity(orders[0].OrderDetails[3]);
daa.DeleteEntity(orders[0].OrderDetails[1]);

the entities are still in 'orders[0].OrderDetails'. The second fetch will not fetch the deleted entities again (as they're not in the DB) however it will fetch the same order. The context still has this order and will return that instance instead. As that instance still has the 2 deleted entities in its OrderDetails collection, you still see them. So they're not pulled from the context, as they're not loaded again, however they're sticking around because they're not removed from the collection they're in.

To work around this, assign a tracker collection to OrderDetails and simply remove the orderdetails entity from orders[0].OrderDetails, so it is added to the tracker collection. Then call DeleteEntitiesCollection by passing the tracker collection. (see: http://www.llblgen.com/documentation/4.2/LLBLGen%20Pro%20RTF/hh_goto.htm#Using%20the%20generated%20code/Adapter/gencode_usingcollectionclasses_adapter.htm#trackingremoves )

You can simplify this with DataScopes which take of the bookkeeping for you and simply hand you a unit of work which you can persist. See: http://www.llblgen.com/documentation/4.2/LLBLGen%20Pro%20RTF/hh_goto.htm#Using%20the%20generated%20code/gencode_datascopes.htm

Hopefully this helps simple_smile

Frans Bouma | Lead developer LLBLGen Pro
JuergenF
User
Posts: 29
Joined: 23-May-2006
# Posted on: 10-Feb-2016 09:49:17   

Thanks!