2

我有一个泛型类型类过滤器,它需要一些 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<Func<T,string>>在过滤器中使用。

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

4

1 回答 1

0

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

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

它编译得很好,但在运行时会出现相同的错误,因为您正在调用已编译的函数。该部分“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 到字符串

于 2012-07-24T03:53:05.677 回答