Saltar al contenido

No se puede convertir implícitamente el tipo ‘System.Linq.IQueryable’ a ‘System.Data.Entity.DbSet’

La guía o código que encontrarás en este post es la solución más fácil y válida que encontramos a tus dudas o problema.

Solución:

La razón por la cual el primer escenario no funciona es que el System.Linq.IQueryable es una interfaz que es implementada, entre otros, por el System.Data.Entity.DbSet clase. En C#, si la clase C interfaz de implementos Icuando se trata de transiciones entre tipos, también puede tratar I como Cla clase base de (incluso la semántica class C : I sugerir tal enfoque). Y dado que no puede implícitamente (es decir, no detalladamente) convertir una clase (o interfaz) a una de sus clases descendientes, obtiene un error de tiempo de compilación cuando intenta hacerlo. Puede hacer lo contrario, es decir, convertir implícitamente una clase descendiente en su clase base (o interfaz). Eso es exactamente lo que sucede en el segundo escenario.

En su caso, podría engañar al compilador emitiendo explícitamente:

query = (DbSet) query.Where(p => p.Id == id);

pero yo podria fuertemente le aconsejo que no lo haga ya que terminará con una excepción desordenada, porque el resultado de query.Where(p => p.Id == id) no es de hecho un ejemplo de DbSetsino alguna clase que representa el resultado de una consulta realizada en un DbSetque implementa la IQueryable interfaz.

Entonces, para resumir, repasemos todos los escenarios:

Escenario 1:

//query is of type DbSet
var query = _db.Products; 
if (bool) 
  //here you're trying to assign a value of type IQueryable
  //to a variable of it's descendant type DbSet
  //hence the compile-time error
  query = query.Where(p => p.Id == id); 

Escenario 2:

//here you implicitly cast value of type DbSet
//to IQueryable, which is OK
IQueryable query = _db.Products; 
if (bool) 
  //here you're assigning a value of type IQueryable
  //to a variable of the same type, which is also OK
  query = query.Where(p => p.Id == id); 

Escenario 3:

//I assume you have the following line in your code
var products = _db.Products;
//query is of type IQueryable, because you perform
//a query on the DbSet
var query = from product in products
            select product;
if (bool) 
  //here you're assigning a value of type IQueryable
  //to a variable of the same type, which is OK
  query = query.Where(p => p.Id == id); 

EDITAR

Ha pasado un tiempo desde que respondí esta pregunta, y aunque el mérito sigue en pie, tiendo a usar un enfoque ligeramente diferente (que podría no haber estado disponible en el momento de la respuesta original, no estoy seguro).

La forma más simple (y creo que la más segura) de lanzar un objeto implementando IQueryable para IQueryable Es esto:

var query = _db.Products.AsQueryable();

Esto simplemente devuelve el asunto de la llamada a su IQueryable implementación de la interfaz. No debería producir ninguna sobrecarga al ejecutar la consulta. Ahora, hay comentarios que sugieren usar algunos trucos, que creo que podrían ser una mala idea.

Un ejemplo de tal truco es usar esto:

var queryable = query.Select(x => x);

Si bien es (casi) completamente benigno cuando se consultan objetos, puede causar algún daño cuando se trata de algunas implementaciones de IQueryable. Es decir, cuando la consulta se traduce, por ejemplo, a una consulta SQL, lo más probable es que agregue una "SELECT * FROM ..." a la consulta ejecutada. Ese es el mejor de los casos: en el escenario más probable, agregará algo mucho más tedioso, algo como "SELECT x.P1, x.P2, ... FROM ... AS x". Por supuesto, puede estar de acuerdo con eso, pero debe ser consciente de ello. Consciente del hecho de que, según la implementación, las llamadas como esa pueden no ser “gratuitas”, aunque parezca que no hacen nada.

Otro ejemplo:

query.Where(x => true)

potencialmente agregará un WHERE 1=1 a su consulta SQL.

Cuando usas var el compilador infiere el tipo de la expresión a la derecha de la asignación. Cuando escribes

var query = _db.Products;

query es de tipo DbSety no se le puede asignar ninguna IQueryableque la Where método de extensión devuelve.

Cuando usó la sintaxis de consulta, query estaba de nuevo IQueryable, lo que hizo que funcionara. es equivalente a escribir

var query = products.Select(t => t);

los Select método de extensión, como Wheredevoluciones IQueryable.

Aquí puedes ver las reseñas y valoraciones de los lectores

Si estás de acuerdo, tienes la opción de dejar un enunciado acerca de qué te ha gustado de este ensayo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *