实体Linq不能识别方法

本文关键字:方法 识别 不能 Linq 实体 | 更新日期: 2023-09-27 17:53:54

我有这些方法:

   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不能识别方法

使用链接到实体时,不能在查询中使用任意的。net方法。查询中使用的每个方法都必须可翻译为SQL。它不会帮助您返回Expession<Func<entityType, bool>>,因为必须对数据库服务器上的每条记录评估where条件。

对于EF,你的代码意味着:

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

因为EF验证传递给查询的函数名,它将抛出异常,因为它不知道SQL服务器上的IsMatch等价。

可以在链接到实体中使用的唯一可能的函数是:

  • 具有预定义映射到SQL等效函数的标准函数
  • EdmFunctions

EdmFunctions是用EdmFunctionAttribute标记的方法,它将。net函数映射到SQL对应的函数。这些函数通常不能在普通的。net代码中执行,因为它们什么都不做或抛出异常。它们只是链接到实体的函数占位符。可用的EdmFunctions有:

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

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

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

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

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

实际上,您传递给count的内容看起来像这个函数:

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

但是,这需要EF知道,在这个实体上调用的IsMatch方法到底是什么意思。

我现在唯一能想到的建议是使用某种动态表达式锻造来动态地创建这个查询。

实际上,有一种更简单、更普通的方法,只需几步就能完成。

    设置IsMatch方法为static。
  1. 直接从IsMatch返回Expression<{your entity here}, bool>
  2. 像这样传递:({your entity here}.IsMatch({parameters}))

其余的可以和现在一样。

<<p> 编辑:例子/strong>这将与特定的实体工作,所以我将假设您的实体是Order。替换你自己的实体
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));