J'ai seulement regardé 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 le sentiment d’en souffrir pour le moment.
J'ai utilisé List<T>
dans mes cours, et cela a très bien fonctionné.
Maintenant, j'ai lu de la documentation et il est écrit que j'aurais dû utiliser ICollection<T>
. J'ai changé pour ceci, et cela n'a même pas provoqué de changement de contexte de modèle. Est-ce parce que les deux List<T>
et ICollection<T>
hériter IEnumerable<T>
, et c’est ce qui est réellement requis pour EF?
Cependant, si tel est le cas, pourquoi la documentation EF ne dit-elle pas qu'elle nécessite 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?
Entity Framework utiliserait ICollection<T>
parce qu’il doit prendre en charge les opérations Add
, qui ne font pas partie du IEnumerable<T>
interface.
Notez également que vous étiez en utilisant ICollection<T>
, vous l'exposiez simplement comme le List<T>
la mise en oeuvre. List<T>
apporte avec lui IList<T>
, ICollection<T>
, et IEnumerable<T>
.
En ce qui concerne votre changement, exposer via l'interface est un bon choix, malgré List<T>
travail. L'interface définit le contrat mais pas la mise en œuvre. La mise en œuvre pourrait changer. Dans certains cas, l’implémentation pourrait être un HashSet<T>
, par exemple. (C'est d'ailleurs un état d'esprit que vous pourriez utiliser pour autre chose que Entity Framework. Une bonne pratique orientée objet consiste à programmer en fonction de l'interface et non de la mise en œuvre. Les implémentations peuvent et vont changer.)
Ils ont choisi l'interface qu'ils ont choisie parce qu'elle donne une abstraction compréhensible par rapport aux requêtes magiques qu'Entity Framework effectue lorsque vous utilisez Linq.
Voici la différence entre les interfaces:
IEnumerable<T>
est en lecture seuleICollection<T>
List<T>
Parmi ceux-ci, ICollection
et IEnumerable
correspondent bien aux opérations de base de données, car interroger et ajouter/supprimer des entités sont des tâches que vous pourriez effectuer dans une base de données.
L'accès aléatoire par index ne correspond pas aussi bien, car vous devez disposer d'un résultat de requête existant pour effectuer une itération, ou chaque accès aléatoire interroge à nouveau la base de données. En outre, à quoi l'index correspondrait-il? Numéro de ligne? Il n'y a pas beaucoup de requêtes de numéros de rangées que vous voudriez effectuer, et cela 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 d’interroger et de modifier les données, utilisez-le.
La raison List<T>
fonctionne pour commencer car l’implémentation EF finit par en renvoyer un à la fin. Mais c'est à la fin de votre chaîne de requête, pas au début. Donc, rendant vos propriétés ICollection<T>
Il sera plus évident que l’EF crée un groupe 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.
ICollection diffère d'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 souhaitez autoriser l'ajout de la collection. Faites en sorte qu'ICollection soit virtuel pour profiter également du chargement paresseux.
Bien que la question ait été postée il y a plusieurs années, elle reste valable lorsque quelqu'un recherche le même scénario.
Un article récent [2015] de CodeProject explique la différence entre beaucoup de détails et une représentation graphique avec un exemple de code . Il ne vise pas directement EF, mais espère néanmoins que ce sera plus utile:
Liste vs IEnumerable vs IQueryable vs ICollection vs IDictionary