2011-04-30 3 views
8

Ho una classe Entity con data/ora archiviato, desidero selezionare il valore distinto 'mon-yyyy' nel formato archiviato datetime e popolare l'elenco a discesa.La data di formattazione nella query Linq-to-Entities causa l'eccezione

il seguente codice mi dà l'errore: messaggio

var env = db.Envelopes.Select(d => new 
     { 
      d.ReportDate.Year, 
      d.ReportDate.Month, 
      FormattedDate = d.ReportDate.ToString("yyyy-MMM") 
     }).Select(d => d.FormattedDate) 

    List<SelectListItem> _months = new List<SelectListItem>();   

    foreach (var mname in env) 
    { 
     _months.Add(new SelectListItem() { Text = mname, Value = mname }); 
    } 

Errore:

LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.

Come posso correggere questo messaggio di errore?

Grazie SR

risposta

13

Ricordate che la vostra richiesta sta per essere tradotto in SQL e inviati al database. Il tuo tentativo di formattare la data non è supportato nella query, motivo per cui stai visualizzando quel particolare messaggio di errore. È necessario recuperare i risultati e quindi formattare dopo che i dati sono stati materializzati.

Un'opzione è semplicemente selezionare la data così com'è. Mentre esegui l'iterazione sul risultato, formattalo mentre lo aggiungi al tuo elenco. Ma puoi anche ottenere la costruzione della lista con la data formattata in una singola istruzione usando il metodo di concatenazione.

List<SelectListItem> _months = db.Envelopes.OrderByDescending(d => d.ReportDate) 
     .Select(d => d.ReportDate) 
     .AsEnumerable() // <-- this is the key method 
     .Select(date => date.ToString("MMM-yyyy")) 
     .Distinct() 
     .Select(formattedDate => new SelectListItem { Text = formattedDate, Value = formattedDate }) 
     .ToList(); 

Procedimento .AsEnumerable() forzerà l'esecuzione della prima porzione della query nel database e il resto lavoreranno con i risultati in memoria.

+0

@Anthony Pegram: grazie per la risposta. dal tuo codice voglio ottenere il valore distinto e ordinare da ReportDate in ordine decrescente. dove ho bisogno di aggiungere questi due nel tuo codice. – sfgroups

+0

Ho aggiornato la risposta per includere un ordinamento per data discendente e un distinto prima della chiamata 'AsEnumerable()'. Questi saranno quindi parte di SQL e gestiti dal database. –

+0

@Anthony Pegram, scusa se la mia domanda non è chiara, penso. Voglio ottenere il valore distinto 'yyyy-MMM', non il distinto reportdate. – sfgroups

8

Ecco un'alternativa:

.Select(p -> SqlFunctions.StringConvert((double) 
        SqlFunctions.DatePart("m", p.modified)).Trim() + "/" + 
       // SqlFunctions.DateName("mm", p.modified) + "/" + MS ERROR? 
       SqlFunctions.DateName("dd", p.modified) + "/" + 
       SqlFunctions.DateName("yyyy", p.modified) 

Apparentemente DateName("MM", ..) enuncia il nome del mese in cui DatePart("mm", ..) fornisce un valore numerico, così il StringConvert(), ma questo pad a sinistra il risultato con gli spazi, quindi il .Trim().

come Anthony Pegram detto sopra, questo accade nel database, piuttosto che in C# (.AsEnumerable() tira tutti i dati locali di C# in modo da assicurarsi di filtrare i dati prima di utilizzarlo.)

Ovviamente ci si vuole riorganizzare l'output leggermente per adattarsi allo yyyy-MM e utilizzare DatePart per la cifra o DateName per il nome del mese.

+4

Ama la risposta, ma mi uccide quando le persone usano le classi senza indicare lo spazio dei nomi in cui la classe può essere trovata. SqlFunctions si trova nello spazio dei nomi System.Data.Objects.SqlClient. Avrai bisogno di un riferimento all'assembly System.Data.Entity nel tuo progetto per trovarlo. – Tim

+0

Molto utile, grazie. – hncl

1

Ecco un'alternativa che utilizza il formato comune gg/MM/aaaa. Confermato lo SQL Server 2012 con Entity Framework 5

invoices.Select(i => new 
{ 
    FormattedDate = ( EntityFunctions.Right(String.Concat(" ", SqlFunctions.StringConvert((double?) SqlFunctions.DatePart("dd", i.DocumentDate))), 2) 
         + "/" 
         + EntityFunctions.Right(String.Concat(" ",SqlFunctions.StringConvert((double?) SqlFunctions.DatePart("mm", i.DocumentDate))), 2) 
         + "/" 
         + EntityFunctions.Right(SqlFunctions.StringConvert((double?) SqlFunctions.DatePart("yyyy", i.DocumentDate)), 4) 
         ).Replace(" ", "0") 
} 

Produce date in un formato gg/mm/aaaa con zeri.

0

Ho utilizzato una soluzione alternativa per creare manualmente i formati contenenti yyyy e MM. Vorrei citare qui se può aiutare qualcuno (almeno temporaneamente):

FormattedDate = d.ReportDate.Year.ToString() + "-" + d.ReportDate.Month.ToString() 

Questo rende il formato yyyy-MM

Problemi correlati