2010-01-20 15 views
5

Ich bin neu in LINQ to SQL und ich möchte wissen, wie so etwas in LINQ zu erreichen:LINQ Gruppe von Monat Frage

 Month Hires Terminations 
     Jan  5  7 
     Feb  8  8 
     Marc  8  5 

ich das habe, so weit, und ich denke, es ist etwas falsch damit aber ich bin mir nicht sicher:

from term1 in HRSystemDB.Terminations 
group term1 by new { term1.TerminationDate.Month, term1.TerminationDate.Year } into grpTerm 
select new HiresVsTerminationsQuery 
{ 
    Date = Criteria.Period, 
    TerminationsCount = grpTerm.Count(term => term.TerminationDate.Month == Criteria.Period.Value.Month), 
    HiresCount = (from emp in HRSystemDB.Persons.OfType<Employee>() 
       group emp by new { emp.HireDate.Month, emp.HireDate.Year } into grpEmp 
       select grpEmp).Count(e => e.Key.Month == Criteria.Period.Value.Month) 
}); 

Vielen Dank im Voraus.

+0

Zeigen Sie uns Ihr Datenbankschema würde helfen. – Blindy

+0

Was sind 'Criteria.Period' und' Criteria.Period.Value.Month'? –

+0

Was lässt Sie unsicher sein, dass es richtig ist? Kompiliert es? Hast du es versucht? Gibt es die Ergebnisse, die Sie erwarten? –

Antwort

6

Ich bin mir nicht ganz sicher, wo der Wert Criteria.Period in Ihrer Beispielabfrage herkommt.

Aber ich denke, Sie versuchen, sowohl Mieten und Abschlüsse für alle verfügbaren Monate zu lesen (und dann können Sie es leicht filtern). Ihre Abfrage könnte schief gehen, wenn die erste Tabelle (Termination) keine Datensätze für einen bestimmten Monat enthält (z. B. Mai). Dann würde die select-Klausel nicht mit "May" als Parameter überhaupt aufgerufen werden, und selbst wenn Sie einige Daten in der zweiten Tabelle (Hires) hätten, wären Sie nicht in der Lage, sie zu finden.

Dies kann elegant mit der Concat method gelöst werden (siehe MSDN-Beispiele). Sie könnten alle termniations wählen und alle Mitarbeiter (in eine Datenstruktur eines bestimmten Typs) und dann die Gruppe alle Daten von Monat:

var terms = from t in HRSystemDB.Terminations 
      select new { Month = t.TerminationDate.Month, 
         Year = term1.TerminationDate.Year, 
         IsHire = false }; 
var hires = from emp in HRSystemDB.Persons.OfType<Employee>() 
      select new { Month = emp.HireDate.Month, 
         Year = emp.HireDate.Year 
         IsHire = true }; 

// Now we can merge the two inputs into one 
var summary = terms.Concat(hires); 

// And group the data using month or year 
var res = from s in summary 
      group s by new { s.Year, s.Month } into g 
      select new { Period = g.Key, 
         Hires = g.Count(info => info.IsHire), 
         Terminations = g.Count(info => !info.IsHire) } 

Wenn jetzt Blick auf den Code, ich bin ziemlich sicher, dass es einige kürzere Weg ist, um dies zu schreiben. Auf der anderen Seite sollte dieser Code gut lesbar sein, was ein Vorteil ist. Beachten Sie auch, dass es nicht wichtig ist, dass wir den Code in einige Unterabfragen aufteilen. Dank der Lazy Evaluation von LINQ to SQL sollte dies als eine einzige Abfrage ausgeführt werden.

+0

Das ist eine ziemlich gute Antwort. Ich wusste nichts von der Concat-Methode. Ich werde später damit experimentieren und meine Ergebnisse veröffentlichen. Vielen Dank. – jasonco

+0

Du hast mein Leben gerettet. Hat super funktioniert! Genau das, wonach ich gesucht habe. Vielen Dank! +1 – jasonco

3

Ich weiß nicht, ob es kürzer ist, aber Sie können diese Version auch versuchen, um zu sehen, ob es besser mit Ihrem Server funktioniert. Ich weiß nicht genau, wie diese beiden Antworten zu SQL-Anweisungen werden. Einer könnte besser sein, basierend auf Ihren Indizes und so.

var terms = 
    from t in Terminations 
    group t by new {t.Month, t.Year} into g 
    select new {g.Key, Count = g.Count()}; 

var hires = 
    from p in Persons 
    group p by new {p.Month, p.Year} into g 
    select new {g.Key, Count = g.Count()}; 

var summary = 
    from t in terms 
    join h in hires on t.Key equals h.Key 
    select new {t.Key.Month, t.Key.Year, 
     Hires = h.Count, Terms = t.Count}; 
+0

Danke für die Antwort. Diese Version funktioniert so lange, wie es im selben Monat Kündigungen oder Neueinstellungen gab. Wenn es in keinem von ihnen irgendwelche Einstellungen oder Kündigungen gegeben hat, werden keine Ergebnisse für diesen speziellen Monat angezeigt, selbst wenn es im Mai 2, aber 0 Kündigungen gab. Ich musste eine kleine Korrektur vornehmen, die Gruppe von (für meinen speziellen Fall) sollte "Gruppe t durch neue {t.TerminationDate.Month, t.TerminationDate.Year} in g" und "Gruppe p durch neue {p. HireDate.Month, p.HireDate.Year} in g ". Ansonsten denke ich, dass es eine gute Antwort ist. Vielen Dank! +1 :-) – jasonco