这两个 LINQ 查询有啥区别以及如何正确优化它们?

Posted

技术标签:

【中文标题】这两个 LINQ 查询有啥区别以及如何正确优化它们?【英文标题】:What is the difference between these two LINQ Queries and how to correctly optimize them?这两个 LINQ 查询有什么区别以及如何正确优化它们? 【发布时间】:2020-12-06 13:50:31 【问题描述】:

我有一个包含以下列的客户表: Id、FirstName、LastName、CurrencyId、Gender。

我想选择与 Id 10 对应的客户货币,所以我正在做这样的事情:

var currencyId = Db.Clients.FirstOrDefault(c=>c.Id == 10)?.CurrencyId;

此行是从 Db 中获取所有属性并在代码中选择货币还是在数据库中执行类似的操作:

SELECT currencyId FROM Client WHERE ID = 10

或者我应该这样写 linq:

var currencyId = Db.Clients.Where(c=>c.Id == 10).Select(c=>c.CurrnecyId).FirstOrDefault();

这两个查询有什么区别? 将上述 SQL 查询转换为 linq 查询的正确方法是什么?

【问题讨论】:

没什么。您必须查看 SQL 命令文本才能确定差异。 @jdweng 根本不正确 - 这些查询是不同的。第一个可以抛出异常,而第二个会给你一个默认值(例如0 @DavidG 注意到“?”我在第一个查询的 firstOrDefault() 之后添加,这样它就不会抛出异常 好的,但还是不一样。第一个会给你null,第二个仍然给你一个默认值,比如0 @DavidG 好的,谢谢。但是翻译后的 SQL 查询有区别吗? 【参考方案1】:

我自己研究了一下,因为我发现大多数人的回答都是有问题的。我希望 FirstOrDefault 能够实现结果(您还可以从类型中看到您不再使用查询对象),这意味着它会查询所有属性。

与第二个查询不同,您在过滤您喜欢的属性时仍在使用查询,因此取决于实现,它可用于过滤属性和选择特定字段。

以下是使用 EF 为两个类似查询生成的查询示例,其中显示了两者都生成不同的查询:https://dotnetfiddle.net/5aFJAZ

【讨论】:

嗨,你是对的,但要超正确,a) 你的程序不能证明这一点,除非你在单独的上下文中执行这两个查询..我做了并且结果是相同的 b)它应该是“它可以用于过滤属性和选择特定字段” @MichaelSchönbauer 是的 :) 你是完全正确的。我已在 anwser 中添加反馈【参考方案2】:

在您的第一个示例中,var currencyId = Db.Clients.FirstOrDefault(c=>c.Id == 10)?.CurrencyId; 查询将整个对象选择到内存中,然后从内存对象中返回 Id 属性。因此,它需要执行类似于以下 SQL 的操作:SELECT * FROM Clients WHERE Id = 10。我知道我在这里没有使用参数,并且 EF 确实拼出了每一列。然而,这里要理解的关键是,如果返回的列比您需要的多,您可能会设置性能问题,因为不会使用 Id 和 CurrencyId 上的覆盖索引。

您的第二个 LINQ 查询将使用像 SELECT CurrencyId FROM Clients Where Id = 10 这样的 SQL 语句,假设您有一个涵盖这些列的索引,它将利用您的索引。

【讨论】:

以上是关于这两个 LINQ 查询有啥区别以及如何正确优化它们?的主要内容,如果未能解决你的问题,请参考以下文章

Linq to XML 后代和元素有啥区别

如何正确分组我的 LINQ 查询?

在 LINQ 中,Join 和从嵌套查询中选择第一项之间有啥区别

Yii2 中的 $with 和 $joinWith 有啥区别以及何时使用它们?

这是在 .netCore 项目中使用 LINQ 查询连接两个表的正确方法吗?

LINQ TO SQL 和 ADO.NET ENTITY 有啥区别呢?