ICollection‹T› против List‹T› в Entity Framework

Я посмотрел всего несколько веб-трансляций, прежде чем приступил к разработке нескольких приложений Entity Framework. Я действительно не читал так много документации, и я чувствую, что сейчас страдаю за это.

Я использовал List<T> в своих классах, и это отлично сработало.

Теперь я прочитал некоторую документацию, и в ней говорится, что я должен был использовать ICollection<T>. Я перешел на это, и это даже не привело к изменению контекста модели. Это потому, что и List<T>, и ICollection<T> наследуют IEnumerable<T>, а это то, что на самом деле требуется для EF?

Однако если это так, то почему в документации EF не указано, что требуется IEnumerable<T> вместо ICollection<T>?

В любом случае, есть ли недостатки в том, что я сделал, или я должен это изменить?


person wil    schedule 05.10.2011    source источник


Ответы (4)


Entity Framework будет использовать ICollection<T>, поскольку ему необходимо поддерживать операции Add, которые не являются частью интерфейса IEnumerable<T>.

Также обратите внимание, что вы использовали ICollection<T>, вы просто представили его как реализацию List<T>. List<T> приносит с собой IList<T>, ICollection<T> и IEnumerable<T>.

Что касается вашего изменения, экспозиция через интерфейс — хороший выбор, несмотря на то, что List<T> работает. Интерфейс определяет контракт, но не реализацию. Реализация может измениться. В некоторых случаях возможной реализацией может быть, например, HashSet<T>. (Кстати, это мышление можно использовать не только для Entity Framework. Хорошей объектно-ориентированной практикой является программирование интерфейса, а не реализации. Реализации могут и будут меняться.)

person Anthony Pegram    schedule 05.10.2011
comment
Итак.... просто для того, чтобы я понял немного дальше - List наследует IList, который наследует ICollection, который наследует IEnumerable? - person wil; 05.10.2011
comment
Да, это цепь. List<T> должен реализовать каждый из этих интерфейсов (IList<T>, ICollection<T>, IEnumerable<T>) из-за иерархии наследования. Для завершения IList<T> также подбирает неуниверсальные интерфейсы IList, ICollection и IEnumerable. - person Anthony Pegram; 05.10.2011
comment
Спасибо... Некоторые функции Ixxx до сих пор ускользают от моего понимания! Однако вы поняли, что последнее, что меня раздражает, если другие Ixx наследуют IEnumerable, как это добавить к IEnumerable, если Ienumerable доступен только для чтения? ... Если это слишком сложно, не волнуйтесь, когда у меня будет немного времени, я попытаюсь зажечь отражатель! - person wil; 05.10.2011
comment
Обычные операции Linq ничего не добавляют и не изменяют, они просто фильтруют, группируют, проецируют и т. д. Последовательности только для чтения и только вперед — это все, что необходимо для поддержки этих операций. Когда у вас есть поставщик Linq, такой как Entity Framework, который занимается сохранением данных, возможность добавления является существенным преимуществом, которое требует более мощного интерфейса, который приглашает ICollection<T> на вечеринку (и этот интерфейс приносит с собой IEnumerable<T>, поэтому обычные операции Linq по-прежнему действительны). - person Anthony Pegram; 05.10.2011
comment
@AnthonyPegram: я думаю, что совершенно неправильно говорить, что все три интерфейса должны быть реализованы. Поскольку IList‹T› наследует ICollection‹T›, который наследует IEnumerable‹T›, для List‹T› достаточно просто реализовать IList‹T›. - person CJ7; 17.12.2011
comment
@CraigJ, зависит от того, что вы подразумеваете под реализацией. List‹T› должен реализовать методы и свойства каждого интерфейса. List‹T› не нужно декларировать, что он реализует эти интерфейсы (помимо только IList‹T›), так как этот факт уже транзитивно объявлен. - person Anthony Pegram; 17.12.2011
comment
Я немного опоздал на вечеринку для этого конво, но с унаследованным List‹T›, потребуется ли больше времени для каждого? Как бы быстрее определить ICollection? Если это имеет смысл? - person Christian4423; 01.09.2017

Они выбрали интерфейс, потому что он дает понятную абстракцию над магическими запросами, которые Entity Framework выполняет при использовании Linq.

Вот разница между интерфейсами:

  • IEnumerable<T> доступен только для чтения
  • Вы можете добавлять и удалять элементы в ICollection<T>
  • Вы можете сделать произвольный доступ (по индексу) к List<T>

Из них ICollection и IEnumerable хорошо сопоставляются с операциями базы данных, поскольку запросы и добавление/удаление сущностей — это то, что вы можете делать в БД.

Произвольный доступ по индексу также не отображается, поскольку вам нужно будет иметь существующий результат запроса для повторения, иначе каждый случайный доступ будет снова запрашивать базу данных. Кроме того, на что будет отображаться индекс? Номер строки? Существует не так много запросов с номерами строк, которые вы хотели бы выполнить, и это совершенно бесполезно при построении более крупных запросов. Так что просто не поддерживают.

ICollection<T> поддерживается и позволит вам как запрашивать, так и изменять данные, так что используйте это.

Причина, по которой List<T> работает с самого начала, заключается в том, что реализация EF в конечном итоге возвращает единицу. Но это в конце вашей цепочки запросов, а не в начале. Таким образом, создание ваших свойств ICollection<T> сделает более очевидным, что EF создает кучу SQL и возвращает только List<T> в конце, а не выполняет запросы для каждого уровня Linq, который вы используете.

person Merlyn Morgan-Graham    schedule 05.10.2011

ICollection отличается от IEnumerable тем, что вы действительно можете добавлять элементы в коллекцию, тогда как с IEnumerable вы не можете. Так, например, в ваших классах POCO вы хотите использовать ICollection, если хотите разрешить добавление коллекции. Сделайте ICollection виртуальной, чтобы воспользоваться отложенной загрузкой.

person Ralph Lavelle    schedule 05.10.2011
comment
Я хочу понять - те же операции (и даже больше!) можно проделать и с List‹T›. Почему ICollection‹T›? Почему не Лист‹Т›? Выглядит проще и мощнее. - person monstro; 18.10.2015
comment
List‹T› Реализует ICollection и IEnumerable. Больше операций, но с этим больше накладных расходов. - person IronAces; 25.01.2017

Хотя вопрос был опубликован много лет назад, он все еще актуален, когда кто-то ищет тот же сценарий.

Существует недавняя статья CodeProject [2015 года], в которой подробно и графически объясняется разница с примером кода. Он не ориентирован непосредственно на EF, но все же надеюсь, что он будет более полезен:

Список, IEnumerable, IQueryable, ICollection, IDictionary

person BiLaL    schedule 23.05.2015