Gruppierung nach Wochen in LINQ an Entitäten

c# entity-framework linq linq-to-entities

Frage

Ich habe eine Anwendung, mit der Benutzer die Zeit eingeben können, für die sie arbeiten, und ich versuche, dafür gute Berichte zu erstellen, die LINQ to Entities nutzen. Da jede TrackedTime ein TargetDate das nur der "Date" -Abschnitt einer DateTime , ist es relativ einfach, die Zeiten nach Benutzer und Datum zu gruppieren (ich verwende zur Vereinfachung die "Wo" -Klauseln):

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)
                };

Dank der DateTime.Month Eigenschaft ist die Gruppierung nach Benutzer und Monat nur etwas komplizierter:

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)
                };

Nun kommt der knifflige Teil. Gibt es einen zuverlässigen Weg, um nach Wochen zu gruppieren? Aufgrund dieser Antwort auf eine ähnliche LINQ to SQL-Frage habe ich Folgendes versucht:

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 scheint jedoch keine arithmetischen Operationen für DateTime-Objekte zu unterstützen, so dass es nicht weiß, wie (t.TargetDate - firstDay).Days / 7 zu tun ist.

Ich habe mir überlegt, eine Ansicht in der Datenbank zu erstellen, die einfach Tage bis Wochen abbildet, und dann diese Ansicht zu meinem Entity Framework-Kontext hinzufügt und in meiner LINQ-Abfrage beitreten, aber das scheint eine Menge Arbeit für so etwas zu sein. Gibt es eine gute Umgehung des arithmetischen Ansatzes? Etwas, das mit Linq to Entities funktioniert, das ich einfach in die LINQ-Anweisung integrieren kann, ohne die Datenbank berühren zu müssen? Eine Möglichkeit, Linq den Entitäten mitzuteilen, wie ein Datum von einem anderen abgezogen werden soll?

Zusammenfassung

Ich möchte mich bei allen für ihre nachdenklichen und kreativen Antworten bedanken. Nach all dem Hin und Her sieht es so aus, als wäre die Antwort auf diese Frage "Warte bis .NET 4.0". Ich werde Noldorin die Prämie dafür geben, dass er die praktischste Antwort gibt, die LINQ noch nutzt, wobei Jacob Proffitt besonders erwähnt wird, weil er eine Antwort gefunden hat, die das Entity Framework verwendet, ohne dass Änderungen an der Datenbank vorgenommen werden müssen. Es gab auch andere großartige Antworten, und wenn Sie sich die Frage zum ersten Mal ansehen, würde ich nachdrücklich empfehlen, alle aufgegebenen Antworten sowie ihre Kommentare zu lesen. Dies ist wirklich ein hervorragendes Beispiel für die Leistungsfähigkeit von StackOverflow. Danke euch allen!

Akzeptierte Antwort

Sie sollten die Abfrage erzwingen können, LINQ to Objects anstelle von LINQ to Entities für die Gruppierung zu verwenden, indem AsEnumerable Erweiterungsmethode AsEnumerable .

Versuche Folgendes:

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)
    };

Dies würde zumindest bedeuten, dass die where Klausel von LINQ to Entities ausgeführt wird, aber die group Klausel, die für Entities zu komplex ist, wird von LINQ to Objects erledigt.

Lassen Sie mich wissen, ob Sie Glück haben.

Aktualisieren

Hier ist ein weiterer Vorschlag, der es Ihnen ermöglicht, LINQ to Entities für das Ganze zu verwenden.

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

Dadurch wird die Operation einfach so erweitert, dass nur eine ganzzahlige Subtraktion statt der DateTime Subtraktion ausgeführt wird.

Es ist derzeit nicht getestet, daher kann es funktionieren oder nicht ...


Beliebte Antwort

Sie können SQL-Funktionen auch in LINQ verwenden, solange Sie SQLServer verwenden:

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();

Dieses Beispiel wurde von MVP Zeeshan Hirani in diesem Thread angepasst: eine MSDN



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum