LINQ-如果使用扩展方法,则Distinct()返回不同的值 [英] LINQ - Distinct() returning a different value if extension method used

查看:85
本文介绍了LINQ-如果使用扩展方法,则Distinct()返回不同的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个LINQ查询,它试图获取表中所有日期的所有不同月份.

I have a LINQ query which is attempting to get all of the distinct months of all of the dates in a table.

我使用Distinct()扩展方法进行了这项工作.然后,我通过使用扩展方法提取月份来使其更具可读性.然后它停止返回不同的结果.

I had this working using the Distinct() extension method. I then made it more readable by using an extension method to extract the month. And then it stopped returning Distinct results.

有人可以帮我弄清楚这里发生的事吗?

Can anyone help me work out what happened here?

顺便说一句,如果有人可以告诉我获得不同月份的最佳方法,那也很好.但更重要的是,我了解为什么会失败.

As an aside, if someone can tell me the best way to get the distinct months, that would be nice too. But it's more important that I understand why this is failing.

这是代码.

static class DcUtils
{
     public static DateTime GetMonth(this Timesheet_Entry entry)
    {
        DateTime dt = new DateTime(
                                     entry.Entry_Start_DateTime.Year,
                                     entry.Entry_Start_DateTime.Month, 
                                     1
                                  );
        return dt;
    }
}



public class Demo
{
    public DemonstrateBug()
    {
        TimesheetDataClassesDataContext dc = new TimesheetDataClassesDataContext();
    /////////////////////////////////
    //// Here are the queries and their behaviours
    var q1 = (
                from ts
                in dc.Timesheet_Entries
                select new DateTime(ts.Entry_Start_DateTime.Year, ts.Entry_Start_DateTime.Month, 1)
             ).Distinct();
    // This returns 3 (which is what I want)
    int lengthQuery1 = q1.Count();  

    // And now for the bug!

    var q2 = (
                 from ts
                 in dc.Timesheet_Entries
                 select ts.GetMonth()
             ).Distinct(); 
        // This returns 236 (WTF?)
        int lengthQuery2 = q2.Count();
    }
}

推荐答案

我想通过SQL Server Profiler运行它.

It occurred to me to run this through the SQL Server Profiler.

此查询:

var q1 = (                
            from ts                
            in dc.Timesheet_Entries                
            select new DateTime(ts.Entry_Start_DateTime.Year,
                                ts.Entry_Start_DateTime.Month, 
                                1)             
          ).Distinct();

生成以下SQL.如您所见,它将System.DateTime调用转换为Transact SQL.

generates the following SQL. As you can see, it converted the System.DateTime calls into Transact SQL.

     SELECT DISTINCT 
             [t1].[value]
       FROM (
           SELECT 
                CONVERT(
                          DATETIME, 
                          CONVERT(
                                    NCHAR(2), 
                                    DATEPART(
                                             Month, 
                                             [t0].[Entry_Start_DateTime]
                                             )
                                  ) 
                                    + (''/'' + (CONVERT(NCHAR(2), @p0) 
                                    + (''/'' + CONVERT(NCHAR(4), 
                                                      DATEPART(
                                                           Year, 
                                                           [t0].[Entry_Start_DateTime]
                                                              )
                                                       )
                                       ))), 101
                             ) AS [value]
             FROM [dbo].[Timesheet_Entry] AS [t0]
          ) AS [t1]

但是,如果我将月份提取逻辑放在扩展方法中:

But if I put the month extraction logic in the extension method:

    var q2 = (                 
                 from ts                 
                 in dc.Timesheet_Entries                 
                 select ts.GetMonth()             
             ).Distinct(); 

它产生以下SQL.

SELECT DISTINCT 
      [t0].[Timesheet_Entry_ID], 
      [t0].[Entry_Start_DateTime], 
      [t0].[Entry_End_DateTime], 
      [t0].[Task_Description], 
      [t0].[Customer_ID]
FROM [dbo].[Timesheet_Entry] AS [t0]

因此它已将DISTINCT函数移至服务器,但保留了日期提取代码,直到DISTINCT操作之后为止,这不是我想要的,也不是第一个示例中发生的情况.

So it's moved the DISTINCT function to the server, but kept the date extraction code until after the DISTINCT operation, which is not what I want, and is not what happens in the first example.

我不知道我应该称它为错误还是泄漏抽象.

I don't know if I should call this a bug or a leaky abstraction.

这篇关于LINQ-如果使用扩展方法,则Distinct()返回不同的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