【问题标题】:Select values in anonymous type with func in linq select statement在linq select语句中使用func选择匿名类型的值
【发布时间】:2012-08-31 09:13:47
【问题描述】:

我有一个泛型类型类 Filter,它采用一些 lambda 表达式从类型中选择值,以便该类可重用。该类在另一个泛型类型类 Search 中使用,它将使用 Filter 选择最终将在下拉列表中使用的类型的不同项目。

我删除了这些不重要的代码。

public class Filter<T>
{
   public string Name;
   public Func<T, string> Key;
   public Func<T, string> Value;
}

public class Search<T>
{
   MyDBContext db = new MyDBContext();
   IQueryable<T> Model = db.Stuff.OrderBy(a => a.TermID);
   Filter filter = new Filter(
      Name: "Term",
      Value: a => a.TermID.ToString(),
      Key: a => a.Term.TermType.Name
   );

   var filterItems = Model
      .Select(a => new { Key = filter.Key(a), Value = filter.Value(a)})
      .OrderBy(t => t.Key)
      .Distinct()
      .ToArray();
}

我收到运行时错误:The LINQ expression node type 'Invoke' is not supported in LINQ to Entities. 我尝试使用强类型而不是匿名类型,并在过滤器中使用Expression&lt;Func&lt;T,string&gt;&gt;

经过数小时的搜索和尝试不同的事情,我不确定如何完成这项工作。 感谢您的帮助。

【问题讨论】:

  • 我怀疑 filter.Keyfilter.Value 所做的任何事情都可以从 LINQ 转换到您的后端存储。
  • 如果 Invoke 是主要问题,可以通过使用 ExpressionVisitor 融合两个表达式来避免。我不在电脑前,但如果你没有得到任何快乐,请提醒我,我会添加一个示例。

标签: c# linq entity-framework


【解决方案1】:

您的问题可以更简单地表达,例如,它重现了它:

Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.Select(c => x(c)).ToArray();

它编译得很好,但在运行时会出现同样的错误,因为您正在调用 compiled 函数。那部分“t => t.ID”是编译代码(至少对 IL),linq 无法读取它以将其转换为 SQL。它只能将表达式树转换为 SQL。上述情况的解决方案相当简单,我不确定这将如何转化为您的情况,但应该是可能的。

Expression<Func<SomeClass, int>> x = t => t.ID;
var y = db.SomeClasses.Select(x).ToArray();

还有将函数调用移动到 linq 到对象的选项,这样就不需要将其转换为 sql(在客户端处理“AsEnumerable”之后的所有内容)。这使得可以在函数中放置的内容具有更大的灵活性,并将消除您遇到的错误类型。这也将消除调用 SqlFunctions 的需要(见下文)。缺点是服务器返回的行数可能比需要的多。

Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.AsEnumerable().Select(c => x(c)).ToArray();

您的最后一个问题是 EF 不喜欢 ToString 方法,您需要使用相当糟糕的 SqlFunctions.StringConvert。见这里:int to string in Entity Framework

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多