2011-05-01 112 views
10

我有那些方法:LINQ到实体无法识别方法

public int count(
     Guid companyId, Expression<Func<T, bool>> isMatch) 
    { 
     var filters = new Expression<Func<T, bool>>[]{ 
      x => x.PriceDefinition.CompanyId == companyId, 
      isMatch 
     }; 

     return GetCount(filters); 
    } 

public virtual int GetCount(
      IEnumerable<Expression<Func<T, bool>>> filters) 
     { 
      IQueryable<T> _query = ObjectSet; 

      if (filters != null) 
      { 
       foreach (var filter in filters) 
       { 
        _query = _query.Where(filter); 
       } 
      } 

      return _query.Count(); 
     } 

使用:

count(some_guid, x => x.IsMatch(entityId, inviterId, routeId, luggageTypeId)); 

我得到以下异常:

LINQ to Entities does not recognize the method 'Boolean IsMatch(System.Nullable`1[System.Int64], System.Nullable`1[System.Int64], System.Nullable`1[System.Int64], System.Nullable`1[System.Int64])' method, and this method cannot be translated into a store expression. 

什么这是为什么?
我该如何解决?

+0

你的过滤器是什么? – SLaks 2011-05-01 02:27:14

+0

@ SLaks♦:对不起,我用isMatch委托更新了问题。 – Naor 2011-05-01 02:29:07

回答

14

当使用LINQ到实体不能使用查询任意.NET方法。查询中使用的每种方法都必须可转换为SQL。它不会帮助您返回Expession<Func<entityType, bool>>,因为必须针对数据库服务器上的每条记录评估条件。

对于EF代码是指这样的:

SELECT COUNT(*) 
FROM ... 
LEFT JOIN ... 
WHERE IsMatch(....) 

由于EF验证传递给查询会抛出异常,因为它不知道IsMatch相当于SQL服务器上的功能名称。

,其可以用在LINQ到实体的唯一可能的功能是:

EdmFunctions都方法标有EdmFunctionAttribute其将.NET函数映射到SQL对应项。这些函数通常不能用通用的.NET代码执行,因为它们什么都不做或抛出异常。他们只是Linq-to-entities的功能占位符。可用EdmFunctions是:

  • 预定义EdmFunctions在System.Data.Objects.EntityFunctions
  • 预定义EdmFunctions在System.Data.Objects.SqlClient.SqlFunctions
  • SQL服务器(不紧凑)自定义映射SQL函数 - 在实体设计导入向导,可以导入SQL函数(除表值功能)。您可以在此之后编写自定义静态.NET函数,并将其按EdmFunction属性映射到导入到设计器的SQL函数。
  • 自定义模型定义函数 - 这是在EDMX文件中手动编写的特殊函数(以XML打开)。它是Entity SQL的自定义可重用部分。

我已经在另一个答案中描述了how to create model defined function。创建映射SQL function is pretty similar。而不是在EDMX中手动创建Function元素,而是将EdmFunctionAttribute属性映射到导入的SQL函数。

2

您正在传递一个调用名为IsMatch的函数的表达式。

LINQ to Entities不知道如何处理此功能。

+0

♦:我更新了问题.. – Naor 2011-05-01 02:29:44

+0

LINQ to Entities不知道如何将IsMatch转换为SQL。您需要用表达式树替换它。 – SLaks 2011-05-01 02:31:19

+3

♦:“用表达式树替换它”是什么意思? – Naor 2011-05-01 02:34:18

1

我正在处理类似的问题。在尝试使用我的自定义方法之前,工作解决方案使用了.AsEnumerable()。您可以take a look at it here

+0

添加AsEnumerable会将整个表加载到内存中,在companyId的过滤器之后,我仍然有很多结果。 – Naor 2011-05-01 02:42:33

+0

@Naor:好吧,它对我有用,因为我工作的结果很少。不知道你的。 – Damb 2011-05-01 02:53:15

0

Actualy,要传递什么指望像这样的功能:

bool anonymous_delagate#123(T entity) 
{ 
    return entity.IsMatch(a,b,c,d) 
} 

但是,这需要EF知道,真正的方法IsMatch,被称为本实体,意味着。

我现在所能想到的只是使用某种动态表达式锻造来创建查询动态。或者将您的设计修改为与其他不同的设计。

实际上,有一种更容易和普通的方法,需要很少的步骤来实现。

  1. 制作方法IsMatch静态。
  2. 返回Expression<{your entity here}, bool>直接从IsMatch
  3. 通过它喜欢:({your entity here}.IsMatch({parameters}))

休息能保持一样的,你现在有。

编辑:例 这将与特定实体的工作,所以我会asume你的实体是订单。替换你自己的实体。

public static Expression<Func<Order, bool>> IsMatch(int id, ...) // static method, that returns filtering expression 
{ 
    return i => i.Id == id; // create the filtering criteria 
} 

然后调用它像:

count(some_guid, Order.IsMatch(entityId, inviterId, routeId, luggageTypeId)); 
+0

你能举个例子吗?我没有理解你最后的两个步骤。 – Naor 2011-05-01 12:54:11

+0

您写的静态IsMatch方法是否必须返回不基于其他函数的委托?我可以使用例如“return i => i.MyMethod(id);”? – Naor 2011-05-02 03:03:49

+0

不可以。您必须使用eiter完整地创建它作为表达式或Ladislav所说的,将您的函数映射到存储过程。 – Euphoric 2011-05-02 06:23:09

相关问题