Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在linq Select语句中使用func选择匿名类型中的值_C#_Linq_Entity Framework - Fatal编程技术网

C# 在linq Select语句中使用func选择匿名类型中的值

C# 在linq Select语句中使用func选择匿名类型中的值,c#,linq,entity-framework,C#,Linq,Entity Framework,我有一个泛型类型类过滤器,它使用一些lambda表达式从类型中选择值,以便该类是可重用的。该类在另一个泛型类型类搜索中使用,该类将使用筛选器选择最终将在下拉列表中使用的类型的不同项 我删除了这些不重要的代码 public class Filter<T> { public string Name; public Func<T, string> Key; public Func<T, string> Value; } public class

我有一个泛型类型类过滤器,它使用一些lambda表达式从类型中选择值,以便该类是可重用的。该类在另一个泛型类型类搜索中使用,该类将使用筛选器选择最终将在下拉列表中使用的类型的不同项

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

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();
}
公共类过滤器
{
公共字符串名称;
公钥;
公共职能价值;
}
公共类搜索
{
MyDBContext db=新的MyDBContext();
IQueryable Model=db.Stuff.OrderBy(a=>a.TermID);
过滤器=新过滤器(
名称:“期限”,
值:a=>a.TermID.ToString(),
Key:a=>a.Term.TermType.Name
);
var filterItems=模型
.Select(a=>new{Key=filter.Key(a),Value=filter.Value(a)})
.OrderBy(t=>t.Key)
.Distinct()
.ToArray();
}
我得到运行时错误:
LINQ to实体中不支持LINQ表达式节点类型“Invoke”。
我尝试过使用强类型而不是匿名类型,并在过滤器中使用
Expression

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

您的问题可以更简单地表达出来,例如,这再现了它:

Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.Select(c => x(c)).ToArray();
Func x=t=>t.ID;
vary=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();
表达式x=t=>t.ID; var y=db.SomeClasses.Select(x.ToArray(); 还可以选择将函数调用移动到linq to对象中,这样就不需要将其转换为sql(在客户端上处理“AsEnumerable”之后的所有内容)。这允许在函数中放置更大的灵活性,并将消除您所遇到的错误类型。这也将消除调用SqlFunctions的需要(见下文)。缺点是从服务器返回的行可能比需要的多

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

最后一个问题是EF不喜欢ToString方法,您需要使用SqlFunctions.StringConvert,这相当糟糕。请参见此处:

您的问题可以更简单地表达出来,例如,这再现了它:

Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.Select(c => x(c)).ToArray();
Func x=t=>t.ID;
vary=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();
表达式x=t=>t.ID; var y=db.SomeClasses.Select(x.ToArray(); 还可以选择将函数调用移动到linq to对象中,这样就不需要将其转换为sql(在客户端上处理“AsEnumerable”之后的所有内容)。这允许在函数中放置更大的灵活性,并将消除您所遇到的错误类型。这也将消除调用SqlFunctions的需要(见下文)。缺点是从服务器返回的行可能比需要的多

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

最后一个问题是EF不喜欢ToString方法,您需要使用SqlFunctions.StringConvert,这相当糟糕。请参见此处:

我怀疑任何
过滤器。Key
过滤器。Value
do都可以从LINQ转换到后端存储。如果调用是主要问题,则可以通过使用ExpressionVisitor融合这两个表达式来避免。我不在电脑前,但如果你没有得到任何乐趣,请提醒我,我将添加一个示例。我怀疑
filter.Key
filter.Value
所做的任何事情都可能从LINQ转换到后端存储。如果调用是主要问题,则可以使用ExpressionVisitor将这两个表达式进行融合来避免。我不在电脑前,但如果你没有得到任何乐趣,提醒我,我会添加一个例子。