user2657943 user2657943 - 1 year ago 140
C# Question

The parameter 'p' was not bound in the specified LINQ to Entities query expression

I am trying to do a quick test to make my own linq queries using a custom helper file. But when I run the query I get an error saying

.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.OrderBy(
.Call System.Linq.Queryable.Join(
.Call System.Linq.Queryable.Join(
.Call .Constant<System.Data.Entity.Core.Objects.ObjectQuery`1[S20_Workflow.Domain.Model.Persoon]>(System.Data.Entity.Core.Objects.ObjectQuery`1[S20_Workflow.Domain.Model.Persoon]).MergeAs(.Constant<System.Data.Entity.Core.Objects.MergeOption>(AppendOnly))
,
.Call .Constant<System.Data.Entity.Core.Objects.ObjectQuery`1[S20_Workflow.Domain.Model.Verhuringen]>(System.Data.Entity.Core.Objects.ObjectQuery`1[S20_Workflow.Domain.Model.Verhuringen]).MergeAs(.Constant<System.Data.Entity.Core.Objects.MergeOption>(AppendOnly))
,
'(.Lambda #Lambda1<System.Func`2[S20_Workflow.Domain.Model.Persoon,System.Int32]>),
'(.Lambda #Lambda2<System.Func`2[S20_Workflow.Domain.Model.Verhuringen,System.Int32]>),
'(.Lambda #Lambda3<System.Func`3[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen,<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen]]>))
,
.Call .Constant<System.Data.Entity.Core.Objects.ObjectQuery`1[S20_Workflow.Domain.Model.Eenheid]>(System.Data.Entity.Core.Objects.ObjectQuery`1[S20_Workflow.Domain.Model.Eenheid]).MergeAs(.Constant<System.Data.Entity.Core.Objects.MergeOption>(AppendOnly))
,
'(.Lambda #Lambda4<System.Func`2[<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen],System.Int32]>),
'(.Lambda #Lambda5<System.Func`2[S20_Workflow.Domain.Model.Eenheid,System.Int32]>),
'(.Lambda #Lambda6<System.Func`3[<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen],S20_Workflow.Domain.Model.Eenheid,S2020.Personen.ViewModels.PersoonDTO]>))
,
'(.Lambda #Lambda7<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>)),
'(.Lambda #Lambda8<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>)),
'(.Lambda #Lambda9<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>)),
'(.Lambda #Lambda10<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>)),
'(.Lambda #Lambda11<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>)),
'(.Lambda #Lambda12<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>)),
'(.Lambda #Lambda13<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>))

.Lambda #Lambda1<System.Func`2[S20_Workflow.Domain.Model.Persoon,System.Int32]>(S20_Workflow.Domain.Model.Persoon $persoon)
{
$persoon.ComputerNr
}

.Lambda #Lambda2<System.Func`2[S20_Workflow.Domain.Model.Verhuringen,System.Int32]>(S20_Workflow.Domain.Model.Verhuringen $verhuring)
{
$verhuring.PersoonsID
}

.Lambda #Lambda3<System.Func`3[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen,<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen]]>(
S20_Workflow.Domain.Model.Persoon $persoon,
S20_Workflow.Domain.Model.Verhuringen $verhuring) {
.New <>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen](
$persoon,
$verhuring)
}

.Lambda #Lambda4<System.Func`2[<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen],System.Int32]>(<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen] $t)
{
($t.verhuring).Eenheid
}

.Lambda #Lambda5<System.Func`2[S20_Workflow.Domain.Model.Eenheid,System.Int32]>(S20_Workflow.Domain.Model.Eenheid $eenheid)
{
$eenheid.ComputerNr
}

