Always Prefetch

Posts   
 
    
garrett
User
Posts: 33
Joined: 21-Feb-2008
# Posted on: 23-Jul-2008 19:33:51   

Just throwing this one out there to see what way people are working this (or indeed if there is a standard way)

Using Adapter, I have a relation on a several different entity types that I ALWAYS want to prefetch. Is there any way to have adapter always automatically load the relation rather than having to specify it in the query?

Thanks Garrett

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 24-Jul-2008 06:46:11   

Hi Garrett, prefetches aren't done by default as it WILL hurt performance in the long run and you're then stuck with the prefetch even when you don't want to load the related entities.

I never did that. However I can think in two options:

A. Write some Manager class that take care of the fetch, save, etc., then you add the desired prefetchpath and return the fetched collection.

public static class CustomerManager
{
     public static EntityCollection<CustomerEntity> GetAllCustomers()
     {
           EntityCollection<CustomerEntity> toReturn = new EntityCollection<CustomerEntity>(...);
           IPrefetchPath2 path = new PrefetchPath((int) EntityType.Customer);
           path.Add(CustomerEntity.PrefetchPathOrders);

           ....

           return toReturn;     
     }
}

B. Extend DataAccessAdapter, override FetchEntityCollection, and there you can pass the prefetchPathToUse depending on the fetching entity to the base call.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39863
Joined: 17-Aug-2003
# Posted on: 24-Jul-2008 10:12:21   

The 'always' part is indeed something you might regret in the long run, when you want to work with solely the parent entities in some process for performance reasons.

I'd indeed go for option 1 in David's reply: write a method which does this easily for you: it is abstracted away, and the code you have to write is easier: just call one method.

There's another reason we didn't implement this: The 'always' part suggests that there's no filter possible on the related entities, but this is sometimes required. So if people want this, they should write a small method and use that instead.

An example is "order" and "Orderline". Often, people say that an Order should always be fetched with its orderlines and an orderline isn't something you can fetch separately. However, when one wants to display orders, why fetch the orderlines ? It's not as if they're needed in that context.

Frans Bouma | Lead developer LLBLGen Pro
garrett
User
Posts: 33
Joined: 21-Feb-2008
# Posted on: 10-Sep-2008 12:36:30   

Sorry to pick this on up again, but this is all related.

I'm using Linq -> instead of saying I always want to include a prefetch path, how can I create either a method or property that I can append to my Linq query which will define an extra set of SubPaths?

Can i use IPathEdgeParser or IPathEdgeRootParser to create a predefined set of subpaths?

for instance something like

var q = (from c in metaData.Customer select c).WithPath(p=>p.Prefetch(c=>c.Orders) .SubPath(Country.MyExtraSubPaths));

Thanks Garrett

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 10-Sep-2008 17:49:44   

Can i use IPathEdgeParser or IPathEdgeRootParser to create a predefined set of subpaths?

I think you mau use IPathEdgeParser.

Also I think if you want to return a full prefetchPath, you may try IPathEdge[].

garrett
User
Posts: 33
Joined: 21-Feb-2008
# Posted on: 10-Sep-2008 18:08:29   

Thanks Walaa

Do you know of any examples round the forum or otherwise?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 10-Sep-2008 18:20:48   

Aside from this thread, the following thread is the only place where this interface was mentioned in the forums. http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=12983

garrett
User
Posts: 33
Joined: 21-Feb-2008
# Posted on: 10-Sep-2008 18:27:33   

Yeh I seen that one before, if I can use the syntax below it will be pretty neat. Will try when I get home.

IPathEdge[] edges = new IPathEdge[] { new PathEdge<MusicianInstrumentEntity>(MusicianEntity.PrefetchPathMusicianInstruments, new PathEdge<InstrumentEntity>(MusicianInstrumentEntity.PrefetchPathInstrument, new PathEdge<ShellMaterialEntity>(DrumKitEntity.PrefetchPathShellMaterial))) };

Thanks Garrett

garrett
User
Posts: 33
Joined: 21-Feb-2008
# Posted on: 10-Sep-2008 23:54:44   

Does seem to like my method that returns IPathEdge[] very much

Do I need to create a method that returns a Func<IPathEdgeRootParser<T.....

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39863
Joined: 17-Aug-2003
# Posted on: 11-Sep-2008 16:41:51   

The .SubPath method works like it's called multiple times: .WithPath(a=>a.Prefetch(...) .SubPath(s1=>s1.Prefetch.... ) .SubPath(s2=>s2.Prefetch....)

etc.

so the argument of SubPath isn't accepting a set of paths. What you should do is create an extensionMethod of IPathEdgeParser (.SubPath is also a method of that type), which simply chains SubPath call together. Though it might become complex really quickly...

You could also check in the source what SubPath does, which is creating a new parser and passes that to the lambda, which thus calls the SubPath on that parser.

The lambda variant does produce IPathEdge elements in the end, so if you use the IPathEdge variant, you can pass in an array of IPathEdge elements as the argument, which might be easier to work with I think in this case.

Frans Bouma | Lead developer LLBLGen Pro
garrett
User
Posts: 33
Joined: 21-Feb-2008
# Posted on: 11-Sep-2008 22:58:59   

Nice one Otis! That extension methods solution works fantastically well.