linq toEntity 无法识别方法
我有这些方法:
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.
这是什么原因?
我该如何解决?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用 linq-to-entities 时,您不能在查询中使用任意 .NET 方法。查询中使用的每种方法都必须可转换为 SQL。它不会帮助您返回
Expession>
因为必须为数据库服务器上的每条记录评估 where 条件。对于 EF,您的代码意味着类似以下内容:
因为 EF 验证传递给查询的函数名称,所以它会抛出异常,因为它不知道 SQL Server 上的 IsMatch 等效项。
可以在 Linq-to-entities 中使用的唯一可能的函数是:
EdmFunctions
EdmFunctions 是用映射 .NET 函数的
EdmFunctionAttribute
标记的方法到 SQL 对应项。这些函数通常无法在通用 .NET 代码中执行,因为它们不执行任何操作或引发异常。它们只是 Linq-to-entities 的函数占位符。可用的 EdmFunctions 有:System.Data.Objects.EntityFunctions
中预定义的 EdmFunctionSystem.Data.Objects.SqlClient.SqlFunctions
中为 SQL Server 预定义的 EdmFunctions(非紧凑型)EdmFunction
属性将其映射到导入到设计器的 SQL 函数。我已经描述了如何创建模型定义的函数 在另一个答案中。创建映射的 SQL 函数非常相似。您无需在 EDMX 中手动创建
Function
元素,而是将EdmFunctionAttribute
属性映射到导入的 SQL 函数。When using linq-to-entities you cannot use arbitrary .NET methods in query. Each method used in the query must be translatable to SQL. It will not help you to return
Expession<Func<entityType, bool>>
because where condition must be evaluated for each record on the database server.For EF your code means something like:
Because EF validates function names passed to the query it will throw exception because it doesn't know IsMatch equivalent on SQL server.
The only possible functions which can be used in Linq-to-entities are:
EdmFunctions
EdmFunctions are methods marked with
EdmFunctionAttribute
which maps .NET function to SQL counterpart. Those functions usually cannot be executed in common .NET code because they do nothing or throw exception. They are only function place holder for Linq-to-entities. Available EdmFunctions are:System.Data.Objects.EntityFunctions
System.Data.Objects.SqlClient.SqlFunctions
EdmFunction
attribute to the SQL function imported to designer.I have already described how to create model defined function in another answer. Creating mapped SQL function is pretty similar. Instead of manually creating
Function
element in EDMX you will mapEdmFunctionAttribute
properties to imported SQL function.您正在传递一个调用名为
IsMatch
的函数的表达式。LINQ to Entities 不知道如何使用此函数。
You're passing an expression that calls a function named
IsMatch
.LINQ to Entities doesn't know what to do with this function.
我正在处理类似的问题。工作解决方案是在尝试使用我的自定义方法之前使用
.AsEnumerable()
。您可以 在这里看看。I was dealing with similar problem. Working solution was using
.AsEnumerable()
before trying to use my custom method. You can take a look at it here.实际上,您传递给 count 的内容看起来像这个函数:
但是,这需要 EF 知道在此实体上调用的真正方法
IsMatch
的含义。我现在唯一能想到的推荐就是使用某种动态表达式伪造来动态创建此查询。或者将您的设计重新设计为不同的东西。实际上,有一种更简单且正常的方法,只需几个步骤即可完成。
IsMatch
静态。IsMatch
返回Expression<{您的实体}, bool>
。({这里是您的实体}.IsMatch({parameters}))
其余的可以保持与现在相同。
编辑:示例
这适用于特定实体,因此我假设您的实体是订单。替换您自己的实体。
然后这样称呼它:
Actualy, what you are passing to count look like this function:
But, this would require EF to know, what really method
IsMatch
, that is called on this entity, means.Only thing I can think about recomending now is to use some kind of dynamic expression-forging to create this query dynamicaly. Or rework your design to somethign different.Actualy, there is easier and normal method, that requires few steps to acomplish.
IsMatch
static.Expression<{your entity here}, bool>
directly fromIsMatch
.({your entity here}.IsMatch({parameters}))
Rest can remain same as you have now.
Edit: Example
This will work with specific entity, so I will asume your entity is Order. Substitute your own entity.
Then call it like: