【问题标题】:How to call a method in lambda expression to run in Entity Framework?如何调用 lambda 表达式中的方法在实体框架中运行?
【发布时间】:2014-02-22 11:59:22
【问题描述】:

我有一个查询并将其交给Entity Framework 运行:

using (var context = new MyEFContext())
{
    var result = context.Items.Select(item => new {Type = item.GetType()}).ToList();
}

但是我遇到了调用像GetType()这样的系统方法的异常:(

LINQ to Entities does not recognize the method 'System.Type GetType()' method,
and this method cannot be translated into a store expression.

我尝试动态创建 lambda 表达式,但运行动态表达式有同样的问题。 如何给Entity Frameworkenter一个lambda表达式形式的方法?

【问题讨论】:

  • 报错说GetType不能转换成SQL语句,所以根本不能这样做。您可以直接转换为IEnumerable<Item> 并调用Enumerable.Select
  • 谢谢@Lee。我想从实体框架中获取实体列表。但并非所有实体字段,假设我只想要实体的“Id”。所以我必须创建一个查询,将必填字段作为新的动态类型(匿名类型)。现在我需要知道主要实体的类型,所以我尝试使用 GetType 方法将实体类型获取到表达式主体中。不幸的是,它不起作用。如何做到这一点?
  • 也许问题应该是:为什么需要类型?显然,您有一个要按基本类型查询的继承树。 A 假设在查询之后,您会根据类型分支到不同的行为。或许你可以转一下:先分支,然后分别获取每个分支需要的子类型。

标签: entity-framework lambda expression


【解决方案1】:

你只需要在 Select() 之前调用 ToList()

using (var context = new MyEFContext())
{
    var result = context.Items.ToList().Select(item => new {Type = item.GetType()}).ToList();
}

这将首先由实体框架执行 context.Items.ToList() 部分,然后 Select 在 EF 外部的本地列表中工作

如果你只想要一个字段

var result = (from item in  context.Items
select new 
{ 
field = item.yourfield
}).ToList().Select(p=> new {Type = p.field.GetType()}).ToList();

【讨论】:

  • 谢谢@Tinu。但是你的方式很重,性能很差。假设我想要我的繁重相关表中的一个且只有一个字段,您的方式将所有相关表的所有字段带入客户端,然后选择该必填字段。
  • 编辑了答案,您可以指定获取要获取的列名,该列名将仅获取一个字段,然后执行获取类型
  • 这种方式也很重。如果在.Select() 之前调用.ToList() 方法,这意味着所有实体都将被推送到客户端应用程序,这不是一个好主意。
  • 如果你只想要一个然后将其更改为 FirstorDefault() 或放置一个 where 子句来限制记录
  • "One" 列就是一个例子。可以选择 1,2,3,... 甚至所有列。
【解决方案2】:

您需要调用AsEnumerable(),以便使用 Linq-To-Objects 而不是 Linq-To-Entities 评估 GetType。 SQL中没有GetType的概念,需要在CLR中求值:

 using (var context = new MyEFContext())
 {
      var result = context.Items.AsEnumerable().Select(item => new {Type = item.GetType()}).ToList();
 }

不确定这有多大用处,因为您最终会获得Item 类型的列表...

【讨论】:

  • 谢谢@Chris Hardie。但是,如果 Link To SQL 执行并产生结果,那么每个项目的类型将是匿名的,因为选择了一些字段作为新的动态类型:item => new {Type = item.GetType()}
【解决方案3】:

使用下面的代码:

using (var context = new MyEFContext())
 {
      var result = context.Items.AsEnumerable().ToList().Select(item => new {Type = item.GetType()}).ToList();
 }

item.GetType()函数是代码函数,必须在客户端运行。在您的代码中,GetType 函数想要在服务器上运行。当您使用ToList()时,所有推送到客户端的项目,您都可以在其上运行GetType()函数。

EDIT1

您可以创建GetType 扩展存储过程并使用以下代码:

using (var context = new MyEFContext())
 {
      var result = context.Items.AsEnumerable().Select(item => new {Type = GetType(Item)}).ToList();
 }

为了在 Linq 中调用函数,请使用以下链接:Calling Functions in LINQ

【讨论】:

  • 谢谢@Mehdi Lotfi。恳请您阅读我在上述帖子(Chris Harie 的帖子)中的评论。
猜你喜欢
  • 1970-01-01
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多