【问题标题】:LINQ: Difference between 'Select c' and 'Select new (c...'LINQ:“选择 c”和“选择新(c ...”)之间的区别
【发布时间】:2009-08-10 10:54:50
【问题描述】:

这两种说法有什么区别:

 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 仅包含这 3 个列。)

谢谢。

【问题讨论】:

    标签: c# asp.net linq linq-to-sql


    【解决方案1】:

    这两种说法有什么区别

    第一个返回原始/完整源对象的过滤序列;第二个仍然执行过滤器,但返回具有这三个属性的匿名类型序列。

    这些陈述中是否存在任何与性能相关的问题

    性能取决于后端。如果这是 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 表示通用答案,但在他的情况下,他无论如何都会返回所有列。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我进行了一些测试(使用秒表)。在 Linq-to-SQL(针对 SQL Server)、Linq-to-Entities(针对 MySQL)和 Linq-to-Objects(针对 List)中,匿名类型在任何情况下都没有更快的速度。事实上,通常它会更慢,具体取决于您选择的列数。

      我的一个结果: 我使用 Linq-to-Entities 针对由 400 行填充的 5 列表运行每个查询 5000 次。

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

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

      源对象:16055ms

      无论如何,找出答案的最好方法是自己测试(写一篇好帖子大约需要时间)。

      【讨论】:

        【解决方案4】:

        如有疑问,请提供个人资料。

        但是,是的,我认为存在性能开销。如果您执行select c,则该集合将包含对原始项目的引用。如果你这样做select new { ... },那么 C# 正在为你构建一个匿名类型,创建该类型的新实例并用数据填充它们。对我来说听起来肯定更慢。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-07
          • 2015-12-19
          • 1970-01-01
          • 2011-01-26
          相关资源
          最近更新 更多