linq toEntity 无法识别方法

发布于 2024-11-04 00:59:56 字数 1210 浏览 0 评论 0 原文

我有这些方法:

   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.

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

I have those methods:

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

When using:

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

I get the following exception:

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.

What is the reason for this?
How can I solve it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

辞取 2024-11-11 00:59:56

使用 linq-to-entities 时,您不能在查询中使用任意 .NET 方法。查询中使用的每种方法都必须可转换为 SQL。它不会帮助您返回 Expession> 因为必须为数据库服务器上的每条记录评估 where 条件。

对于 EF,您的代码意味着类似以下内容:

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

因为 EF 验证传递给查询的函数名称,所以它会抛出异常,因为它不知道 SQL Server 上的 IsMatch 等效项。

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

EdmFunctions 是用映射 .NET 函数的 EdmFunctionAttribute 标记的方法到 SQL 对应项。这些函数通常无法在通用 .NET 代码中执行,因为它们不执行任何操作或引发异常。它们只是 Linq-to-entities 的函数占位符。可用的 EdmFunctions 有:

  • System.Data.Objects.EntityFunctions 中预定义的 EdmFunction
  • System.Data.Objects.SqlClient.SqlFunctions 中为 SQL Server 预定义的 EdmFunctions(非紧凑型)
  • 自定义映射 SQL函数 - 实体设计器中的导入向导允许您导入 SQL 函数(表值函数除外)。之后,您可以编写自定义静态 .NET 函数,并通过 EdmFunction 属性将其映射到导入到设计器的 SQL 函数。
  • 自定义模型定义的函数 - 这是在 EDMX 文件(以 XML 形式打开)中手动编写的特殊函数。它是 Entity 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:

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

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 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:

  • Predefined EdmFunctions in System.Data.Objects.EntityFunctions
  • Predefined EdmFunctions for SQL Server (not compact) in System.Data.Objects.SqlClient.SqlFunctions
  • Custom mapped SQL functions - import wizard in Entity designer allows you import SQL functions (except table valued functions). You can after that write custom static .NET function and map it by EdmFunction attribute to the SQL function imported to designer.
  • Custom model defined functions - this is special function written manually in EDMX file (opened as XML). It is custom reusable part of Entity SQL.

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 map EdmFunctionAttribute properties to imported SQL function.

寻梦旅人 2024-11-11 00:59:56

您正在传递一个调用名为 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.

一片旧的回忆 2024-11-11 00:59:56

我正在处理类似的问题。工作解决方案是在尝试使用我的自定义方法之前使用 .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.

感受沵的脚步 2024-11-11 00:59:56

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

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

但是,这需要 EF 知道在此实体上调用的真正方法 IsMatch 的含义。

我现在唯一能想到的推荐就是使用某种动态表达式伪造来动态创建此查询。或者将您的设计重新设计为不同的东西。

实际上,有一种更简单且正常的方法,只需几个步骤即可完成。

  1. 使方法 IsMatch 静态。
  2. 直接从 IsMatch 返回 Expression<{您的实体}, bool>
  3. 像这样传递它:({这里是您的实体}.IsMatch({parameters}))

其余的可以保持与现在相同。

编辑:示例
这适用于特定实体,因此我假设您的实体是订单。替换您自己的实体。

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

Actualy, what you are passing to count look like this function:

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

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.

  1. Make method IsMatch static.
  2. Return Expression<{your entity here}, bool> directly from IsMatch.
  3. Pass it like : ({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.

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

Then call it like:

count(some_guid, Order.IsMatch(entityId, inviterId, routeId, luggageTypeId));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文