Click here to Skip to main content
14,773,753 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
We have created a framework that helps us quickly creating code for fetching, sorting, filtering, inserting and updating data consumed by a REST client.
Now we need a way to dynamically join to a table, to get a value from the joined table into a projected field.

Our model:
public class CompanyPotential
{
    [AutoLabel]
    public long LabelRecordId { get; set; }
}

The DTO projected to the client:
public class CompanyPotentialOutDto
{
    [AutoLabel(nameof(CompanyPotentialOutDto.Name))]
    public long LabelRecordId { get; set; }

    public string Name { get; set; }
}

The model we want to join with (also shortened):
public class ClientLabelValueView
{
    public long LabelRecordId { get; set; }
    public long LanguageRecordId { get; set; }
    public string LabelValue { get; set; }
}

What all this means, is that fields decorated with that AutoLabel attributes, will be handled by the framework. There can be 0 to N labeled fields for every entity in our application.
In the example above, we want to join CompanyPotential with ClientLabelValueView on LabelRecordId, to project ClientLabelValueView.LabelValue into CompanyPotentialOutDto.Name.
Because all this is dynamic, our framework works with expression trees.

What I have tried:

I have successfully injected a join on ClientLabelValueView into the basic query.
What I'm struggling with, is to inject a member initialization in the projection block.
And I also need to inject a criteria for the joined table in the where clause.
All of this can be created through Linq, so it stands to reason that it should be possible to create it using expression trees.
I have tried to use ExpressionVisitor to inject the init fields, and it works great if I use constant values. But when I try to get the value from the joined table, I get this error:
Quote:
The parameter 'MyParameterName' was not bound in the specified LINQ to Entities query expression.

I can't seem to find anything about joins in expression trees on Google, but I hope that one of you guys knows what to do!
Posted
Updated 12-Jan-21 21:41pm

1 solution

Even I have used LINQ very less at work, based on error message found these threads. Without seeing code, it's hard to guess.
Ho Hai Thanh's Blog: LINQ to Entities: PredicateBuilder and Dynamic Linq[^]
c# - Runtime joins to query within Entity Framework - Stack Overflow[^]
C# PredicateBuilder Entities: The parameter 'f' was not bound in the specified LINQ to Entities query expression - Stack Overflow[^]

Also found this blog post which looks nice
Don’t use Linq’s Join. Navigate![^]

And it would be nice if you share your own solution here if you fixed it already.
   
Comments
jan larsen 13-Jan-21 8:44am
   
Hi, thank you for the links. I really like the link about Navigate attributes, i didn't know about them.
While they are not, at a glance, enough for my needs, they would maybe be a solution for something else I had in mind.
Yes, I did find a solution, but it is not built as a simple general solution.
I promise that I will post it as an article if I get the time to polish it.
I do have a slight suspicion that I have overengineered the thing a bit though. Because the sequence is basically like this:
For every field with a label attribute:
1. Add join
2. Add select block
3. Rebind fields in the select block

After all this, the our framework allows developers to adding other joins, and as we do not know if they have selected the same fields in the same order, which would be weird if they did, because why else make a join?, we have to ensure that all select blocks returning the same type, are having the same fields in the same order.

By the way, I read the post about navigation properties, and I was about to check out the Association one, but MS has marked it obsolete.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900