Подтвердить что ты не робот

Linq - группировка по дате и выбор счетчика

В настоящее время я работаю над проблемой, когда я хотел бы запустить запрос, который группирует результаты по выбранной дате.

В этом примере представьте себе такую ​​простую модель:

public class User
{
      public DateTime LastLogIn {get; set;}
      public string Name {get; set;}
}

Решение, которое я ищу, - это подсчет количества зарегистрированных пользователей по дате. В базе данных DateTime хранятся с компонентами даты и времени, но для этого запроса я действительно забочусь только о дате.

В настоящее время у меня есть:

    context.Users
            .Where((x.LastLogIn  >= lastWeek)    
                && (x.LastLogIn <= DateTime.Now))
            .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
            .Select(x => new
            {
                Value = x.Count(),
                Day = (DateTime)EntityFunctions.TruncateTime(x.Key)
            }).ToList();

Приведенное выше возвращает пустой список.

Конечная цель состоит в том, чтобы иметь список объектов, которые содержат значение (количество зарегистрированных пользователей в день) и день (день, о котором идет речь)

Любые мысли?

После изменения запроса на:

    context.Users
            .Where((x.LastLogIn  >= lastWeek)    
                && (x.LastLogIn <= DateTime.Now))
            .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
            .Select(x => new
            {
                Value = x.Count(),
                Day = (DateTime)x.Key
            }).ToList();

теперь он возвращает список с одним элементом, а значение - это общее количество пользователей, которое соответствует предложению where, а день - самый первый день. Кажется, он все еще не мог группироваться по дням.

ПРИМЕЧАНИЕ: оказывается, что приведенный выше код прав, я просто делал что-то еще не так.

Sql, который он генерирует, (обратите внимание, что здесь могут быть очень незначительные синтаксические ошибки, когда я настраиваю его для примера):

SELECT 
1 AS [C1], 
[GroupBy1].[A1] AS [C2], 
 CAST( [GroupBy1].[K1] AS datetime2) AS [C3]
FROM ( SELECT 
        [Filter1].[K1] AS [K1], 
        COUNT([Filter1].[A1]) AS [A1]
        FROM ( SELECT 
                 convert (datetime2, convert(varchar(255), [Extent1].[LastLogIn], 102) ,  102) AS [K1], 
                1 AS [A1]
                FROM [dbo].[Users] AS [Extent1]
                WHERE (([Extent1].[LastLogIn] >= @p__linq__1) AND ([Extent1].[LastLogIn] <= @p__linq__2)
        )  AS [Filter1]
       GROUP BY [K1]
)  AS [GroupBy1] 
4b9b3361

Ответ 1

Вам не нужен второй TruncateTime там:

context.Users
    .Where((x.LastLogIn  >= lastWeek) && (x.LastLogIn <= DateTime.Now))
    .GroupBy(x => DbFunctions.TruncateTime(x.LastLogIn))
    .Select(x => new
    {
        Value = x.Count(),
        // Replace the commented line
        //Day = (DateTime)DbFunctions.TruncateTime(x.Key)
        // ...with this line
        Day = (DateTime)x.Key
    }).ToList();

GroupBy уже GroupBy время с DateTime, поэтому вам не нужно вызывать его снова.

Чтобы использовать DbFunctions.TruncateTime вам нужно сослаться на сборку System.Data.Entity и включить using System.Data.Entity;

Примечание. Отредактировано для устранения устаревания EntityFunctions.

Ответ 2

Попробуйте следующее:

 .GroupBy(x => new {Year = x.LastLogIn.Year, Month = x.LastLogIn.Month, Day = x.LastLogIn.Day)
                .Select(x => new
                {
                    Value = x.Count(),
                    Year = x.Key.Year,
                    Month = x.Key.Month,
                    Day = x.Key.Day
                })

Ответ 3

Вы можете сделать это легко:

yourDateList.GroupBy(i => i.ToString("yyyyMMdd"))
             .Select(i => new
             {
                 Date = DateTime.ParseExact(i.Key, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None),
                 Count = i.Count()
             });

Ответ 4

Вы также можете сделать это в одной строке.

var b = (from a in ctx.Candidates select a)
            .GroupBy(x => x.CreatedTimestamp.Date).Select(g => new { Date=(g.Key).ToShortDateString(), Count = g.Count() });