c# - ICollection<T> Vs List<T> en Entity Framework
ienumerable vs ilist (4)
Aunque la pregunta se publicó hace años, sigue siendo válida cuando alguien está buscando el mismo escenario.
Hay un artículo reciente [2015] CodeProject que explica la diferencia en muchos detalles y la representación gráfica con código de muestra . No se enfoca directamente en EF, pero aún así espero que sea de mayor ayuda:
Lista vs IEnumerable vs IQueryable vs ICollection vs IDictionary
Solo vi algunos webcasts antes de adentrarme en el diseño de algunas aplicaciones de Entity Framework. Realmente no leí tanta documentación y ahora siento que estoy sufriendo por eso.
He estado usando List<T>
en mis clases, y ha funcionado muy bien.
Ahora he leído algo de documentación y dice que debería haber estado usando ICollection<T>
. Cambié a esto, y ni siquiera causó un cambio de contexto modelo. ¿Esto es porque tanto List<T>
como ICollection<T>
heredan IEnumerable<T>
, y eso es lo que realmente se requiere para EF?
Sin embargo, si este es el caso, ¿por qué la documentación de EF no indica que requiere IEnumerable<T>
lugar de ICollection<T>
?
En cualquier caso, ¿hay algún inconveniente en lo que he hecho o debería cambiarlo?
Entity Framework usaría ICollection<T>
porque necesita admitir operaciones Add
, que no son parte de la IEnumerable<T>
.
También tenga en cuenta que estaba usando ICollection<T>
, simplemente lo estaba exponiendo como la implementación List<T>
. List<T>
trae consigo IList<T>
, ICollection<T>
e IEnumerable<T>
.
En cuanto a su cambio, exponer a través de la interfaz es una buena opción, a pesar de que List<T>
funciona. La interfaz define el contrato pero no la implementación. La implementación podría cambiar. En algunos casos, tal vez la implementación podría ser un HashSet<T>
, por ejemplo. (Por cierto, esta es una mentalidad que podría usar para algo más que Entity Framework. Una buena práctica orientada a objetos es programar hacia la interfaz y no la implementación. Las implementaciones pueden cambiar y lo harán).
Escogieron la interfaz que hicieron porque ofrece una abstracción comprensible sobre las consultas mágicas que realiza Entity Framework cuando utiliza Linq.
Aquí está la diferencia entre las interfaces:
-
IEnumerable<T>
es de solo lectura - Puede agregar y eliminar elementos a un
ICollection<T>
- Puede hacer acceso aleatorio (por índice) a una
List<T>
De ellos, ICollection
e IEnumerable
correlacionan bien con las operaciones de la base de datos, ya que consultar y agregar / eliminar entidades son cosas que podrías hacer en un DB.
El acceso aleatorio por índice tampoco se correlaciona, ya que tendría que tener un resultado de consulta existente para iterar, o cada acceso aleatorio volvería a consultar la base de datos. Además, ¿a qué se referiría el índice? ¿Numero de fila? No hay muchas consultas de número de fila que desee hacer, y no es útil en absoluto para generar consultas más grandes. Entonces simplemente no lo admiten.
ICollection<T>
es compatible, y le permitirá consultar y cambiar datos, así que use eso.
La razón por la que List<T>
funciona para empezar es porque la implementación de EF termina devolviendo una al final. Pero eso está al final de su cadena de consultas, no al principio. Entonces, crear sus propiedades ICollection<T>
hará que sea más obvio que el EF crea un montón de SQL y solo devuelve una List<T>
al final, en lugar de hacer consultas para cada nivel de Linq que use.
ICollection difiere de IEnumerable en que realmente puede agregar elementos a la colección, mientras que con IEnumerable no puede. Entonces, en sus clases de POCO, por ejemplo, desea usar ICollection si tiene la intención de permitir que se agregue la colección. Haga que ICollection sea virtual para beneficiarse de la carga diferida también.