2009-09-02 14 views
29

que estoy tratando de hacer una consulta como así ...sintaxis de LINQ en valor de cadena no es nulo o vacío

query.Where(x => !string.IsNullOrEmpty(x.PropertyName)); 

pero falla ...

así que por ahora han puesto en práctica la siguiente, que funciona ...

query.Where(x => (x.PropertyName ?? string.Empty) != string.Empty); 

hay una manera mejor (más nativa?) que se encarga de esta LINQ?

EDITAR

disculpas! no incluyó el proveedor ... Esto está utilizando LINQ to SQL

+0

¿Qué proveedor LINQ? SQL, Entity, Object, ...? –

+0

Supongo que su proveedor LINQ no admite String.IsNullOrEmpty() que causa una NotSupportedException. –

+0

¿Puedes explicar por qué falla? Qué valores están obteniendo que no esperas alcanzar. No veo nada malo con este código en particular (o lo que lo diferenciaría del segundo ejemplo). – JaredPar

Respuesta

37

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=367077

Planteamiento del problema
Es posible escribir LINQ a SQL que obtiene todas las filas que tienen ya sea nulo o una cadena vacía en un campo determinado, pero no es posible utilizar String.IsNullOrEmpty hacer esto, a pesar de que muchos otros métodos de cadena mapean a LINQ to SQL. Solución propuesta Permitir String.IsNullOrEmpty en una LINQ to SQL en la cláusula de manera que estas dos consultas tienen el mismo resultado:

var fieldNullOrEmpty = 
from item in db.SomeTable 
where item.SomeField == null || item.SomeField.Equals(string.Empty) 
select item; 

var fieldNullOrEmpty2 = 
from item in db.SomeTable 
where string.IsNullOrEmpty(item.SomeField) 
select item; 

otra lectura:
1. DevArt
2. Dervalp.com
3.StackOverflow Post

2

Esto funcionará bien con Linq to Objects. Sin embargo, algunos proveedores LINQ tienen dificultades para ejecutar métodos CLR como parte de la consulta. Esto es especialmente cierto para algunos proveedores de bases de datos.

El problema es que los proveedores de DB intentan mover y compilar la consulta LINQ como una consulta de base de datos, para evitar tirar de todos los objetos a través del cable. Esto es algo bueno, pero ocasionalmente restringe la flexibilidad en sus predicados.

Desafortunadamente, sin consultar la documentación del proveedor, es difícil saber siempre exactamente qué se admitirá o no en el proveedor. Parece que su proveedor permite comparaciones, pero no la verificación de cadenas. Supongo que, en tu caso, este es probablemente el mejor enfoque posible. (Realmente no es tan diferente de la comprobación IsNullOrEmpty, salvo la creación de la instancia "string.Empty" para la comparación, pero eso es menor.)

14

Esto no fallará en Linq2Objects, pero fallará en Linq2SQL, por lo que supongo que estás hablando del proveedor SQL o algo similar.

La razón tiene que ver con la forma en que el proveedor de SQL maneja su expresión lambda. No lo toma como una función Func<P,T>, sino una expresión Expression<Func<P,T>>. Toma ese árbol de expresiones y lo traduce como una declaración SQL real, que envía al servidor.

El traductor sabe cómo manejar operadores básicos, pero no sabe cómo manejar métodos en objetos. No sabe que IsNullOrEmpty(x) se traduce en return x == null || x == string.empty. Eso tiene que hacerse explícitamente para que tenga lugar la traducción a SQL.

+1

Gran explicación - ¡gracias! –

Cuestiones relacionadas