none
IEnumerable vs IQueryable vs List RRS feed

  • Pregunta

  • Buena tarde comunidad.

    He investigado el uso de IEnumerable e IQueryable pero a pesar de haber leído diferentes artículos no me queda claro en que situaciones debería implementarse el uno o el otro.

    Para ejemplificar mi duda mostraré algo de codigo, espero logre aclarar mi punto.

    Sin hacer uso de Entity Framework, haciendo todo a mano crearía un método como el siguiente para realizar una consulta a una tabla:

    public List<PersonaEN> ObtenerPersona()
            {
                MySqlConnection conn = null;
                try
                {
                    conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["K2"].ConnectionString);
                    //conn.Open(); --> No es necesario abrir la conexion.
                    MySqlCommand command = new MySqlCommand() { Connection = conn, CommandText = "SELECT * FROM cp_pers", CommandType = CommandType.Text };
                    MySqlDataAdapter adapter = new MySqlDataAdapter(command); //Adapta el commando a lo que necesita MySQL para interpretarlo.
                    DataTable dt = new DataTable(); //Tipo de objeto .NET
                    adapter.Fill(dt); //Fill coger lo que retorno la consulta en el adapter y se los pasa al dt.
                    listPersona = (from t in dt.AsEnumerable()
                                   select new PersonaEN()
                                   {
                                       Documento = t.Field<int>("Docum"),
                                       PrimerNombre = t.Field<string>("prnom"),
                                       SegundoNombre = t.Field<string>("sgnom"),
                                       PrimerApellido = t.Field<string>("prape"),
                                       SegundoApellido = t.Field<string>("sgape"),
                                       FechaNacimiento = t.Field<DateTime>("fechan"),
                                       Edad = t.Field<int>("edad"),
                                       CodigoDireccion = t.Field<Int32?>("codDi") ?? 0
                                   }).ToList();
                }
                catch
                {
                    throw;
                }
    
                finally
                {
                    if (conn != null && conn.State == ConnectionState.Open)
                    {
                        conn.Close();
                    }
                }
                return listPersona;
            }

    Y haciendo uso de Entity Framework tendría algo así:

    public List<PRODUCTO> ObtenerProductos()
            {
                return context.PRODUCTO.ToList();
            }

    En ambos casos retorno un List, no he tenido problema haciendo uso del List en ningún momento, sin embargo he notado que la mayoria de desarrollos mas profesionales hacen uso de IEnumerable o IQueryable, no me queda claro cual es la utilidad del uso de ellos, que ventajas tiene sobre el ToList

    miércoles, 3 de marzo de 2021 20:51

Respuestas

  • Sin embargo aun tengo dudas sobre cuando usar IQueryable e IEnumerable, cual sería la diferencia entre uno y el otro, que ventajas tienen entre sí y sobre List.

    Se trata de una jerarquía. IQueryable a su vez implementa IEnumerable. Esto significa que IQueryable tiene todo lo que tiene IEnumerable y admás algunas cosas más.

    Similarmente, List<T> también implementa IEnumerable, con lo que igualmente el List tiene todo lo que tiene IEnumerable y algunas cosas más.

    Entonces la idea es que si no tienes una necesidad concreta de hacer uso de esas "algunas cosas más", entonces deberías usar la clase o interfaz que tiene la mínima cantidad de "cosas", porque de esta manera impones las mínimas limitaciones a la función que expone dicho objeto.

    Entonces, ¿cuáles son esas "algunas cosas más"? Bueno lo mejor es acudir a la documentación y ver la lista de miembros de cada una de las clases o inerfaces.

    La principal característica del IQueryable es que permite evaluar consultas contra un proveedor de datos, mientras que el IEnumerable únicamente permite listar los elementos de una colección, sin tener control sobre cómo llegaron a esa colección. Si desde fuera de tu función no vas a usar lambdas para restringir la evaluación de la query, sino que vas a devolver el resultado ya evaluado, entonces no deberías devolver un IQueryable, sino que basta con el IEnumerable para que desde fuera de la función se puedan usar los resultados.

    Similarmente, el List te da acceso a modificar la colección, mientras que el IEnumerable solo enumera el contenido. Si no tienes necesidad de modificar el contenido desde fuera de tu función (solo lo modifica la función internamente) entonces no devuelvas un List.

    viernes, 5 de marzo de 2021 15:11
    Moderador

