2012-11-24 8 views
8

Sto utilizzando .NET e Entity Framework. Voglio raggruppare una tabella per una data senza la parte relativa all'ora.Entity framework group per data e ritorno nuova classe

Ho la classe:

public sealed class QueryItem { 
    public int Year { get; set; } 
    public int Month { get; set; } 
    public int Day { get; set; } 
} 

E il metodo (sto usando il BLToolkit, se si vuole sapere che cosa è DBManager):

protected override IQueryable<QueryItem> InitiateQuery() { 
    return 
     from query in DbManager.GetTable<SomeTableModel>() 
     group query by new { Year = query.CreationDate.Year, Month = query.CreationDate.Month, Day = query.CreationDate.Day } 
     into list1 
     select new QueryItem {Year = list1.Key.Year, Month = list1.Key.Month, Day = list1.Key.Day}; 
} 

In questo metodo LINQ tradotto in questa query SQL:

SELECT 
    [query].[CreationDate] 
FROM 
    [SomeDatabase.SomeTable] [query] 
GROUP BY 
    DatePart(Year, [query].[CreationDate]), 
    DatePart(Month, [query].[CreationDate]), 
    DatePart(Day, [query].[CreationDate]), 
    [query].[CreationDate] 

E questa è una query errata perché non raggruppa solo per una data.

Ma se io uso questo codice (non è utilizzabile, ho bisogno di restituire un oggetto di classe):

var result = 
    from query in DbManager.GetTable<SomeTableModel>() 
    group query by new { Year = query.CreationDate.Year, Month = query.CreationDate.Month, Day = query.CreationDate.Day } 
    into list1 
    select list1; 

Sarà tradotto in questo modo:

SELECT 
    [t1].[c1] as [c11], 
    [t1].[c2] as [c21], 
    [t1].[c3] as [c31] 
FROM 
    (
     SELECT 
      DatePart(Year, [selectParam].[CreationDate]) as [c1], 
      DatePart(Month, [selectParam].[CreationDate]) as [c2], 
      DatePart(Day, [selectParam].[CreationDate]) as [c3] 
     FROM 
      [SomeDatabase.SomeTable] [selectParam] 
    ) [t1] 
GROUP BY 
    [t1].[c1], 
    [t1].[c2], 
    [t1].[c3] 

E questo è il giusto query.

Suppongo che Entity Framework cerchi di ottimizzare la mia query o qualcosa del genere e questo è il motivo per cui ho ottenuto la query sbagliata.

Ho ragione? Lo sto facendo nel modo giusto? Cosa devo fare (magari usare la query SQL diretta o qualcos'altro)?

risposta

8

E 'molto più semplice da usare EntityFunctions * qui:

var result = 
    from query in DbManager.GetTable<SomeTableModel>() 
    group query by EntityFunctions.TruncateTime(query.CreationDate) 
    into list1 
    select list1; 

* DbFunctions come di Entity Framework 6.

+0

Suppongo che dovrebbe funzionare. Ma ha fallito con BLToolkit. Il messaggio di eccezione: _'TruncateTime (Convertire (selectParam.CreationDate))' non può essere convertito in SQL._ E la stacktrace: _ a BLToolkit.Data.Linq.Builder.ExpressionBuilder.ConvertToSql (contesto, espressione Espressione IBuildContext , Boolean unwrap) _ Dovrei pensare a come realizzare l'interfaccia utente del filtro in un altro modo. – colotiline

+0

In EF si traduce in 'convert (datetime, convert (varchar (255), [DateField], 102), 102))'. Puoi usarlo per creare qualche funzione in BLT? Non mi è chiaro come BLT e EF collaborino. La documentazione BLT è davvero scarsa, purtroppo. –

+0

Ho provato ad implementare il mio comparatore. Anche questo è fallito.È sempre cercare di ottimizzare la query e fallito. Ma ho usato un'altra interfaccia utente e un modo per filtrare i dati e ora tutto funziona. – colotiline

2

Aggiornamento risposta:EntityFunctions preso deprecato.

Attenzione 1 'System.Data.Entity.Core.Objects.EntityFunctions' è obsoleta: 'Questa classe è stata sostituita da System.Data.Entity.DbFunctions.' C: \ Users \ liufa \ documenti \ Visual Studio 2013 \ Projects \ MatasMrLenderTest \ Mvc5MobileApplication1 \ Controller \ CreditScoreController.cs 32 103 Mvc5MobileApplication1

Ora è DbFunctions.

using System.Data.Entity; 

var result = DbManager.GetTable<SomeTableModel>() 
.GroupBy(o => DbFunctions.TruncateTime(o.CreationDate))