reuse/merge of prefetch paths?

Posts   
 
    
magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 08-Dec-2008 21:32:05   

I have two entities, lets call them customer and order for simplicities' sake. I have two wrapper classes that handle these functionalities, in particular each class has a method that returns the needed prefetch path.

Now if I want to fetch a given order, I need the order prefetch path, and I also would like to use the prefetch path defined in the customer class. To specify the same prefetch already defined in the customer class also in the order class, seems like a waste of time and leads to inconsistencies (when one functionality/path is updated).

So I was wondering, whether there is a functionality (that I can't find) that adds a whole prefetch path as a subpath of another prefetch path? Or whether I should write one myself? Or whether the whole idea of merging the prefetch paths is not a good idea at all? wink

So far I have only come across path.SubPath.Add(IPrefetchElement2 element). My idea would be a functionality like path.SubPath.Add(IPrefetchElement2 connectElement, IPrefetchPath2 subpath).

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 09-Dec-2008 05:09:15   

AFAIK that isn't possible unless you build that utility yourself.

David Elizondo | LLBLGen Support Team
magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 09-Dec-2008 13:31:45   

daelmo wrote:

AFAIK that isn't possible unless you build that utility yourself.

ok, but before I do it for myself, I would like to know whether this is something that was not implemented so far because there was no need for it (there were more important things to implement etc.), or something that by LGP philosophy shouldn't be done?

From my (very small) experience with LGP so far, it seems to be quite important if I don't want to maintain the prefetch paths at 10 different places in my code if I want to change one thing.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39859
Joined: 17-Aug-2003
# Posted on: 10-Dec-2008 10:43:02   

Prefetch paths are build using Prefetch path element objects (the objects created by the generated methods in the entity classes). These are added to PrefetchPath(2) instances to build a tree (e.g. by adding them to the PrefetchPath(2) instance returned by SubPath())

The only thing that's required is that a prefetch path element is compatible with the entity type of the PrefetchPath(2) instance it is added to.

So if you create a path by doing: PrefetchPath2 path = new PrefetchPath(EntityType.CustomerEntity); you can then add prefetch path elements (e.g. CustomerEntity.PrefetchPathOrders) which are meant for Customer, so which describe how to fetch entities related to Customer.

If I then do: IPrefetchPathElement2 orderElement = path.Add(CustomerEntity.PrefetchPathOrders);

I have access to a new container, namely orderElement.SubPath(). This routine returns a PrefetchPath2 instance which is for OrderEntity, and which accepts prefetch path element instances which are meant for Order and which describe how to fetch entities related to Order.

As long as you don't break this pattern, you can move around the path elements freely. Every path element is fetched separately, with the help of the parent elements. I'm not sure what you meant with 'the prefetch path for customer and the prefetch path for order', as a prefetch path is always from a root element (in my example above 'Customer') to sub elements. You werent' very clear in your startpost, as you simply described classes with paths but what these paths look like is unclear.

So if you have two prefetch paths, e.g. Customer -> Order and Order -> OrderDetails, you can add the Order -> OrderDetails path as the path from Order in Customer -> Order, by adding the Order element of Order->OrderDetails to the SubPath() path container of Order in Customer -> Order. As long as you add elements meant for entity E to a PrefetchPath(2) instance meant for E, you're fine.

Keep in mind that adding path element instances multiple times to the same path is not going to work. That's also why the elements returned from the static properties aren't cached, but re-created every time. The reason is that the data fetched for that element is stored inside the element till it's merged into the parent's data.

Frans Bouma | Lead developer LLBLGen Pro
magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 10-Dec-2008 14:39:39   

Otis, thank you for your explanation. I think I understand the basics, but maybe I didn't phrase my problem correctly. When talking about a "path" I actually meant the whole "path tree". So for example:


// CustomerAdapter
public static IPrefetchPath2 getPrefetchPath()
{
    IPrefetchPath2 prefetch = new PrefetchPath2(EntityType.CustomerEntity);

    // to the hometown and it's province
    prefetch.Add(CustomerEntity.PrefetchPathCity)
        .SubPath.Add(CityEntity.PrefetchPathProvince);
}

// OrderAdapter
public static IPrefetchPath2 getPrefetchPath()
{
    IPrefetchPath2 prefetch = new PrefetchPath2(EntityType.OrderEntity);

    // to the product and it's category
    prefetch.Add(OrderEntity.PrefetchProduct)
        .SubPath.Add(ProductEntity.PrefetchPathProductCategory);

    // to the customer and his city & province
    prefetch.Add(OrderEntity.PrefetchPathCustomer)
        // redundant part (defined in CustomerAdapter.gePrefetchPath()
        .SubPath.Add(CustomerEntity.PrefetchPathCity)
        .SubPath.Add(CityEntity.PrefetchPathProvince);
}

Instead of adding the second redundant prefetch path in the OrderAdapter, I thought it would be better to add the customer prefetch tree as a subtree of the order prefetch tree.

So something like:


// OrderAdapter
public static IPrefetchPath2 getPrefetchPath()
{
    IPrefetchPath2 prefetch = new PrefetchPath2(EntityType.OrderEntity);

    // to the product and it's category
    prefetch.Add(OrderEntity.PrefetchProduct)
        .SubPath.Add(ProductEntity.PrefetchPathProductCategory);

    // to the customer and his city & province
    prefetch.Add(OrderEntity.PrefetchPathCustomer
        .SubPath.AddTree(CustomerAdapter.getPrefetchPath());
}

Now - beside the fact that one would have to play around with the functionality (root node, path elements, etc.) - does this approach make sense in terms of LGP philosophy, or not?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 10-Dec-2008 17:14:30   

What you want to do is possible, as Frans has explained before.

Please check the following code:

// CustomerAdapter
public static void getPrefetchPath(IPrefetchPath2 prefetch)
{
    // to the hometown and it's province
    prefetch.Add(CustomerEntity.PrefetchPathCity)
        .SubPath.Add(CityEntity.PrefetchPathProvince);
}

// OrderAdapter
public static void getPrefetchPath(IPrefetchPath2 prefetch)
{
    // to the product and it's category
    prefetch.Add(OrderEntity.PrefetchProduct)
        .SubPath.Add(ProductEntity.PrefetchPathProductCategory);

    // to the customer and his city & province

    IPrefetchPathElement2 prefetchCustomer = prefetch.Add(OrderEntity.PrefetchPathCustomer);

    CustomerAdapter.getPrefetchPath(prefetchCustomer.SubPath);
}

Then to consume the OrderAdapter.getPrefetchPath, you should do the following.

IPrefetchPath2 prefetch = new PrefetchPath2(EntityType.OrderEntity);
OrderAdapter.getPrefetchPath(prefetch);
magic
User
Posts: 125
Joined: 24-Nov-2008
# Posted on: 10-Dec-2008 17:58:23   

Walaa, thank you for the help. simple_smile I will try to incorporate the idea in my project.