Dereferencing related entity

Posts   
 
    
Kazak1
User
Posts: 39
Joined: 30-May-2006
# Posted on: 10-May-2007 18:27:13   

2.0.0.0 Final March 21, 2007 Adapter, .net 2.0, SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll (2.0.7.402) Oracle 10g Driver (ODP.NET 10.1.x)

According to the following excerpt from the documentation, setting myOrder.Customer property to null (line B) would set myOrder.CustomerId field to null.

// C#
PrefetchPath2 path = new PrefetchPath2((int)EntityType.OrderEntity);
path.Add(OrderEntity.PrefetchPathCustomer);
OrderEntity myOrder = new OrderEntity(10254);
adapter.FetchEntity(myOrder, path);     // A
myOrder.Customer = null;    // B

At line A, the prefetch path loads the related Customer entity together with the Order entity 10254. At line B, this customer is dereferenced. This means that the FK field of order creating this relation, myOrder.CustomerId, will be set to null (Nothing). So if myOrder is saved after this, NULL will be saved in the field Order.CustomerId

However, it works only when a prefetch path is used to fetch related Customer entity. The following example will not get Customer dereferenced.


OrderEntity myOrder = new OrderEntity(10254);
adapter.FetchEntity(myOrder);
myOrder.Customer = null;

Is this a "by design" behavior? If yes, would it be more consistent to always set Order.CustomerId to null when Order.Customer is set to null?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-May-2007 12:21:36   

Kazak1 wrote:

2.0.0.0 Final March 21, 2007 Adapter, .net 2.0, SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll (2.0.7.402) Oracle 10g Driver (ODP.NET 10.1.x)

According to the following excerpt from the documentation, setting myOrder.Customer property to null (line B) would set myOrder.CustomerId field to null.

// C#
PrefetchPath2 path = new PrefetchPath2((int)EntityType.OrderEntity);
path.Add(OrderEntity.PrefetchPathCustomer);
OrderEntity myOrder = new OrderEntity(10254);
adapter.FetchEntity(myOrder, path);     // A
myOrder.Customer = null;    // B

At line A, the prefetch path loads the related Customer entity together with the Order entity 10254. At line B, this customer is dereferenced. This means that the FK field of order creating this relation, myOrder.CustomerId, will be set to null (Nothing). So if myOrder is saved after this, NULL will be saved in the field Order.CustomerId

However, it works only when a prefetch path is used to fetch related Customer entity. The following example will not get Customer dereferenced.


OrderEntity myOrder = new OrderEntity(10254);
adapter.FetchEntity(myOrder);
myOrder.Customer = null;

Is this a "by design" behavior? If yes, would it be more consistent to always set Order.CustomerId to null when Order.Customer is set to null?

It's a bit of a problem. The thing is: myOrder.Customer is null already. Setting it to null, doesn't make a change.

If there's a customer referenced from order, it will reset the FK:


[Test]
public void FkResetTest()
{
    OrderEntity o = new OrderEntity(10254);
    using(DataAccessAdapter adapter = new DataAccessAdapter())
    {
        adapter.FetchEntity(o);
        o.Customer = (CustomerEntity)adapter.FetchNewEntity(new CustomerEntityFactory(), o.GetRelationInfoCustomer());
    }

    Assert.IsNotNull(o.Customer);
    Assert.AreEqual(o.CustomerId, o.Customer.CustomerId);
    Assert.AreEqual("CHOPS", o.CustomerId);

    o.Customers = null;
    Assert.AreEqual("", o.CustomerId);
}

So to actively DE-reference an entity B from an entity A, you have to make that change, so the code knows "Oh, the entity is dereferenced, so we'll have to reset the FK". Now you don't make a change. It's confusing abit, due to the fact that the null of Customer can mean two things: - the order has no customer referenced OR - the customer hasn't been loaded yet.

Frans Bouma | Lead developer LLBLGen Pro
arschr
User
Posts: 893
Joined: 14-Dec-2003
# Posted on: 11-May-2007 13:10:14   
  • the order has no customer referenced OR
  • the customer hasn't been loaded yet.

If we just have the order entity and no visibility to what's happened to it in that past, is there a way to know which of the two possibilities is the case? This question also relates to a related case when we have a collection of related entities such as order.orderdetailcollection. How can we tell if orderdetailcollection is empty because nothing was fetched or because the fetch hasn't been attempted yet?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 12-May-2007 09:58:32   

If we just have the order entity and no visibility to what's happened to it in that past, is there a way to know which of the two possibilities is the case? This question also relates to a related case when we have a collection of related entities such as order.orderdetailcollection. How can we tell if orderdetailcollection is empty because nothing was fetched or because the fetch hasn't been attempted yet?

http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=2013

David Elizondo | LLBLGen Support Team
arschr
User
Posts: 893
Joined: 14-Dec-2003
# Posted on: 12-May-2007 13:13:28   

Quoting from Frans in the other message.

Isn't that a bit weird? I mean: the adapter classes are considered disconnected from whatever persistence store, so if there is no data in the collection, either you didn't fetch it or it wasn't there. Which one it is, depends on your own code. If you request the data for some entity and some related collections, the data is thus fetched and apparently there was no data.

the thing is that you should simply think in these steps: - I want to process something - I need data - I get the data - I got the data and will now process it. - I'm finished processing - Next!

You're either in this cycle or outside this cycle.

So the answer is no.

I don't think this analysis is correct. Who knows where the entity I have came from or what processes it's been through before it got to me. There are many cases where I won't care to or can't know the detailed history of the entity I'm working with. The database may not be easily and cheaply available. So if a entities collection is empty, it may not be practical to just go try to fill it again to see if it is (or still is) in the database.

As a feature in a future version I'd like to see a way to tell the difference.

mikeg22
User
Posts: 411
Joined: 30-Jun-2005
# Posted on: 13-May-2007 09:43:25   

arschr wrote:

Quoting from Frans in the other message.

Isn't that a bit weird? I mean: the adapter classes are considered disconnected from whatever persistence store, so if there is no data in the collection, either you didn't fetch it or it wasn't there. Which one it is, depends on your own code. If you request the data for some entity and some related collections, the data is thus fetched and apparently there was no data.

the thing is that you should simply think in these steps: - I want to process something - I need data - I get the data - I got the data and will now process it. - I'm finished processing - Next!

You're either in this cycle or outside this cycle.

So the answer is no.

I don't think this analysis is correct. Who knows where the entity I have came from or what processes it's been through before it got to me. There are many cases where I won't care to or can't know the detailed history of the entity I'm working with. The database may not be easily and cheaply available. So if a entities collection is empty, it may not be practical to just go try to fill it again to see if it is (or still is) in the database.

As a feature in a future version I'd like to see a way to tell the difference.

I always thought it would make sense if the collection was NULL if the data was not fetched, and empty if it was fetched but there was no related data. That said, I have never come across a situation where I don't know the prefetch path that was used to fetch the data in the context of where I am using the data, so this hasn't really been a problem. I'm pretty convinced that the place where the data is used HAS to know the edges of the graph, and assume it is getting all the data it needs. If it is not getting all the data it needs, then it can't do its job anyway unless there is some kind of custom lazy-loading system to fill in missing branches. If this is the case, then the custom lazy loading system can keep track of what it has loaded and what it has not loaded. I don't think it would be useful for collections to track whether they have been fetched or not unless you plan on lazy loading one collection at a time (as opposed to larger branches at a time). Might as well use SelfServing if this is the plan!