【问题标题】:Lambda expression creates multiple queriesLambda 表达式创建多个查询
【发布时间】:2014-07-07 12:58:38
【问题描述】:

我有一个奇怪的 system.function LINQ 问题。如果我的 Lambda 表达式包含两次数据上下文,它将生成多个 SQL 查询,而不是(参见第二个)一个 SQL 查询。

第一

Dim whereFunction As Func(Of tasks, Boolean) = Function(task) New With {.condition =
                                                      (From i In myDataContext.taskInfo Where i.taskId = task.id).Any()
                                                 }.condition
Dim tasksLambda = myDataContext.tasks.Where(whereFunction)
Dim taskList = tasksLambda.ToList 
'generates for each task one select to taskinfo on SQL Server Profiler -> bad

第二

Dim tasksNoLambda = (From task In myDataContext.tasks Where (From i In myDataContext.taskInfo Where i.taskId = task.id).Any())
taskList  = tasksNoLambda .ToList 
'generates only one select to tasks with subselect to taskinfo on SQL Server Profiler -> good

您能否解释一下为什么它会进行多个查询而不是子查询和/或这两个 Lambda 查询之间有什么区别。

提前致谢,

丹尼尔

【问题讨论】:

  • 您正在进出IQueryable。任何时候查询越界,它都必须进行单独的查询。
  • 以及如何防止这些多个查询@Enigmativity?我真的需要这个功能。

标签: vb.net linq lambda


【解决方案1】:
  • myDataContext.tasks指数据源提供的集合

  • .Where(whereFunction) 是一个必须在客户端计算的表达式,因为whereFunction 通常不能转换为 SQL 表达式(它正在构造新的匿名对象,我相信没有 SQL 转换) .

  • 函数内的myDataContext.taskInfo再次引用数据源。

因此,在对最高级别表达式的求值、从数据源检索数据、在客户端的函数中对其进行处理时,需要进行大量的来回通信,而客户端又必须从其中检索更多数据数据源。

你能在没有匿名对象的情况下尝试同样的事情吗?你能试试这个吗?

Dim whereFunction As Func(Of tasks, Boolean) = _
    Function(task) (From i In myDataContext.taskInfo Where i.taskId = task.id).Any())

知道了。第二次尝试——试试这个:

Dim whereFunction As System.Linq.Expressions.Expression(Of Func(Of tasks, Boolean)) = _
    Function(task) (From i In myDataContext.taskInfo Where i.taskId = task.id).Any())

通过将变量表示为 LINQ“表达式”,我认为它提高了 LINQ 将其转换为其他形式(如 SQL)的能力。

【讨论】:

  • 感谢您的快速回复@BlueMonkMN,但不幸的是它没有任何区别。还是有这个问题。
  • @daniel.didusch 这次我想我明白了。
  • @BlueMonkMN 到底是什么意思?我无法用你的回答解决这个问题。
  • @daniel.didusch 你看到我的第二个答案了吗?当我使用这种方法时,它确实改变了我测试中的行为。不是给你的吗?
  • 非常感谢@BlueMonkMN,我真的很感激!我将您的答案标记为正确。
【解决方案2】:

尝试这样做:

Dim tasksLambda  = _
    From task In myDataContext.tasks
    Group Join i In myDataContext.taskInfo On task.id Equals i.taskId Into Group
    Where Group.Any()
    Select task

这将是您可以做的最好的一个查询。

如果这不起作用,那么您可以将taskstaskInfo 记录拉入内存并在那里进行过滤。只要您没有太多记录,这通常会更快。

【讨论】:

  • 抱歉@Enigmativity,这不是我的目标,因为我需要一个返回的 Where 函数。
  • @daniel.didusch - 如果你想返回一个 where 子句 并且 只在查询时进行,那么你需要返回一个 Expression(Of Func(Of tasks, Boolean)),而不仅仅是一个 Func(Of tasks, Boolean)
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多