我有实体,例如CategoryEntity,RubricEntity,CityEntity等 我需要显示这些实体的下拉列表。此实体具有不同的属性。 所有这些我需要转换为DropDownListItem以显示为下拉列表,所以我想我可以使用这样的方法来处理数据库,但我得到了异常
LINQ表达式节点类型' Invoke' LINQ to Entities不支持。
public static IQueryable<DropDownListItem> ToDropDownList<TSource>(IQueryable<TSource> query, Expression<Func<TSource, long>> value, Expression<Func<TSource, string>> text)
{
var valueLambda = value.Compile();
var textLambda = text.Compile();
return query.Select(x => new DropDownListItem
{
Value = (long) valueLambda(x),
Text = (string) textLambda(x)
});
}
我认为我可以使用类似的东西,但不知道如何使用表达式和lambda来制作它。
因此我想要像
这样的东西ToDropDownList2<RubricEntity>(_service.RubricAsQueryable(), x => x.Id, x => x.DisplayName)
答案 0 :(得分:0)
问题是Linq To Entities不支持编译表达式,并且您编译了两个表达式并尝试调用它们。但是LINQ试图将它们解析为表达式并将它们转换为SQL代码,而它却无法做到。
并且您希望将text
和value
作为不同的参数传递,因此您无法将它们组合在一起。
你可以这样做:
public static IQueryable<DropDownListItem> ToDropDownList<TSource>(IQueryable<TSource> query, Expression<Func<TSource, DropDownListItem>> value)
{
return query.Select(value);
}
ToDropDownList<RubricEntity>(_service.RubricAsQueryable(), x => new DropDownListItem() { Value = x.Id, Text = x.DisplayName });
但就我而言,它没有多大意义......
如果您仍想将它们作为单独的参数传递,那么您可以尝试在运行时将它们组合起来,如下所示:
public static IQueryable<DropDownListItem> ToDropDownList<TSource>(IQueryable<TSource> query, Expression<Func<TSource, long>> value, Expression<Func<TSource, string>> text)
{
Expression<Func<TSource, DropDownListItem>> func = x => new DropDownListItem
{
Value = 1,
Text = "1"
};
var replacer = new ExpressionReplacer<TSource>()
{
Text = text,
Value = value,
Parameter = func.Parameters[0] // we will take X parameter
};
var convertedFunc = replacer.Visit(func) as Expression<Func<TSource, DropDownListItem>>;
return query.Select(convertedFunc);
}
private class ExpressionReplacer<TSource> : ExpressionVisitor
{
public Expression<Func<TSource, long>> Value { get; set; }
public Expression<Func<TSource, string>> Text { get; set; }
public ParameterExpression Parameter { get; set; }
protected override Expression VisitConstant(ConstantExpression node)
{
if (node.Type == typeof(long))
return this.Visit(Value.Body);
if (node.Type == typeof(string))
return this.Visit(Text.Body);
return base.VisitConstant(node);
}
protected override Expression VisitParameter(ParameterExpression node)
{
// we will replace all usage to X. it has the same type, but it isn't linked to expiression
return Parameter;
}
}
ToDropDownList<RubricEntity>(_service.RubricAsQueryable(), x => x.Key, x => x.Value);
基本上我们只是使用常量值创建存根表达式,然后根据类型到参数中的表达式替换常量值。然后将替换的表达式发送给Select方法,因此最终表达式将类似于:
Select(x => new DropDownListItem() { Value = x.Id, Text = x.DisplayName })