我有一个泛型类型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.
我尝试过使用强类型而不是匿名类型,并在Filter中使用Expression<Func<T,string>>
。
经过几个小时的搜索和尝试不同的事情,我不知道如何使这项工作。 谢谢你的帮助。
答案 0 :(得分:0)
你的问题可以更简单地表达出来,例如,这再现了它:
Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.Select(c => x(c)).ToArray();
它编译得很好,但在运行时会出现相同的错误,因为您正在调用编译的函数。那部分“t =&gt; 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