엔티티에 대한 LINQ의 주별 그룹화

c# entity-framework linq linq-to-entities

문제

나는 사용자가 일하는 데 소비하는 시간을 입력 할 수있는 응용 프로그램을 가지고 있으며 LINQ to Entities를 활용하는 좋은보고 기능을 얻으려고합니다. 각 TrackedTime 에는 DateTime 의 "Date"부분 인 TargetDate 가 있으므로 사용자와 날짜별로 시간을 그룹화하는 것이 상대적으로 간단합니다 (간단히하기 위해 "where"절을 생략합니다).

var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, t.TargetDate} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    TargetDate = ut.Key.TargetDate,
                    Minutes = ut.Sum(t => t.Minutes)
                };

DateTime.Month 속성 덕분에 사용자 및 월별 그룹화가 약간 더 복잡해집니다.

var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, t.TargetDate.Month} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    MonthNumber = ut.Key.Month,
                    Minutes = ut.Sum(t => t.Minutes)
                };

이제 까다로운 부분이 있습니다. Week로 그룹화 할 수있는 확실한 방법이 있습니까? 비슷한 LINQ to SQL 질문에 대한 이 응답 을 기반으로 다음을 시도했습니다.

DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days / 7} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    WeekNumber = ut.Key.WeekNumber,
                    Minutes = ut.Sum(t => t.Minutes)
                };

그러나 LINQ to Entities는 DateTime 개체의 산술 연산을 지원하지 않으므로 수행 방법을 알지 못합니다 (t.TargetDate - firstDay).Days / 7 .

필자는 며칠에서 수 주일 만에 매핑하는 데이터베이스에서 뷰를 만든 다음이 뷰를 내 Entity Framework 컨텍스트에 추가하고 LINQ 쿼리에 추가하는 방법을 고려해 보았습니다. 산술 방식에 대한 좋은 해결책이 있습니까? LINQ 문에 데이터베이스를 건드리지 않고도 간단히 통합 할 수있는 Linq와 Entity의 작동 원리는 무엇입니까? Linq에게 엔티티에게 한 날짜를 빼는 방법을 알려주는 방법은 무엇입니까?

개요

나는 사려 깊고 창의적인 답변을 해주신 모든 분들께 감사 드리고 싶습니다. 이 모든 질문을 마치고 나면이 질문에 대한 진정한 대답은 ".NET 4.0까지 기다려야합니다."와 같이 보입니다. 나는 Noldorin에게 LINQ를 여전히 활용하는 가장 실용적인 답을 주셨습니다. Jacob Proffitt는 데이터베이스 측면에서 수정하지 않고도 Entity Framework를 사용하는 응답을 내놓았습니다. 다른 위대한 해답도 있었고, 처음 질문을 보았을 때, 투표를 한 모든 사람들과 그들의 의견을 읽는 것이 좋습니다. 이것은 실제로 StackOverflow의 힘을 보여주는 훌륭한 예입니다. 다들 감사 해요!

수락 된 답변

AsEnumerable 확장 메서드에 대한 호출을 사용하여 그룹화를 위해 LINQ to Entities 대신 LINQ to Objects를 사용하도록 쿼리가 수행 할 수 있어야합니다.

다음을 시도하십시오.

DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes = 
    from t in context.TrackedTimes.Where(myPredicateHere).AsEnumerable()
    group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days / 7} into ut
    select new
    {
        UserName = ut.Key.UserName,
        WeekNumber = ut.Key.WeekNumber,
        Minutes = ut.Sum(t => t.Minutes)
    };

이것은 적어도 where 절이 LINQ to Entities에 의해 실행되지만 Entity가 처리하기에는 너무 복잡한 group 절이 LINQ to Objects에 의해 수행된다는 것을 의미합니다.

운이 좋으면 알려줘.

최신 정보

여기에 또 다른 제안이 있습니다. LINQ to Entities를 사용하여 전체적인 작업을 수행 할 수 있습니다.

(t.TargetDate.Days - firstDay.Days) / 7

이것은 단순히 연산을 확장하여 DateTime 빼기 대신 정수 빼기 만 수행하도록합니다.

현재 테스트되지 않았으므로 작동하지 않을 수도 있습니다 ...


인기 답변

SQLServer를 사용하는 한 LINQ에서도 SQL 함수를 사용할 수 있습니다.

using System.Data.Objects.SqlClient;

var codes = (from c in _twsEntities.PromoHistory
                         where (c.UserId == userId)
                         group c by SqlFunctions.DatePart("wk", c.DateAdded) into g
                         let MaxDate = g.Max(c => SqlFunctions.DatePart("wk",c.DateAdded))
                         let Count = g.Count()
                         orderby MaxDate
                         select new { g.Key, MaxDate, Count }).ToList();

이 샘플은 MVP Zeeshan Hirani의이 스레드에서 수정되었습니다. MSDN



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.