Linq to Entities non riconosce la stringa.Formato o concatenazione ‘+’

Ho il codice sotto:

using (DBContext context = new DBContext())
{
    myCollection = context.Items.Where(i => i.Type == 1).OrderBy(k => k.Name).Select(w => new
    {
        Alias = w.Name + string.Format("{0}", w.Id),
        Name = w.Name                        
    }).ToArray();
}

In fase di esecuzione ottengo un errore quando cerchi di concatenare le stringhe e cercando con la conversione intero w.Id di stringa.

Di errore dice:

Linq to entities non riconosce il metodo string.Formato

anche più concatenazione segno ‘+’ non è supportato.

Ho risolto questo introducendo AsEnumerable:

using (DBContext context = new DBContext())
{
    myCollection = context.Items.AsEnumerable().Where(i => i.Type == 1).OrderBy(k => k.Name).Select(w => new
    {
        Alias = w.Name + string.Format("{0}", w.Id),
        Name = w.Name                        
    }).ToArray();
}

ma vorrei sapere se questa è la soluzione migliore o c’è un altro modo più adatto per farlo. Idee?

InformationsquelleAutor Rodri | 2013-10-02

 

2 Replies
  1. 15

    Una ottimizzazione del codice è quello di utilizzare AsEnumerable() dopo il Where metodo. Se non, ogni ente è tornato da stoccaggio, e l’intera tabella viene esaminato utilizzando LINQ to Objects. Con questa semplice modifica del codice si lascia che la clausola where in esecuzione in sql e recuperare meno dischi da storage. La regola generale è quello di posizionare qualsiasi query clausole che sono implementati dal provider LINQ prima.

    using (DBContext context = new DBContext())
    {
        myCollection = context.Items.Where(i => i.Type == 1)
           .AsEnumerable().OrderBy(k => k.Name).Select(w => new
            {
                Alias = w.Name + string.Format("{0}", w.Id),
                Name = w.Name                        
            }).ToArray();
    }
    • Sì, funziona … ma fate attenzione a restringere il resultset prima l’ .AsEnumerable(), come hai fatto tu nell’esempio utilizzando Where(...). Altrimenti le cose potrebbero diventare incredibilmente lento, perché si sta facendo a memoria, piuttosto che nel database.
  2. 15

    EF non è possibile convertire String.Format in SQL, ma gestisce concatenazioni di stringa senza problema. Utilizzare SqlFunctions.StringConvert invece di String.Format per convertire il numero in stringa sul lato server:

    Select(w => new {
        Alias = w.Name + SqlFunctions.StringConvert((double)w.Id),
        Name = w.Name                        
    })

    Genera qualcosa come

    SELECT 
    [Extent1].[Name] + STR( CAST( [Extent1].[Id] AS float)) AS [C1], 
    [Extent1].[Name] AS [Name]
    FROM [dbo].[Items] AS [Extent1]

    AGGIORNAMENTO: Così si utilizza EF provider che non supporta questa conversione (SQL CE provider non può tradurre questa query in SQL) hai una sola opzione a sinistra – spostare i calcoli per il lato client, come hai già fatto.

    • Si è dato il seguente errore: Il metodo ‘del Sistema.Stringa StringConvert(Di Sistema.Nullable`1[Sistema.Double])’ sul tipo ‘System.Dati.Oggetti.SqlClient.SqlFunctions’ non può essere tradotto in LINQ to Entities negozio di espressione.
    • sembra come se non si utilizza Microsoft SQL Server provider di Entity Framework, e il tuo provider non supporta queste funzioni. Se il provider non supporta la conversione di numeri in stringhe sul lato server, quindi è possibile spostare solo la conversione al cliente (ad es. con AsEnumerable())
    • Il provider che sto usando è SQLCe (compact edition) 4.0, quindi in questo caso come hai detto, l’unica possibile soluzione è usare AsEnumerable().
    • purtroppo sì, ma vi consiglio di selezionare solo i dati necessari prima di passare al client: Select(w => new { w.Name, w.Id }).AsEnumerable().Select(x => new { Alias = x.Name + x.Id, x.Name })
    • SqlFunctions sono molto interessanti. Mai usato prima. Ma come ottenere i dati convertiti in una cultura più sensibile? Ho la punto come separatore decimale, quando mi aspetto una virgola. Grazie.

Lascia un commento