WithPath Lamba Expression PrefetchPath

Posts   
 
    
jhowes
User
Posts: 12
Joined: 18-Jun-2014
# Posted on: 27-Jan-2016 18:20:29   

I have a ton of reusable paths and I am struggling to build the prefetch from the lamba portion of the WithPath to make it reusable.


           var metaData = new LinqMetaData { CustomFunctionMappings = new DBFunctionMappings() };

            IQueryable q = (from e in metaData.Claim
                            where e.ClaimId == claimId
                            select e)
                            .WithPath(claim=>claim
                                .Prefetch<DocumentEntity>(claimDocs => claimDocs.Document)
                                .Prefetch<SubmissionEntity>(sub => sub.Submissions)
                                    .SubPath(subDocs => subDocs.Prefetch<DocumentEntity>(x => x.Document))
                            );
            return q;

I would like to reuse:


                           claim=>claim
                                .Prefetch<DocumentEntity>(claimDocs => claimDocs.Document)
                                .Prefetch<SubmissionEntity>(sub => sub.Submissions)
                                    .SubPath(subDocs => subDocs.Prefetch<DocumentEntity>(x => x.Document))

but keep it using Lamba and not using PathEdge or traditional PrefetchPath code. This is the reference post:

https://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=13639&HighLight=1

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 27-Jan-2016 18:47:41   

claim=>claim .Prefetch<DocumentEntity>(claimDocs => claimDocs.Document) .Prefetch<SubmissionEntity>(sub => sub.Submissions) .SubPath(subDocs => subDocs.Prefetch<DocumentEntity>(x => x.Document))

Did you try the following (Pseudo code)?

new PathEdge<DocumentEntity>(ClaimEntity.PrefetchPathDocuments),
new PathEdge<SubmissionEntity>(ClaimEntity.PrefetchPathDocuments, new PathEdge<DocumentEntity>(SubmissionEntity.PrefetchPathDocuments))
jhowes
User
Posts: 12
Joined: 18-Jun-2014
# Posted on: 27-Jan-2016 19:28:02   

Walaa,

That does work, but I am very interested in keeping that expression as Lamba. Is there a way to do this?


var path = claim => claim
                                .Prefetch<DocumentEntity>(claimDocs => claimDocs.Document)
                                    .Exclude(c => c.Base64Data, c => c.DocumentData)
                                .Prefetch<SubmissionEntity>(sub => sub.Submissions)
                                    .SubPath(subDocs => subDocs.Prefetch<DocumentEntity>(x => x.Document)
                                        .Exclude(c => c.Base64Data, c => c.DocumentData));


            IQueryable q = (from e in metaData.Claim
                            where e.ClaimId == claimId
                            select e)
                            .WithPath(path)
                            );
            return q;

I think this is more of a Lamda question rather than a Prefetch question?

Thanks!

Jon

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 28-Jan-2016 03:33:23   

AFAIK you can't do that, at least not that easy. If you want to reuse predicates, try PathEdge's, but if you want to use linq all the way, in my opinion you can't reuse the predicates.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 28-Jan-2016 11:24:37   

There's a way, but you have to create a method. It's not recommended to share prefetch path objects, predicates etc. as they're not thread safe.

I've illustrated it with the example below:


// original query
LinqMetaData metaData = new LinqMetaData(adapter);
var q = (from c in metaData.Customer
         where !(new string[] { "FISSA", "PARIS" }.Contains(c.CustomerId))
         select c).WithPath(customerPath => customerPath
                    .Prefetch<OrderEntity>(c => c.Orders).OrderByDescending(o => o.OrderDate).LimitTo(2)
                        .SubPath(orderPath => orderPath
                                    .Prefetch(o => o.OrderDetails)
                                    .Prefetch(o => o.Employee)));

reworked version with separate method


var q = (from c in metaData.Customer
         where !(new string[] { "FISSA", "PARIS" }.Contains(c.CustomerId))
         select c).WithPath(EntityFetches.CreatePPath());

// separate method:
private static Func<IPathEdgeRootParser<CustomerEntity>, IPathEdgeRootParser<CustomerEntity>> CreatePPath()
{
    return customerPath => customerPath
        .Prefetch<OrderEntity>(c => c.Orders).OrderByDescending(o => o.OrderDate).LimitTo(2)
        .SubPath(orderPath => orderPath
            .Prefetch(o => o.OrderDetails)
            .Prefetch(o => o.Employee));
}

The method will simply produce the set of edges you want. It's full of specific elements for this query, but it's easy to make it a bit more generic of course.

Frans Bouma | Lead developer LLBLGen Pro