Todas las respuestas

  • Hola Julián,

    Con respecto a su  duda todo depende del programa o necesidad del cliente en el proyecto, básicamente si vamos a realizar filtrados dinámicos en un conjunto de datos se debe utilizar la interface IQueryable, sino sería de forma contraria, pero como mencioné todo depende del tipo de proyecto que estás realizando y las consultas que tengas que hacer, para un proyecto simple como lo que compartiste en el código esta bien hecho, pero si necesitas algo más rebusto con más consultas y filtrados dinámicos, IQueryable es lo que deberías de usar.

    Saludos,

    Eric Ruiz

    miércoles, 3 de marzo de 2021 23:18
    Moderador
  • Hola Eric, gracias por tu respuesta.

    Me gustaría entender un poco mas.

    Tengo entendido que la diferencia entre IEnumerable y IQueryable es que:

    IEnumerable<PRODUCTO> list = dbContext.PRODUCTO.Where(e=>e.Valor > 1000); -> Me traería TODOS los productos desde la BD y luego aplicaría el filtro.
    IQueryable <PRODUCTO> list = dbContext.PRODUCTO.Where(e=>e.Valor > 1000); -> Me traería los productos ya filtrados desde la BD, es decir, hace el WHERE en la BD

    Segun leí, IQueryable retrasa la ejecución del query hasta su implementación o iteración.
    Mi idea es comenzar a usar mejores practicas, desde ahora usar las herramientas adecuadas para cada ocasión.

    jueves, 4 de marzo de 2021 20:09
  • En un caso como el que propones, mi propuesta sería devolver IEnumerable desde los métodos. La idea es exponer el mínimo de funcionalidad que sea necesaria para utilizar el método desde fuera del mismo. De esa manera, tu implementación interna del método puede ser modificada cuando sea necesario sin afectar a los llamantes. Por ejemplo, Si en un momento dado cambia la tecnología de acceso a datos y resulta que usas unos "drivers" que devuelven un array de registros, puedes devolver ese array y sigue siendo un IEnumerable; todos los llamantes del método no se ven afectados, mientras que sí que habría que cambiarlos todos si sustituyeses el List por el Array en el resultado del método.
    viernes, 5 de marzo de 2021 7:45
    Moderador
  • Hola Alberto, agradezco tu respuesta.

    No había considerado ese escenario, sería una ventaja adicional al usar el IEnumerable al traer los registros en la capa de Datos y luego pasarlo al tipo de dato que necesite.

    Sin embargo aun tengo dudas sobre cuando usar IQueryable e IEnumerable, cual sería la diferencia entre uno y el otro, que ventajas tienen entre sí y sobre List.

    viernes, 5 de marzo de 2021 13:22
  • Sin embargo aun tengo dudas sobre cuando usar IQueryable e IEnumerable, cual sería la diferencia entre uno y el otro, que ventajas tienen entre sí y sobre List.

    Se trata de una jerarquía. IQueryable a su vez implementa IEnumerable. Esto significa que IQueryable tiene todo lo que tiene IEnumerable y admás algunas cosas más.

    Similarmente, List<T> también implementa IEnumerable, con lo que igualmente el List tiene todo lo que tiene IEnumerable y algunas cosas más.

    Entonces la idea es que si no tienes una necesidad concreta de hacer uso de esas "algunas cosas más", entonces deberías usar la clase o interfaz que tiene la mínima cantidad de "cosas", porque de esta manera impones las mínimas limitaciones a la función que expone dicho objeto.

    Entonces, ¿cuáles son esas "algunas cosas más"? Bueno lo mejor es acudir a la documentación y ver la lista de miembros de cada una de las clases o inerfaces.

    La principal característica del IQueryable es que permite evaluar consultas contra un proveedor de datos, mientras que el IEnumerable únicamente permite listar los elementos de una colección, sin tener control sobre cómo llegaron a esa colección. Si desde fuera de tu función no vas a usar lambdas para restringir la evaluación de la query, sino que vas a devolver el resultado ya evaluado, entonces no deberías devolver un IQueryable, sino que basta con el IEnumerable para que desde fuera de la función se puedan usar los resultados.

    Similarmente, el List te da acceso a modificar la colección, mientras que el IEnumerable solo enumera el contenido. Si no tienes necesidad de modificar el contenido desde fuera de tu función (solo lo modifica la función internamente) entonces no devuelvas un List.

    viernes, 5 de marzo de 2021 15:11
    Moderador