【问题标题】:Filtering IQueryable using self defined function causes runtime error使用自定义函数过滤 IQueryable 会导致运行时错误
【发布时间】:2014-07-01 07:52:36
【问题描述】:

我有一个与LINQ: How to remove element from IQueryable<T> 类似的查询,并且大部分都回答了我的问题。

我的代码设置类似:

var items = MyDataContext.Items.Where(x =>MyFunction(x.value1, x.value2, x.value3));
...
...
bool MyFunction(decimal val1, decimal val2, decimal val3)
{
 //some calculation with the parameters
 return true;
}

它编译得很好,但是当我运行它时,它会抛出一个错误:

“'System.NotSupportedException' 类型的异常发生在 System.Data.Entity.dll 但未在用户代码中处理

附加信息:LINQ to Entities 无法识别该方法 '布尔 MyFunction(System.Decimal,System.Decimal,System.Decimal)' 方法,并且该方法不能翻译成商店表达式。”

我是 linq 的新手,这周才开始,所以感谢任何帮助。谢谢!

【问题讨论】:

  • 您是否使用此调用查询数据库?
  • 在查询数据库时不能编写相同类型的 Linq 查询。要么运行MyDataContext.Items.ToList().Where(..),首先从数据库中获取所有Items,然后运行where() 性能不佳。否则重写您的Where 查询以支持Linq To Sql
  • 是的,我正在查询数据库
  • @RobertFricke,嗨,我不太了解第一个选项。你的意思是获取所有项目,然后运行另一个 where() 查询?
  • 和@Serv的回答一样

标签: c# linq iqueryable


【解决方案1】:

您的 linq 查询被翻译成SQL。在这种情况下,Linq to Entities 不知道如何正确地将您的方法转换为SQL。所以你不能在 linq to sql 查询上使用自定义方法。你只能使用supported methods

如果你想这样做,你必须从数据库中获取所有数据并在内存中进行。

【讨论】:

  • 我也很怀疑,但后来我看到stackoverflow.com/questions/2937528/… 也使用了自定义函数,所以我认为它会起作用。
  • @mikevil14rin 在那个问题中,第二个查询items.Where(itm =&gt; IsWhatINeed(itm)); 应该在内存而不是sql server 上执行。
  • 您好,您能详细说明一下吗?在内存而不是 sql server 上执行是什么意思?
  • @mikevil14rin 我的意思是,首先从 sql server 获取过滤后的数据,然后再次在内存中过滤,但使用 linq to objects 而不是 linq to sql。所以itm =&gt; IsWhatINeed(itm)不会被翻译成sql。
  • 通过 linq to objects 你的意思是声明一个变量 var item,然后从 items.where() 分配结果?
【解决方案2】:

如果你想完美运行这段代码,你应该像这样使用 IEnumurable:

var items = MyDataContext.Items.toList().Where(x =>MyFunction(x.value1, x.value2, x.value3));

【讨论】:

    【解决方案3】:

    尝试在 where 子句前添加 .ToList()

    我猜你正在查询某种数据库,但数据提供者无法翻译你的方法Myfunction

    在触发 where 子句之前将数据存入内存:

    var items = MyDataContext.Items.ToList().Where(x =>MyFunction(x.value1, x.value2, x.value3)
    

    根据我的理解,需要一些额外的解释。在您真正需要之前,不会执行您的查询。 通过调用.ToList(),您可以具体化您的数据,之后的每个操作都在您的机器上的内存中执行,而不是在数据库上执行。这意味着您可以很好地将其拆分为 2 个调用:

    //First call. Executed as SQL query on database. Materializes data into IEnumerable<Item>
    var items = MyDataContext.Items.ToList();
    
    //second call on client
    var filteredItems = Items.Where(x => x.Id == MyFunction(value1, value2));
    

    如果省略 ToList() 调用,Entity Framework 会尝试将 Myfunction() 转换为 SQL,但它不能,然后抛出错误。

    【讨论】:

    • 您好,感谢您的回复。这解决了错误消息问题,但我的项目没有被过滤,我检查了过滤前后的总数,结果是一样的。我检查了 MyFunction 并且它对某些记录返回“false”,所以过滤后的总数应该更少,如果我的理解是正确的。
    • 太棒了,但我当然无法帮助您进行过滤,因为这不是问题/问题的一部分,而且您没有提供任何代码。随意提出另一个问题来解决您的过滤问题
    猜你喜欢
    • 2019-05-31
    • 1970-01-01
    • 2016-08-05
    • 2023-03-16
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2022-01-08
    相关资源
    最近更新 更多