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


116

Je n'ai regardé que quelques webémissions avant de me lancer dans la conception de quelques applications Entity Framework. Je n'ai vraiment pas lu beaucoup de documentation et j'ai l'impression d'en souffrir maintenant.

J'utilise List<T>dans mes cours et cela a très bien fonctionné.

Maintenant, j'ai lu une documentation et il indique que j'aurais dû utiliser ICollection<T>. J'ai changé pour cela, et cela n'a même pas provoqué de changement de contexte du modèle. Est-ce parce que les deux List<T>et ICollection<T>héritent IEnumerable<T>, et c'est ce qui est réellement requis pour EF?

Cependant, si tel est le cas, pourquoi la documentation EF n'indique-t-elle pas qu'elle requiert IEnumerable<T>au lieu de ICollection<T>?

Dans tous les cas, y a-t-il des inconvénients à ce que j'ai fait ou dois-je le changer?

Réponses:


114

Entity Framework utiliserait ICollection<T>parce qu'il doit prendre en charge des Addopérations qui ne font pas partie de l' IEnumerable<T>interface.

Notez également que vous étiez utilisez ICollection<T>, vous simplement l' exposer comme la List<T>mise en œuvre. List<T>apporte avec elle IList<T>, ICollection<T>et IEnumerable<T>.

Quant à votre changement, exposer via l'interface est un bon choix, malgré le List<T>travail. L'interface définit le contrat mais pas l'implémentation. La mise en œuvre pourrait changer. Dans certains cas, la mise en œuvre pourrait peut-être être un HashSet<T>, par exemple. (C'est un état d'esprit que vous pourriez utiliser pour plus que Entity Framework, au fait. Une bonne pratique orientée objet consiste à programmer vers l'interface et non vers l'implémentation. Les implémentations peuvent changer et vont changer.)


2
Alors ... juste pour que je comprenne un peu plus - List hérite de IList, qui hérite de ICollection, qui hérite de IEnumerable?
wil

3
Oui, c'est la chaîne. List<T>doit mettre en oeuvre chacune de ces interfaces ( IList<T>, ICollection<T>, IEnumerable<T>) en raison de la hiérarchie d'héritage. Pour la fin, IList<T>reprend aussi les non génériques IList, ICollectionet les IEnumerableinterfaces.
Anthony Pegram

Merci ... Certaines des fonctionnalités Ixxx échappent encore à ma compréhension! Vous avez cependant fait sens, une dernière chose qui m'ennuie, si les autres Ixx héritent de IEnumerable, comment cela s'ajoute-t-il au IEnumerable si un Ienumerable est en lecture seule? ... Si c'est trop complexe, ne vous inquiétez pas, quand j'aurai un peu de temps, j'essaierai d'allumer le réflecteur!
wil

10
Les opérations Linq normales n'ajoutent pas ou ne modifient pas les choses, elles filtrent simplement, groupent, projettent, etc. Des séquences en avant uniquement et en lecture seule sont tout ce qui est nécessaire pour prendre en charge ces opérations. Lorsque vous avez un fournisseur Linq tel qu'Entity Framework qui traite la persistance des données, la possibilité d'ajouter est un avantage substantiel qui nécessite une interface plus robuste, ce qui invite ICollection<T>à la fête (et cette interface apporte avec elle IEnumerable<T>, donc le "normal "Les opérations Linq sont toujours valides).
Anthony Pegram

@AnthonyPegram: Je pense qu'il est strictement incorrect de dire que les trois interfaces doivent être implémentées. Puisque IList <T> hérite de ICollection <T> qui hérite de IEnumerable <T>, il suffit que List <T> implémente simplement IList <T>.
CJ7

51

Ils ont choisi l'interface qu'ils ont créée car elle donne une abstraction compréhensible sur les requêtes magiques que Entity Framework effectue lorsque vous utilisez Linq.

Voici la différence entre les interfaces:

  • IEnumerable<T> est en lecture seule
  • Vous pouvez ajouter et supprimer des éléments à un ICollection<T>
  • Vous pouvez faire un accès aléatoire (par index) à un List<T>

Hors de ceux-ci, ICollectionet IEnumerablemappez bien aux opérations de base de données, car l'interrogation et l'ajout / la suppression d'entités sont des choses que vous pouvez faire dans une base de données.

L'accès aléatoire par index ne mappe pas non plus, car vous devez avoir un résultat de requête existant pour itérer, ou chaque accès aléatoire interrogerait à nouveau la base de données. De plus, à quoi correspondrait l'index? Numéro de ligne? Il n'y a pas beaucoup de requêtes de numéro de ligne que vous voudriez faire, et ce n'est pas du tout utile pour créer des requêtes plus volumineuses. Donc, ils ne l'appuient tout simplement pas.

ICollection<T> est pris en charge et vous permettra à la fois d'interroger et de modifier des données, alors utilisez-le.

La raison List<T>fonctionne pour commencer est que l'implémentation EF finit par en renvoyer une à la fin. Mais c'est à la fin de votre chaîne de requêtes, pas au début. Ainsi, en rendant vos propriétés, il ICollection<T>sera plus évident que l'EF crée un tas de SQL et ne renvoie qu'un List<T>à la fin, plutôt que de faire des requêtes pour chaque niveau de Linq que vous utilisez.


8

ICollection diffère de IEnumerable en ce que vous pouvez réellement ajouter des éléments à la collection, alors qu'avec IEnumerable, vous ne pouvez pas. Ainsi, dans vos classes POCO, par exemple, vous souhaitez utiliser ICollection si vous avez l'intention d'autoriser l'ajout de la collection. Rendez l'ICollection virtuelle pour bénéficier également du chargement différé.


1
Je veux comprendre - vous pouvez faire les mêmes opérations (et plus encore!) Avec List <T>. Pourquoi ICollection <T>? Pourquoi ne pas List <T>? Ça a l'air plus simple et plus puissant.
monstro

List <T> Implémente ICollection et IEnumerable. Plus d'opération mais avec cela vient plus de frais généraux.
IronAces

4

Bien que la question ait été postée il y a des années, elle est toujours valable lorsque quelqu'un cherche le même scénario.

Il existe un article récent [2015] CodeProject qui explique la différence en termes de détails et de représentation graphique avec un exemple de code . Il ne se concentre pas directement sur EF mais espère toujours qu'il sera d'une plus grande aide:

List vs IEnumerable vs IQueryable vs ICollection vs IDictionary

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.