我在教程中经常看到这种情况,导航属性为ICollection<T>。

这是实体框架的强制性要求吗?我可以使用IEnumerable吗?

使用ICollection而不是IEnumerable或List<T>的主要目的是什么?


当前回答

回复你关于List<T>的问题:

List<T>是一个类;指定接口可以使实现更加灵活。一个更好的问题是“为什么不IList<T>?”

要回答这个问题,请考虑IList<T>向ICollection<T>:整数索引添加了什么,这意味着项具有某种任意顺序,并且可以通过引用该顺序来检索。这在大多数情况下可能没有意义,因为项目可能需要在不同的上下文中以不同的顺序排列。

其他回答

导航属性通常被定义为虚拟的,这样它们就可以利用某些实体框架的功能,比如延迟加载。

如果一个导航属性可以保存多个实体(如在多对多或一对多关系中),那么它的类型必须是一个列表,其中可以添加、删除和更新条目,例如ICollection。

https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application

What I have done in the past is declare my inner class collections using IList<Class>, ICollection<Class>or IEnumerable<Class> (if static list) depending on whether or not I will have to do any number of the following in a method in my repository: enumerate, sort/order or modify. When I just need to enumerate (and maybe sort) over objects then I create a temp List<Class>to work with the collection within an IEnumerable method. I think this practice would only be effective if the collection is relatively small, but it may be good practice in general, idk. Please correct me if there is evidence as to why this would not good practice.

回复你关于List<T>的问题:

List<T>是一个类;指定接口可以使实现更加灵活。一个更好的问题是“为什么不IList<T>?”

要回答这个问题,请考虑IList<T>向ICollection<T>:整数索引添加了什么,这意味着项具有某种任意顺序,并且可以通过引用该顺序来检索。这在大多数情况下可能没有意义,因为项目可能需要在不同的上下文中以不同的顺序排列。

ICollection和IEnumerable之间有一些基本的区别

IEnumerable -仅包含获取枚举器的GetEnumerator方法,并允许循环 ICollection包含其他方法:添加,删除,包含,计数,CopyTo ICollection继承自IEnumerable 使用ICollection,您可以使用添加/删除等方法修改集合。你不能自由地对IEnumerable做同样的事情。

简单的程序:

using System;
using System.Collections;
using System.Collections.Generic;

namespace StackDemo
{
    class Program 
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>();
            persons.Add(new Person("John",30));
            persons.Add(new Person("Jack", 27));

            ICollection<Person> personCollection = persons;
            IEnumerable<Person> personEnumeration = persons;

            // IEnumeration
            // IEnumration Contains only GetEnumerator method to get Enumerator and make a looping
            foreach (Person p in personEnumeration)
            {                                   
               Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);
            }

            // ICollection
            // ICollection Add/Remove/Contains/Count/CopyTo
            // ICollection is inherited from IEnumerable
            personCollection.Add(new Person("Tim", 10));

            foreach (Person p in personCollection)
            {
                Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);        
            }
            Console.ReadLine();

        }
    }

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
}

Usually what you choose will depend on which methods you need access to. In general - IEnumerable<> (MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx) for a list of objects that only needs to be iterated through, ICollection<> (MSDN: http://msdn.microsoft.com/en-us/library/92t2ye13.aspx) for a list of objects that needs to be iterated through and modified, List<> for a list of objects that needs to be iterated through, modified, sorted, etc (See here for a full list: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx).

从更具体的角度来看,延迟加载用于选择类型。默认情况下,实体框架中的导航属性带有更改跟踪,并且是代理。为了将动态代理创建为导航属性,虚拟类型必须实现ICollection。

表示关系的“多”端的导航属性必须返回实现ICollection的类型,其中T是关系另一端对象的类型。- POCO代理msdn创建要求

关于定义和管理关系的更多信息