En este caso, es importante distinguir entre IQueryable<T>
y IEnumerable<T>
. En resumen, IQueryable<T>
es procesado por un proveedor de LINQ para entregar una consulta optimizada. Durante esta transformación no se admiten todas las instrucciones C#, ya que no es posible traducirlas a una consulta específica de back-end (por ejemplo, SQL) o porque el implementador no previó la necesidad de la declaración.
En el contrato IEnumerable<T>
se ejecuta contra los objetos concretos y, por lo tanto, no se transformará. Por lo tanto, es bastante común que las construcciones, que son utilizables con IEnumerable<T>
, no se puedan usar con IQueryable<T>
y también que IQueryables<T>
respaldado por diferentes proveedores de LINQ no admitan el mismo conjunto de funciones.
Sin embargo, hay algunas soluciones (como Phil's answer) que modifican la consulta. Además, como un enfoque más general, es posible regresar a IEnumerable<T>
antes de continuar con la especificación de la consulta. Sin embargo, esto podría tener un impacto en el rendimiento, especialmente al usarlo en restricciones (por ejemplo, cláusulas where). Por el contrario, cuando se trata de transformaciones, el rendimiento alcanzado es mucho menor, a veces incluso inexistente, dependiendo de su consulta.
Así que el código anterior también podría ser reescrita como esto:
return this.ObjectContext.BranchCostDetails
.AsEnumerable()
.Where(
b => b.TarrifId == tariffId && b.Diameter == diameter
|| (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
||(!b.TarrifId.HasValue) && b.Diameter==diameter
);
NOTA: código Ths tendrá un impacto en el rendimiento más alto que Phil's answer. Sin embargo, muestra el principio.
¿Por qué? Este código compila: 'List my = new List (); var i = from m en my where! string.IsNullOrWhiteSpace (m) select m; ' –
Puede compilarse, pero Linq no lo traduce a SQL en entidades. * El método 'Boolean IsNullOrWhiteSpace (System.String)' no tiene traducción soportada a SQL. * Lo mismo aplica para IsNullOrEmpty. – Phil
Tiene sentido ... –