6

Ho una domanda veloce qui. utilizzando prima il modello EF6.: LINQ to Entities non riconosce il metodo DataLength

var db = new MyEntities(GetEntityConnectionString()); 

ObjectContext objectContext = ((IObjectContextAdapter)db).ObjectContext; 
ObjectSet<DOCUMENT> objectSet = objectContext.CreateObjectSet<DOCUMENT>(); 
var results = objectSet.Where("SqlServer.DATALENGTH(it.BINARYCONTENT)>50000"); 
Assert.IsTrue(results.ToList().Count == 9); 

var results2 = objectSet.Where(doc=>System.Data.Objects.SqlClient.SqlFunctions.DataLength(doc.BINARYCONTENT)>50000); 
Assert.IsTrue(results2.ToList().Count == 9); 

var results3 = db.DOCUMENTS.Where(doc => System.Data.Objects.SqlClient.SqlFunctions.DataLength(doc.BINARYCONTENT) > 50000); 
Assert.IsTrue(results3.ToList().Count == 9); 

La prima asserzione riesce, quindi perché ottengo la seguente eccezione quando risultati2 e risultati 3 vengono eseguiti?

An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code

Additional information: LINQ to Entities does not recognize the method 'System.Nullable`1[System.Int32] DataLength(Byte[])' method, and this method cannot be translated into a store expression.

C'è un modo per ottenere il successo degli altri asseriti?

+0

E 'stata quasi una settimana ormai. Sono ancora interessato a ricevere suggerimenti, non importa quanti anni abbia questa domanda. –

risposta

8

Si scopre che la risposta è che sto usando la funzione sbagliata.

invece di

System.Data.Objects.SqlClient.SqlFunctions.DataLength 

dovrei usare

System.Data.Entity.SqlServer.SqlFunctions.DataLength 

situato all'interno EntityFramework.SqlServer.dll

+0

Sono stato ingannato anche dalla somiglianza dei namespace, grazie per aver sottolineato questa differenza ! Probabilmente mi hai salvato un paio d'ore! – Paccc

+0

Questo potrebbe anche essere semplificato in SqlFunctions.DataLength se viene importata la libreria corretta. – Joe

0

EF non sa come convertire un metodo C# in codice SQL.

Se si modifica a questo dovrebbe funzionare: (Si noti che ho aggiunto "ToList()")

var results2 = objectSet.ToList().Where(doc=>System.Data.Objects.SqlClient.SqlFunctions.DataLength(doc.BINARYCONTENT)>50000); 
Assert.IsTrue(results2.ToList().Count == 9); 

var results3 = db.DOCUMENTS.ToList().Where(doc => System.Data.Objects.SqlClient.SqlFunctions.DataLength(doc.BINARYCONTENT) > 50000); 
Assert.IsTrue(results3.ToList().Count == 9); 

Quando si dichiara una variabile come EF Query non viene effettivamente corse fino alla prima il tempo è elencato. Enumerandolo in un elenco prima di eseguire la clausola where su di esso, la condizione Where viene eseguita sugli oggetti CLR invece di EF che tenta di eseguire come parte della query db.

+0

non secondo http://stackoverflow.com/questions/19496301/how-to-get-a-byte-array-length-using-linq-to-entities anche msdn dice "Questa funzione è tradotta in una corrispondente funzione nel database "vedi http://msdn.microsoft.com/en-us/library/dd466174(v=vs.110).aspx poiché DataLength è una funzione EDM che dovrebbe tradurre in una funzione SQL. la tua risposta significa che l'intero set di dati verrebbe caricato in memoria e quindi filtrato lì. deve essere eseguito come una singola query di filtro. vedi anche: http://www.nilzorblog.com/2011/08/linq2ef-pitfall-using-length-property.html –

Problemi correlati