【发布时间】:2014-01-12 12:02:17
【问题描述】:
我看过一些书籍(例如 Julia Lerman 首先编写实体框架代码)定义了它们的域类 (POCO),而没有初始化导航属性,例如:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Address { get; set; }
public virtual License License { get; set; }
}
其他一些书籍或工具(例如Entity Framework Power Tools)在生成POCO时会初始化该类的导航属性,例如:
public class User
{
public User()
{
this.Addresses = new IList<Address>();
this.License = new License();
}
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual License License { get; set; }
}
Q1:哪个更好?为什么?利弊?
编辑:
public class License
{
public License()
{
this.User = new User();
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
Q2:在第二种方法中,如果 `License` 类也引用了 `User` 类,则会出现堆栈溢出。这意味着我们应该有单向引用。(?)我们应该如何决定应该删除哪一个导航属性?
【问题讨论】:
-
没有堆栈溢出的风险。您不是在创建实体实例,而只是创建列表的一个实例。
-
不,您将初始化列表与初始化列表中的项目混淆了。只要你初始化list,它就是空的,没有元素。
-
在构造函数中初始化虚拟属性真的是bad bad bad。坦率地说,我很惊讶看到应该更了解的作者将此作为解决方案提出。因为首先构造对象的基础部分,所以当访问这些虚拟成员时,子类构造函数尚未运行。如果虚方法被覆盖并且它们的实现依赖于子类构造函数中的初始化,它们就会中断。 EF 通过在运行时创建子类并覆盖虚拟成员来工作。发生此问题的重大风险。
-
我一直认为在 EF 中使用虚拟成员很方便,但最终还是存在缺陷。它可能对数据库造成比开发人员预期更多的命中。当您第一次访问数据库时,最好考虑一下您要加载的内容并
.Include。 -
引用是一个实体。集合包含实体。这意味着初始化集合在业务逻辑方面没有意义:它没有定义实体之间的关联。设置参考确实如此。因此,是否或如何初始化嵌入式列表纯粹是一个偏好问题。至于“如何”,有些人更喜欢惰性初始化: private ICollection _addresses;公共虚拟 ICollection 地址 { 获取 { 返回 this._addresses ?? (this._addresses = new HashSet()); }
标签: c# entity-framework ef-code-first domain-driven-design navigation-properties