LINQ:'Select c'和'Select new (c...'之间的区别

5
这两个语句有什么区别呢?

这两个语句的区别在于:

 var result = from c in context.CustomerEntities
 join p in context.ProjectEntities on c.Pk equals p.CustomerPk
 where p.Entered > DateTime.Now.AddDays(-15)
 select c; 

并且

 var result = from c in context.CustomerEntities
 join p in context.ProjectEntities on c.Pk equals p.CustomerPk
 where p.Entered > DateTime.Now.AddDays(-15)
 select new (c.Company, c.Entered, c.pk);

这些语句中是否存在与性能相关的问题?(为简单起见,c仅包含这三列。)

谢谢。

4个回答

10
这两个语句有何不同?第一个返回源对象的筛选序列;第二个仍然进行筛选,但是返回的是只有这三个属性的匿名类型的序列。
这些语句是否存在性能问题取决于后端。如果是针对 LINQ-to-Objects,那么使用 "new {...}" 会为每个记录创建额外的对象 (匿名类型),因此可能会有非常小的开销。但是,如果是针对 LINQ-to-SQL 等数据库后端,则可能会带来巨大的好处。查询构建器将检查哪些列是必需的,并且只获取匿名类型中的这三个属性;如果你的数据中有不需要的 BLOB(或长的 varchar)等内容,则这可能是一个巨大的好处。
额外说明:匿名类型不能包含在方法签名中,因此您可能需要声明自己的 DTO 类型。
return new CustomerDto { Company = c.Company, Entered = c.Entered, PK = c.pk};
...
public class CustomerDto { ... }

1
+1 对于通用答案,但在他的情况下,他无论如何都会返回所有列。 - cjk

2

我进行了一些测试(使用 Stopwatch)。在 Linq-to-SQL(针对 SQL Server)、Linq-to-Entities(针对 MySQL)以及 Linq-to-Objects(针对 List)中,匿名类型并没有比其他方式更快。实际上,通常情况下,它的速度会更慢,这取决于你选择了多少列。

其中一个测试结果如下: 我在 Linq-to-Entities 中使用了一个有 5 列、400 行的表,每个查询都运行了 5000 次。

匿名对象(选择 1 列):17314 毫秒

匿名对象(选择 5 列):19193 毫秒

源对象:16055 毫秒

无论如何,最好的方法是自己进行测试(需要写一篇好的文章的时间)。


2
主要区别在于第一个示例返回对现有实例的引用,而第二个示例创建了匿名类型的新实例。我比任何可能的性能问题更关心这个问题。

1

如果有疑问,就进行性能分析。

但是,我认为这会带来一定的性能开销。如果你使用 select c,那么集合将包含对原始项的引用。如果你使用 select new { ... },那么 C# 将为你构建一个匿名类型,创建该类型的新实例并填充数据。听起来肯定更慢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接