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的步骤来实现。
- 使方法
IsMatch
静态。 - 直接从
IsMatch
返回Expression<{your entity here}, bool>
。 - 通过它就像:
({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));