EF codefirst:我应该初始化导航属性吗?
我看过一些书(例如, 编程实体框架代码首先是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; }
}
问题2:在第二种方法中,如果License
类也引用了User
类,则将导致堆栈溢出。这意味着我们应该有一个单向引用。(?)我们如何确定应删除哪一个导航属性?
回答:
集合:没关系。
集合和引用作为导航属性之间存在明显区别。引用 是 一个实体。集合 包含 实体。这意味着初始化集合对业务逻辑而言
:它没有定义实体之间的关联。设置参考确实如此。
因此,是否初始化或初始化嵌入式列表完全是一个优先事项。
至于“如何”,有些人喜欢延迟初始化:
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
具有空的,非null 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不会覆盖它们。在您 积极
替换它们之前,它们将始终具有其初始值。更糟糕的是,您甚至可能最终将空实体保存在数据库中!
还有另一个影响: 关系 修复不会发生。关系修正是EF通过其导航属性将上下文中的所有实体连接起来的过程。当a User
和a
Licence
分别加载时,仍然User.License
会填充,反之亦然。当然,除非License
在构造函数中初始化过。对于1:n关联也是如此。如果Address
要User
在其构造函数中初始化,则User.Addresses
不会填充!
实体框架核心中的关系修正(在撰写本文时为2.1)不受构造函数中初始化的参考导航属性的影响。也就是说,当分别从数据库中提取用户和地址时,将填充导航属性。
然而,延迟加载并 没有 覆盖初始化参考导航性能。
在EF核心3中,初始化参考导航属性会阻止其Include
正常工作。
因此,总之,同样在EF-core中,在构造函数中初始化参考导航属性可能会造成麻烦。不要这样 无论如何,这没有任何意义。
以上是 EF codefirst:我应该初始化导航属性吗? 的全部内容, 来源链接: utcz.com/qa/405756.html