2010-01-20 11 views
5

Sono nuovo di LINQ to SQL e vorrei sapere come ottenere qualcosa di simile in LINQ:gruppo LINQ per mese questione

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

ho questo finora, e ci credo c'è qualcosa che non va, ma non sono sicuro:

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

Grazie in anticipo.

+0

Mostrandoci il tuo schema di database sarebbe d'aiuto. – Blindy

+0

Cosa sono 'Criteria.Period' e' Criteria.Period.Value.Month'? –

+0

Cosa ti fa sentire insicuro che sia giusto? Compila? Hai provato a farlo funzionare? Dà i risultati che ti aspetti? –

risposta

6

Non sono del tutto sicuro da dove viene il valore Criteria.Period nella query di esempio.

Tuttavia, penso che stai provando a leggere sia assunzioni che interruzioni per tutti i mesi disponibili (e quindi puoi facilmente filtrarlo). La tua query potrebbe andare storta se la prima tabella (Termination) non include alcun record per un determinato mese (ad esempio maggio). Quindi la clausola select non verrebbe chiamata con "May" come parametro e anche se nella seconda tabella erano presenti alcuni dati (che rappresentano Hires), non sarebbe possibile trovarli.

Questo può essere elegantemente risolto utilizzando Concat method (vedere esempi MSDN). È possibile selezionare tutti i termniations e tutte le assunzioni (in una struttura di dati di un certo tipo) e poi di gruppo tutti i dati per mese:

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

Se si guarda il codice ora, sono abbastanza sicuro che ci sia un modo più breve scrivere questo D'altra parte, questo codice dovrebbe essere abbastanza leggibile, il che è un vantaggio. Nota anche che non importa se dividiamo il codice in un paio di sottoquery. Grazie alla lenta valutazione di LINQ in SQL, questo dovrebbe essere eseguito come una singola query.

+0

Questa è davvero una buona risposta. Non sapevo del metodo concat. Lo sperimenterò più tardi e pubblicherò i miei risultati. Grazie. – jasonco

+0

Mi hai salvato la vita. Ha funzionato alla grande! Proprio quello che stavo cercando. Grazie! +1 – jasonco

3

Non so se è più breve ma puoi provare anche questa versione per vedere se funziona meglio con il tuo server. Non so esattamente come queste due risposte si trasformino in istruzioni SQL. Uno potrebbe essere meglio basato sui tuoi indici e così via.

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

Grazie per la risposta. Questa versione funziona fintanto che ci sono stati terminazioni o assunzioni nello stesso mese. Se non ci fossero assunzioni o cessazioni in nessuno di essi, nessun risultato verrà visualizzato per quel particolare mese, anche se ci sono stati, diciamo 2 assunzioni ma 0 cessazioni a maggio. Ho dovuto fare una piccola correzione, il gruppo da (per il mio caso particolare) dovrebbe essere "gruppo t di nuovo {t.TerminationDate.Month, t.TerminationDate.Year} in g" e "group p di new {p. HireDate.Month, p.HireDate.Year} in g ". Oltre a questo penso che sia una buona risposta. Grazie! +1 :-) – jasonco