收藏:没关系。
作为导航属性,集合和引用之间存在明显的区别。参考is一个实体。一个集合contains实体。这意味着初始化集合是无意义的就业务逻辑而言:它没有定义实体之间的关联。设置参考即可。
因此,是否或如何初始化嵌入列表纯粹是一个偏好问题。
至于“如何”,有些人更喜欢延迟初始化:
private ICollection<Address> _addresses;
public virtual ICollection<Address> Addresses
{
get { return this._addresses ?? (this._addresses = new HashSet<Address>());
}
它可以防止空引用异常,因此有利于单元测试和操作集合,但它也可以防止不必要的初始化。当一个类具有相对较多的集合时,后者可能会产生影响。缺点是它需要相对较多的管道,尤其是。与没有初始化的自动属性相比。此外,C# 中空传播运算符的出现使得初始化集合属性不再那么紧迫。
...除非应用显式加载
唯一的问题是初始化集合使得很难检查实体框架是否加载了集合。如果初始化了一个集合,则像这样的语句...
var users = context.Users.ToList();
...将创建User
具有空、非空的对象Addresses
集合(除了延迟加载)。检查集合是否已加载需要类似的代码...
var user = users.First();
var isLoaded = context.Entry(user).Collection(c => c.Addresses).IsLoaded;
如果集合没有初始化一个简单的null
检查就可以了。因此,当选择性显式加载是编码实践的重要组成部分时,即......
if (/*check collection isn't loaded*/)
context.Entry(user).Collection(c => c.Addresses).Load();
...不初始化集合属性可能更方便。
参考属性: 不
引用属性是实体,因此为它们分配一个空对象是有意义的.
更糟糕的是,如果您在构造函数中启动它们,EF 在具体化对象或通过延迟加载时不会覆盖它们。它们将始终具有其初始值,直到您actively替换它们。更糟糕的是,您甚至可能最终在数据库中保存空实体!
还有另一个效果:关系修复不会发生。关系修复是 EF 通过导航属性连接上下文中所有实体的过程。当一个User
and a Licence
分别加载,仍然User.License
将被填充,反之亦然。当然,除非如果License
已在构造函数中初始化。对于 1:n 关联也是如此。如果Address
会初始化一个User
在其构造函数中,User.Addresses
不会有人居住!
实体框架核心
实体框架核心(撰写本文时为 2.1)中的关系修复不受构造函数中初始化的引用导航属性的影响。也就是说,当分别从数据库中提取用户和地址时,将填充导航属性。
然而,延迟加载确实not覆盖初始化的参考导航属性。
在 EF-core 3 中,初始化引用导航属性会阻止Include
无法正常工作。
因此,总而言之,同样在 EF-core 中,在构造函数中初始化引用导航属性可能会导致问题。不要这样做。无论如何,这没有意义。