适当的LINQ where子句

rjzwgtxy  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(130)

在我的日常生活中,我写了相当多的LINQ,但大多数都是简单的语句。我注意到,当使用where子句时,有很多种方法来编写它们,据我所知,每种方法都有相同的结果。例如:

from x in Collection
  where x.Age == 10
  where x.Name == "Fido"
  where x.Fat == true
  select x;

至少就结果而言,似乎与此等效:

from x in Collection
  where x.Age == 10 &&
        x.Name == "Fido" &&
        x.Fat == true
  select x;

那么除了语法之外,真的有区别吗?如果有,首选的风格是什么,为什么?

58wvjzkj

58wvjzkj1#

编辑:LINQ to Objects的表现与我所期望的不一样。您可能会对我刚刚写的blog post感兴趣...
它们的不同之处在于将什么称为--第一个相当于:

Collection.Where(x => x.Age == 10)
          .Where(x => x.Name == "Fido")
          .Where(x => x.Fat == true)

而后者相当于:

Collection.Where(x => x.Age == 10 && 
                      x.Name == "Fido" &&
                      x.Fat == true)

现在,* 实际 * 产生的差别取决于所调用的Where的实现。如果它是一个基于SQL的提供程序,我希望这两个提供程序最终会创建相同的SQL。如果它是在LINQtoObjects中,第二种方法的间接级别较少(这里只涉及两个迭代器,而不是四个)。这些间接层在速度方面是否 * 重要 * 是另一回事。
通常,如果感觉它们代表的条件明显不同,我会使用几个where子句(例如一个是关于对象的一部分,一个是完全独立的)和一个where子句(例如,某个特定值大于最小值且小于最大值)。基本上,在出现任何轻微的性能差异之前,都值得考虑可读性。

ffdz8vbo

ffdz8vbo2#

第二种方法效率更高,因为它只有一个 predicate 来对集合中的每个项进行求值,与第一种方法一样,它首先将第一个 predicate 应用于所有项,然后将结果(此时已缩小)用于第二个 predicate ,依此类推。结果在每一遍都被缩小,但仍涉及多遍。
另外,链接(第一个方法)只有在你对 predicate 进行AND运算时才起作用。像x.Age == 10 || x.Fat == true这样的东西在你的第一个方法中不起作用。

50few1ms

50few1ms3#

第一个将被实施:

Collection.Where(x => x.Age == 10)
          .Where(x => x.Name == "Fido") // applied to the result of the previous
          .Where(x => x.Fat == true)    // applied to the result of the previous

与简单得多(也快得多--可能更快)的方法相反:

// all in one fell swoop
Collection.Where(x => x.Age == 10 && x.Name == "Fido" && x.Fat == true)
nmpmafwu

nmpmafwu4#

当我跑步时

from c in Customers
where c.CustomerID == 1
where c.CustomerID == 2
where c.CustomerID == 3
select c

from c in Customers
where c.CustomerID == 1 &&
c.CustomerID == 2 &&
c.CustomerID == 3
select c customer table in linqpad

针对我的Customer表,它输出相同的sql查询

-- Region Parameters
DECLARE @p0 Int = 1
DECLARE @p1 Int = 2
DECLARE @p2 Int = 3
-- EndRegion
SELECT [t0].[CustomerID], [t0].[CustomerName]
FROM [Customers] AS [t0]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = @p1) AND ([t0].[CustomerID] = @p2)

因此在转换为sql时没有区别,而且您已经在其他答案中看到了如何将它们转换为lambda表达式

nom7f22z

nom7f22z5#

深入研究一下,这两个语句将被转换成不同的查询表示形式,这取决于CollectionQueryProvider,可能会被优化掉,也可能不会。
当这是一个链接到对象的调用时,多个where子句将导致一个相互读取的IEnumerable链。在这里使用单子句形式将有助于提高性能。
当基础提供程序将其转换为SQL语句时,两个变体很可能会创建相同的语句。

相关问题