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. 

这是什么原因?
我该如何解决?

当使用linq-to-entities时,你不能在查询中使用任意的.NET方法。 查询中使用的每个方法都必须可以转换为SQL。 它不会帮助您返回Expession<Func<entityType, bool>>因为必须在数据库服务器上为每条logging计算条件。

对于EF你的代码意味着像这样:

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

由于EFvalidation传递给查询的函数名称,因此它将抛出exception,因为它不知道SQL服务器上的IsMatch等价物。

可以在Linq-to-entities中使用的唯一可能的函数是:

  • 预定义的映射到SQL等价物的Cannonical函数
  • EdmFunctions

EdmFunctions是使用EdmFunctionAttribute标记的方法,它将.NET函数映射到SQL对象。 这些函数通常不能用通用的.NET代码执行,因为它们什么都不做或抛出exception。 他们只是Linq-to-entities的职能所在地。 可用的EdmFunctions是:

  • System.Data.Objects.EntityFunctions预定义的EdmFunctions
  • System.Data.Objects.SqlClient.SqlFunctions中为SQL Server预定义的EdmFunctions(不紧凑)
  • 自定义映射的SQL函数 – 实体devise器中的导入向导允许您导入SQL函数(表值函数除外)。 您可以在此之后编写自定义的静态.NET函数,并将其通过EdmFunction属性映射到导入到devise器的SQL函数。
  • 自定义模型定义函数 – 这是在EDMX文件(以XML打开)中手动编写的特殊function。 它是Entity SQL的可定制可重用部分。

我已经介绍了如何在另一个答案中创build模型定义的函数 。 创build映射的SQL函数非常相似 。 而不是在EDMX中手动创buildFunction元素,您将把EdmFunctionAttribute属性映射到导入的SQL函数。

您正在传递一个调用名为IsMatch的函数的IsMatch

LINQ to Entities不知道如何处理这个函数。

我正在处理类似的问题。 工作解决scheme之前使用.AsEnumerable()尝试使用我的自定义方法。 你可以在这里看看 。

实际上,你正在通过计数看起来像这样的function:

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

但是,这将要求EF知道,在这个实体上调用IsMatch真正方法是什么意思。

我现在所能想到的只是使用某种dynamicexpression式锻造来创build查询dynamic。 或者重新devise你的devise。

实际上,有一种比较简单和普通的方法,这需要很less的步骤来实现。

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

rest可以保持相同,因为你现在。

编辑:例子这将使用特定的实体,所以我会asume你的实体是秩序 。 replace你自己的实体。

 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));