2014-11-24 23 views
0

我有实体,例如CategoryEntity,RubricEntity,CityEntity等 我需要显示这些实体的下拉菜单。这个实体具有不同的属性。 所有这些我需要转换为DropDownListItem显示为下拉,所以我觉得我可以用这样的方法与DB工作,但我得到异常使用方法中的Lambda表达式的DropDownListItem的实体

的LINQ表达式节点类型“调用”不是在LINQ支持到实体。

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

的问题是,LINQ到实体不支持编译表情,而你编译表达和试图调用它们。但是,LINQ试图将它们解析为表达式并将它们转换为SQL代码,并且它不能这样做。 而你想通过textvalue作为不同的参数,所以你不能合并它们。

你可以这样做:

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 }); 

但对于我来说,这has't有很大的意义...

如果你仍然想通过他们作为独立的参数,那么你就可以尝试在运行时将它们结合起来是这样的:

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); 

基本上我们刚创建的常量值存根表达,然后根据不同类型随附在paremeters表达式替换常数值。然后发送替换表达式选择的方法,所以它finaly表达式将类似于:

Select(x => new DropDownListItem() { Value = x.Id, Text = x.DisplayName }) 
+0

您好我得到了这样的错误“X”未在指定的LINQ到实体绑定的参数查询表达式。感谢您的帮助。 – 2014-11-25 10:58:26

+0

关于如何解决这个问题的任何想法? – 2014-11-25 19:30:37

+0

嗨。嗯你是对的。我更新了'ExpressionReplacer'的答案,并轻微更改了'ToDropDownList'方法。我用EF本地检查它,它工作正常。 – 2014-11-25 22:36:13

相关问题