ICollection <T> Vs List <T> en Entity Framework

114

Solo vi algunos webcasts antes de comenzar a diseñar algunas aplicaciones de Entity Framework. Realmente no leí tanta documentación y siento que estoy sufriendo por eso ahora.

Lo 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 de modelo. ¿Es esto porque ambos List<T>y 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 en IEnumerable<T>lugar de ICollection<T>?

En cualquier caso, ¿hay inconvenientes en lo que he hecho o debería cambiarlo?

wil
fuente

Respuestas:

113

Entity Framework lo usaría ICollection<T>porque necesita admitir Addoperaciones, que no forman parte de la IEnumerable<T>interfaz.

También tenga en cuenta que estaba usando ICollection<T>, simplemente lo estaba exponiendo como la List<T>implementación. List<T>trae junto con él IList<T>, ICollection<T>y IEnumerable<T>.

En cuanto a su cambio, exponer a través de la interfaz es una buena opción, a pesar de List<T>funcionar. La interfaz define el contrato pero no la implementación. La implementación podría cambiar. En algunos casos, quizás la implementación podría ser 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 hacia la implementación. Las implementaciones pueden cambiar y cambiarán).

Anthony Pegram
fuente
2
Entonces ... solo para que entienda un poco más: List hereda IList, que hereda ICollection, que hereda IEnumerable?
Wil
3
Sí, esa es la cadena. List<T>tiene que aplicar cada una de dichas interfaces ( IList<T>, ICollection<T>, IEnumerable<T>) a causa de la jerarquía de herencia. Para finalizar, IList<T>también recoge los no genéricos IList, ICollectiony IEnumerablelas interfaces.
Anthony Pegram
Gracias ... ¡Algunas de las características de Ixxx aún escapan a mi comprensión! Sin embargo, ha tenido sentido, una última cosa que me molesta, si el otro Ixx hereda IEnumerable, ¿cómo se agrega al IEnumerable si un Ienumerable es de solo lectura? ... Si es demasiado complejo, no te preocupes, cuando tenga un poco de tiempo, intentaré encender el reflector!
miércoles
10
Las operaciones normales de Linq no agregan ni mutan cosas, simplemente filtran, agrupan, proyectan, etc. Las secuencias de solo lectura y avance son todo lo que se necesita para respaldar esas operaciones. Cuando tiene un proveedor de Linq como Entity Framework que se ocupa de la persistencia de datos, la capacidad de Agregar es un beneficio sustancial que requiere una interfaz más robusta, que es lo que invita ICollection<T>a la fiesta (y esta interfaz trae consigo IEnumerable<T>, por lo que la "normal "Las operaciones de Linq siguen siendo válidas).
Anthony Pegram
@AnthonyPegram: Creo que es estrictamente incorrecto decir que se deben implementar las tres interfaces. Dado que IList <T> hereda ICollection <T> que hereda IEnumerable <T>, es suficiente que List <T> simplemente implemente IList <T>.
CJ7
51

Eligieron la interfaz que hicieron porque brinda una abstracción comprensible sobre las consultas mágicas que realiza Entity Framework cuando usa Linq.

Aquí está la diferencia entre las interfaces:

  • IEnumerable<T> es de solo lectura
  • Puede agregar y quitar elementos a un ICollection<T>
  • Puede hacer acceso aleatorio (por índice) a un List<T>

Fuera de esos, ICollectiony IEnumerablemapee bien las operaciones de la base de datos, ya que consultar y agregar / eliminar entidades son cosas que puede hacer en una base de datos.

El acceso aleatorio por índice tampoco se asigna, 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 asignaría el índice? ¿Numero de fila? No hay muchas consultas de números de fila que le gustaría hacer, y no es útil en absoluto para generar consultas más grandes. Entonces simplemente no lo apoyan.

ICollection<T> es compatible y le permitirá consultar y cambiar datos, así que úselo.

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 la cadena de consultas, no al principio. Por lo tanto, hacer sus propiedades ICollection<T>hará que sea más obvio que EF crea un montón de SQL y solo devuelve un List<T>al final, en lugar de hacer consultas para cada nivel de Linq que use.

Merlyn Morgan-Graham
fuente
8

ICollection difiere de IEnumerable en que en realidad 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 también de la carga diferida.

Ralph Lavelle
fuente
1
Quiero entender: puede hacer las mismas operaciones (¡y más!) Con List <T>. ¿Por qué ICollection <T>? ¿Por qué no List <T>? Parece más simple y más poderoso.
Monstro
List <T> Implementa ICollection e IEnumerable. Más operación pero con eso viene más gastos generales.
IronAces
4

Aunque la pregunta se publicó hace años, sigue siendo válida cuando alguien busca el mismo escenario.

Hay un artículo reciente de CodeProject [2015] que explica la diferencia con mucho detalle y representación gráfica con código de muestra . No está enfocado directamente en EF pero aún espero que sea de mayor ayuda:

List vs IEnumerable vs IQueryable vs ICollection vs IDictionary

BiLaL
fuente