2013-11-25 12 views
6

Sono relativamente nuovo a LINQ per entità, ma uso LINQ to Sql molto.Non può essere tradotto in un LINQ per l'espressione del negozio di entità

Sto usando Visual Studio 2013, con EntityFramework 6 e MVC 5.

La più grande differenza tra i due è che Linq2SQL ha la capacità di eseguire le conversioni all'interno della stessa query SELECT mentre LINQ2Entities non è così indulgente e deve avere la corretta conversione sul posto prima di eseguire la query LINQ. Pertanto, viene visualizzato l'errore: Il metodo specificato 'System.Decimal ConvertToDecimal (Byte)' sul tipo 'BillYeagerDB.EdmxExtensionMethods' non può essere tradotto in un'espressione di archivio LINQ to Entities.

Dopo aver fatto molte ricerche, soprattutto su stackoveflow con questa domanda, ho scoperto un collegamento (LINQ to Entities does not recognize the method 'Double Parse(System.String)' method, and this method cannot be translated into a store expression) che si spera funzionerebbe. Sono certo che l'esempio che l'autore offre funziona, ma stava lavorando con ObjectContext e sto lavorando con DbContext.

Sono anche sicuro che funzionerà per me, ma penso che sto solo progettando il metodo di estensione in modo errato (che mi dà l'errore di cui sopra). Tieni presente che questo problema specifico riguarda la variabile AvgRating nella query di Linq. Una volta che posso farlo funzionare, posso fare lo stesso tipo di correzione per qualsiasi altra conversione. Si noti che AvgRating è definito come tipo Decimale e a.Rating.RatingValue è definito come tipo Byte.

Se qualcuno mi raddrizza su questo, lo apprezzerei molto.

Ecco il mio codice. Sto cercando di utilizzare la seguente query, che so non funzionerà (come menzionato prima) a causa del problema di conversione.

originale LINQ Query:

namespace BillYeagerDB 
{ 
    public class BillYeagerDB 
    { 
     public async Task<List<RestaurantList>> GetRestaurantListAsync() 
     { 
      try 
      { 
       using (BillYeagerEntities DbContext = new BillYeagerEntities()) 
       { 
        DbContext.Database.Connection.Open(); 

        var restaurants = await DbContext.Restaurants.GroupBy(g => g).Select(s => 
         new RestaurantList() 
         { 
          Name = s.Key.Name, 
          City = s.Key.City, 
          Phone = s.Key.Phone, 
          AvgRating = s.Average(a => Convert.ToDecimal(a.Rating.RatingValue)), 
          NbrOfPeopleRating = s.Distinct().Count(c => Convert.ToBoolean(c.RatingId)), 
          Id = s.Key.Id 
         }).ToListAsync(); 

        return restaurants; 
       } 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 
    } 
} 

Aggiornamento avevo bisogno di fare al mio EDMX il file

<edmx:ConceptualModels> 
     <Schema Namespace="BillYeagerModel" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm"> 
     <Function Name="ParseDecimal" ReturnType="Edm.Decimal"> 
      <Parameter Name="bytevalue" Type="Edm.Byte" /> 
      <DefiningExpression> 
       cast(bytevalue as Edm.Decimal) 
      </DefiningExpression> 
     </Function> 

C Metodo # estensione che è una classe sulla radice del mio progetto - non dentro il mio EDMX

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Data.Entity; 

namespace BillYeagerDB 
{ 
    public partial class EdmxExtensionMethods : DbContext 
    { 
     [DbFunctionAttribute("BillYeagerDB", "ParseDecimal")] 
     public static Decimal ParseDecimal(byte bytevalue) 
     { 
      return Convert.ToDecimal(bytevalue); 
     } 
    } 
} 

Aggiornato query LINQ - nota n tempi di progettazione e di errori di compilazione del progetto compila con successo

namespace BillYeagerDB 
{ 
    public class BillYeagerDB 
    { 
     public async Task<List<RestaurantList>> GetRestaurantListAsync() 
     { 
      try 
      { 
       using (BillYeagerEntities DbContext = new BillYeagerEntities()) 
       { 
        DbContext.Database.Connection.Open(); 

        var restaurants = await DbContext.Restaurants.GroupBy(g => g).Select(s => 
         new RestaurantList() 
         { 
          Name = s.Key.Name, 
          City = s.Key.City, 
          Phone = s.Key.Phone, 
          AvgRating = s.Average(a => EdmxExtensionMethods.ConvertToDecimal(a.Rating.RatingValue)), 
          NbrOfPeopleRating = s.Distinct().Count(c => Convert.ToBoolean(c.RatingId)), 
          Id = s.Key.Id 
         }).ToListAsync(); 

        return restaurants; 
       } 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 
    } 
} 
+0

Si dovrebbe essere in grado di lanciare la vostra byte per un diverso tipo direttamente nella query, senza l'uso di un metodo personalizzato. Forse non dritto al doppio (non sono sicuro), ma in caso contrario, una conversione intermedia dovrebbe funzionare, forse byte -> int -> double. – hvd

+0

La tua soluzione funziona anche per me; dovresti postarlo come risposta e accettarlo in modo che possiamo votarlo! –

risposta

-1

tentativo di riscrivere il metodo di selezione per questo:

var restaurants = await DbContext.Restaurants.GroupBy(g => g).ToListAsync(); 
return restaurants.Select(s => 
    new RestaurantList() 
    { 
    Name = s.Key.Name, 
    City = s.Key.City, 
    Phone = s.Key.Phone, 
    AvgRating = s.Average(a => Convert.ToDecimal(a.Rating.RatingValue)), 
    NbrOfPeopleRating = s.Distinct().Count(c => Convert.ToBoolean(c.RatingId)), 
    Id = s.Key.Id 
    }); 
+0

-1 perché questo impone il recupero di dati che non sono interessanti e genererà eccezioni se il caricamento lento è disabilitato. – hvd

+0

Che tipo di dati non interessanti verranno prelevati dal DB in questo caso? E in quale altro modo sai per evitare le restrizioni EF sulla chiamata ai metodi .NET "non trattati"? Linq2Sql? –

+1

Tutti i dati del ristorante non proiettati verranno comunque recuperati. Saranno utilizzate query separate per recuperare "a.Rating" per ogni ristorante (o un'eccezione se un ristorante non ha una valutazione, o come menzionato se il caricamento pigro è disabilitato). Per quanto riguarda un altro modo, vedi il mio commento sulla domanda. – hvd

1

So di essere un po 'in ritardo alla parte ma a chiunque faccia una ricerca su Google:

Ho avuto questo problema e si scopre che la classe su cui DbFunctionAttribute è attivo deve avere il sa me namespace come schema edmx.

Quindi in questo caso sia modificare lo spazio dei nomi dello schema edmx a BillYeagerDB,
o modificare lo spazio dei nomi EdmxExtensionMethods a BillYeagerModel

Problemi correlati