PrefetchPaths with Lambdas

Posts   
1  /  2
 
    
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 24-Mar-2008 17:26:14   

There's a small issue with m:n relations I think, as 'PathElementCreator.CreateRelation' can't handle 2 relations. I'll add that code.

(edit) ok the code compiles, I'll now port the unittests for prefetch paths over to the new API and give it a spin simple_smile It will be tomorrow for a new release though.

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 24-Mar-2008 19:10:34   

I just ran into the m:n issue myself flushed Sorry about that.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 24-Mar-2008 20:31:09   

This should fix it:


/// <summary>
/// Creates the prefetch path element.
/// </summary>
/// <returns>ready to use prefetch path element</returns>
public IPrefetchPathElementCore CreatePrefetchElement()
{
    IRelationCollection relationsBetweenSourceAndDestination = _sourceInstance.GetRelationsForFieldOfType(_propertyName);
    IEntityRelation pathElementRelation = (IEntityRelation)relationsBetweenSourceAndDestination[0];
    IRelationCollection filterRelations = null;
    RelationType typeOfPathElementRelation = pathElementRelation.TypeOfRelation;

    if(relationsBetweenSourceAndDestination.Count>1)
    {
        // m:n relation
        // obtain the relations again, as we've to reset the aliases on the pathElementRelation, so we need to prevent from modifying the relation
        // inside the collection.
        filterRelations = _sourceInstance.GetRelationsForFieldOfType(_propertyName);
        pathElementRelation.SetAliases(string.Empty, pathElementRelation.AliasEndEntity);
        typeOfPathElementRelation = RelationType.ManyToMany;
    }
    else
    {
        pathElementRelation = (IEntityRelation)relationsBetweenSourceAndDestination[0];

    }

    if(_isSelfServicing)
    {
        return new PrefetchPathElement(
            CreateEntityCollectionSelfServicing(),
            pathElementRelation, _sourceInstance.LLBLGenProEntityTypeValue,
            _destinationInstance.LLBLGenProEntityTypeValue,
            0,
            null,
            null,
            filterRelations,
            _propertyName,
            typeOfPathElementRelation
            );
    } 
    else 
    {
        return new PrefetchPathElement2(
            CreateEntityCollectionAdapter(),
            pathElementRelation, _sourceInstance.LLBLGenProEntityTypeValue,
            _destinationInstance.LLBLGenProEntityTypeValue,
            0,
            null,
            null,
            filterRelations,
            null,
            _propertyName,
            typeOfPathElementRelation
            );
    }
}

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 12:22:56   

I had a bit of a problem writing this:


.WithPath(new PathEdge<OrderEntity>(CustomerEntity.PrefetchPathOrders,
                           new PathEdge<EmployeeEntity>(OrderEntity.PrefetchPathEmployee)),
                   new PathEdge<EmployeeEntity>(CustomerEntity.PrefetchPathEmployeeCollectionViaOrder));

with your code. The main hickup I had was: do I have to specify another Subpath or not? But it turned out to be not the case:


.WithPath(customerPath => customerPath
        .Prefetch<OrderEntity>(c => c.Orders).SubPath(orderPath => orderPath.Prefetch(o => o.Employee))
        .Prefetch<EmployeeEntity>(c => c.EmployeeCollectionViaOrder));

simple_smile

What I'm a bit struggling with, but that's the same as with my api I think, is that it's not that intuitive at first, also because of the classes in the tooltip info. But I think that's unavoidable... After you realize you've to specify .Prefetch for nodes at the same level and .SubPath for nodes below the current level, it's ok simple_smile

I really like the way you have solved it via the lambdas, very clever simple_smile

I'll change 'Limit' into 'LimitTo' (or is LimitBy better english? )

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 25-Mar-2008 12:41:44   

Otis wrote:

I really like the way you have solved it via the lambdas, very clever simple_smile

Thanks simple_smile

Otis wrote:

I'll change 'Limit' into 'LimitTo' (or is LimitBy better english? )

I think LimitTo sounds better.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 13:24:30   

Ok LimitTo it is simple_smile

Selfservicing has some issues with destination type, ('OrderCollection' is the destination type instead of OrderEntity), will fix that. All adapter tests run already so almost there simple_smile (the issue is introduced by me cleaning up GetPrefetchElementType flushed )

(edit) ok DONE simple_smile

I'll now cram in Skip and a WithPath(IPrefetchPath(2)) overload and will release a new build simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 14:35:30   

I thought of some tiny issue... sorting on related entity's fields:

var q = (from od in metaData.OrderDetail
         where od.ProductId > 10
         select od).WithPath(p => p.Prefetch<OrderEntity>(od => od.Order).OrderBy(o => o.Customer.Country));

With the pathedge stuff, this isn't possible, as you have to specify the sortexpression, but you can't specify a relation collection to join the related entity with. I realize this is an oversight, however for the pathedges this isn't really addable, it would otherwise require awkward relation object additions.

What I'll try to do is to wrap the lambda passed into OrderBy()/OrderByDescending() to add these to a new SortClauseExpression list inside pathedge, as these handle the correlation relations automatically.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 14:59:10   

I said something stupid here... ignore flushed

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 25-Mar-2008 15:06:24   

Ah right, I assumed that creating the PrefetchPathElement was necessary as PathEdge<T> requires it in the ctor. If this isn't the case, then this certainly simplifies things a bit.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 15:18:46   

Jez wrote:

Ah right, I assumed that creating the PrefetchPathElement was necessary as PathEdge<T> requires it in the ctor. If this isn't the case, then this certainly simplifies things a bit.

Nah, my bad, it is altered later on indeed. I overlooked that fragment in my code.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 15:26:10   

Ok, works! smile

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39618
Joined: 17-Aug-2003
# Posted on: 25-Mar-2008 18:45:53   

It's available simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 25-Mar-2008 19:23:00   

Woohoo simple_smile

1  /  2