Linq如何正确使用

时间:2014-11-10 08:25:36

标签: c# linq

这两个查询之间有什么区别?

它们不是一样的,哪一个是快速的?在哪里使用后会出现什么问题?写在哪里之后使我的代码对我来说可读。我做错了吗?

首先查询:

   Model= (model.Where(p => p.Date.Year == yilim)
                        .Where(p => p.Id== 2 || p.Id== 3)
                        .OrderBy(m => m.Date.Month))
                        .ToList();

第二次查询:

  Model= (model.Where(p => p.Date.Year == yilim && (p.Id== 2 || p.Id== 3))
                            .OrderBy(m => m.Date.Month))
                            .ToList();

5 个答案:

答案 0 :(得分:5)

没有功能的区别,因为菊花链Where调用是一个逻辑AND操作,您目前正在AND两个独立的条件一起。

但是,在删除编译器优化条件检查(例如短路)的能力以及第二个Where所需的额外枚举器方面可能效率稍低只有一个普查员。(道歉,那部分只适用于Linq to Objects。)

如果您的代码符合OR条件,则只有第二个查询会提供您想要的内容:

Model= (model.Where(p => p.Date.Year == yilim || p.Id== 2 || p.Id== 3)
                          .OrderBy(m => m.Date.Month))
                          .ToList();

// Cannot express the above query in simple daisy-chained Where calls.

如果Where中的逻辑变得难以阅读,请尝试“无评论编码”并将条件填入具有可读名称的方法中,然后您可以执行.Where(x => TheCustomerNameIsValid(x))或方法分组它.Where(TheCustomerNameIsValid)(当你可以)。这也有助于调试,因为在一个方法中放置断点比在lambda中放置断点要少一些。

答案 1 :(得分:3)

不同之处在于,在第一个查询中,第一个Where将应用于名为model的序列,并且在结果序列中将应用第二个where方法。而在第二个查询中,Where方法应用于称为模型的序列。话虽如此,第二个查询从第一个查询开始效率更高,因为您只运行一次模型序列。

然而,说明第二个是从理论上更有效的步骤。我不认为在实践中你会得到任何重要的,如果有的话,可衡量的差异。

答案 2 :(得分:2)

您不太可能注意到两者之间存在任何显着的性能差异。两次调用Where()会增加一些开销:你创建了一个额外的中间对象,当然在枚举期间还有额外的方法调用来处理。

但在大多数代码中,这些差异并不明显。如果通过将过滤器拆分为两个单独的Where()调用,您发现代码更易于阅读和维护,那么这是更好的方法。

至少,也就是说,直到出现真正的性能问题。然后你可以回过头来重新审视这是否是你问题的一部分,值得改变。

答案 3 :(得分:2)

其他'答案非常明确,但我得到了不同的建议。为什么不通过调试检查生成的SQL查询。您将看到它们之间是否存在差异。要获取系统生成并运行的实际SQL查询,可以按如下方式编写:

using (EntityConnection con = new EntityConnection("Name = testEntities"))
{
    con.Open();

    using (testEntities db = new testEntities())
    {
        int yilim = 2013;

        IQueryable<Model> models = (db.Model.Where(p => p.Date.Year == yilim)
                                            .Where(p => p.ID == 2 || p.ID == 3)
                                            .OrderBy(m => m.Date.Month))
                                            .AsQueryable();

        string modelsQuery = ((System.Data.Objects.ObjectQuery)models).ToTraceString();

        IQueryable<Model> models2 = (db.Model.Where(p => p.Date.Year == yilim && 
                                                        (p.ID == 2 || p.ID == 3))
                                             .OrderBy(m => m.Date.Month))
                                             .AsQueryable();

        string modelsQuery2 = ((System.Data.Objects.ObjectQuery)models2).ToTraceString();

        System.IO.File.WriteAllText(@"C:\Users\username\Desktop\queries.txt", 
            "Query 1:\r\n" + modelsQuery + "\r\n" + 
            "Query 2:\r\n" + modelsQuery2);

    }

结果是:

Query 1:
SELECT 
[Project1].[ID] AS [ID], 
[Project1].[Date] AS [Date]
FROM ( SELECT 
    DATEPART (month, [Extent1].[Date]) AS [C1], 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Date] AS [Date]
    FROM [dbo].[Model] AS [Extent1]
    WHERE ((DATEPART (year, [Extent1].[Date])) = @p__linq__0) AND ([Extent1].[ID] IN (2,3))
)  AS [Project1]
ORDER BY [Project1].[C1] ASC


Query 2: 
SELECT 
[Project1].[ID] AS [ID], 
[Project1].[Date] AS [Date]
FROM ( SELECT 
    DATEPART (month, [Extent1].[Date]) AS [C1], 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Date] AS [Date]
    FROM [dbo].[Model] AS [Extent1]
    WHERE ((DATEPART (year, [Extent1].[Date])) = @p__linq__0) AND ([Extent1].[ID] IN (2,3))
)  AS [Project1]
ORDER BY [Project1].[C1] ASC

他们是完全相同的。因此,预计这里的性能不同。

答案 4 :(得分:2)

  

写在哪里之后使我的代码对我来说可读。我做错了吗?

其他人评论了性能/实际编译的好处,我只是建议代码的可读性(具有宗教性质,所以请使用grain of salt)。

重新格式化第一个查询:

   Model= (model.Where(p => p.Date.Year == yilim)
                .Where(p => p.Id== 2 || p.Id== 3)
                .OrderBy(m => m.Date.Month))
                .ToList();

我的偏好是将方法与应用的类对齐。 多维语句可能如下所示:

   Model= (model.Where(p => p.Date.Where(d => d.Year == 2014)
                                  .Where(d => d.Month == 11))
                .Where(p => p.Id== 2 || p.Id== 3)
                .OrderBy(m => m.Date.Month))
                .ToList();

重新格式化的第二个查询:

  Model= (model.Where(p => p.Date.Year == yilim 
                           && (p.Id== 2 || p.Id== 3))
               .OrderBy(m => m.Date.Month))
               .ToList();

为了便于中的操作符,我选择将所有OR内联,并将所有AND保留在不同的行中。

 Model = model.Where(m => (m.Name == "jon" || m.Name == "joe")
                          && (m.Color == "red" || m.Color == "blue"));

最后,我通常将lambda表达式参数缩短为与变量的第一个字母匹配的字母。

所以:

   Model= (model.Where(p => p.Date.Year == yilim)

变为:

   Model= (model.Where(m => m.Date.Year == yilim)

对于更复杂的查询,我还使用了:

   query = persons.Where(person => person == ...
                  .Where(person => person.Friends.Where(friend => 

有时单个字母很难与表达式关联,而不必阅读整个表达式树正在做什么。