.Lambda #Lambda6<System.Func`3[<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen],S20_Workflow.Domain.Model.Eenheid,S2020.Personen.ViewModels.PersoonDTO]>(
<>f__AnonymousType0`2[S20_Workflow.Domain.Model.Persoon,S20_Workflow.Domain.Model.Verhuringen] $t,
S20_Workflow.Domain.Model.Eenheid $eenheid) {
.New S2020.Personen.ViewModels.PersoonDTO(){
ComputerNr = ($t.persoon).ComputerNr,
FAMILIENAAM = ($t.persoon).FAMILIENAAM,
VOORNAAM = ($t.persoon).VOORNAAM,
NAAM = ($t.persoon).NAAM,
ADRES = ($t.persoon).ADRES,
Een = $eenheid
}
}

.Lambda #Lambda7<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
$p.FAMILIENAAM
}

.Lambda #Lambda8<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
($p.Een).GEMEENTECODE
}

.Lambda #Lambda9<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
($p.Een).WIJKCODE
}

.Lambda #Lambda10<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
($p.Een).GROEPCODE
}

.Lambda #Lambda11<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
($p.Een).STRAATCODE
}

.Lambda #Lambda12<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
($p.Een).GEBOUWCODE
}

.Lambda #Lambda13<System.Func`2[S2020.Personen.ViewModels.PersoonDTO,System.String]>(S2020.Personen.ViewModels.PersoonDTO $p)
{
($p.Een).HUISNR
}


I don't really get why this happens, because clearly $p is passed as a parameter, no?

The code where "p" is added looks like this:

private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
{
var parts = propertyName.Split('.');
var param = Expression.Parameter(typeof(T), "p");

Expression parent = parts.Aggregate<string, Expression>(param, Expression.Property);
Expression conversion = Expression.Convert(parent, typeof(object));
var uexpr = (UnaryExpression)conversion;
var pexpr = (MemberExpression)uexpr.Operand;
var customAttributes = pexpr.Member.GetCustomAttributes(typeof(SortComboHelper), true);
var sort = customAttributes[0] as SortComboHelper;
var child = ((MemberExpression)parent).Expression;

var call = sort.ConvertToLambda<T>(source, child as MemberExpression, descending, anotherLevel);

return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(call);
}


I also use $p in the section below, but I don't think the error is because of this p, because if I change this one to a different letter the error is still the same

public Expression ConvertToLambda<T>(IQueryable<T> source, MemberExpression parent, bool descending, bool anotherLevel)
{
var call = source.Expression;
foreach (var s in _param)
{
var property = Expression.Property(parent, s);
var param = Expression.Parameter(typeof(T), "p");
var mySortExpression = Expression.Lambda(property, param);

call = Expression.Call(
typeof(Queryable),
(!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
new[] { typeof(T), property.Type },
call,
Expression.Quote(mySortExpression));
}
return call;
}

Answer Source

The MemberExpression parent you are passing to your ConvertToLambda method is bound to a different parameter

var param = Expression.Parameter(typeof(T), "p");

from the OrderingHelper method. But when you create a lambda expression inside, you use a different parameter (although the name and the type of the parameters are the same, they are still different instances), hence the original parameter is not bound to that lambda and you get the exception in question.

You should pass the original parameter to the ConvertToLambda from outside and use it inside:

public Expression ConvertToLambda<T>(IQueryable<T> source, ParameterExpression param, MemberExpression parent, bool descending, bool anotherLevel)
{
    var call = source.Expression;
    foreach (var s in _param)
    {
        var property = Expression.Property(parent, s);
        var mySortExpression = Expression.Lambda(property, param);

        call = Expression.Call(
            typeof(Queryable),
            (!anotherLevel ? "OrderBy" : "ThenBy") + (descending ? "Descending" : string.Empty),
            new[] { typeof(T), property.Type },
            call,
            Expression.Quote(mySortExpression));
    }
    return call;
}

private static IOrderedQueryable<T> OrderingHelper<T>(IQueryable<T> source, string propertyName, bool descending, bool anotherLevel)
{
    // ...
    var call = sort.ConvertToLambda<T>(source, param, child as MemberExpression, descending, anotherLevel);
    // ...
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download