【发布时间】:2012-11-19 11:48:02
【问题描述】:
我是 Entity Framework 的新手,正在尝试学习如何使用 Code First 从数据库中加载实体。
我的模型包含一个用户:
public class User
{
public int UserID { get; set; }
[Required]
public string Name { get; set; }
// Navigation Properties
public virtual ICollection<AuditEntry> AuditEntries { get; set; }
}
每个用户都可以有一组审计条目,每个条目都包含一条简单的消息:
public class AuditEntry
{
public int AuditEntryID { get; set; }
[Required]
public string Message { get; set; }
// Navigation Properties
public int UserID { get; set; }
public virtual User User { get; set; }
}
我有一个只公开两个表的 DBContext:
public DbSet<User> Users { get; set; }
public DbSet<AuditEntry> AuditEntries { get; set; }
我要做的是加载包含消息的 AuditEntry 对象列表以及包含 UserID 和 Name 属性的相关 User 对象。
List<AuditEntry> auditEntries = db.AuditEntries.ToList();
因为我将导航属性标记为虚拟并且我没有禁用延迟加载,所以我得到了一个无限深的对象图(每个 AuditEntry 都有一个 User 对象,其中包含 AuditEntries 的列表,每个都包含一个 User对象,其中包含 AuditEntries 列表等)
如果我想序列化对象(例如在 Web API 中作为结果发送),那就不好了。
我尝试关闭延迟加载(通过从模型中的导航属性中删除虚拟关键字,或者将 this.Configuration.LazyLoadingEnabled = false; 添加到我的 DBContext)。正如预期的那样,这会生成一个包含 User 设置为 null 的 AuditEntry 对象的平面列表。
关闭延迟加载后,我尝试像这样急切加载用户:
var auditentries = db.AuditEntries.Include(a => a.User);
但这会导致与以前相同的深度/循环结果。
如何在不将反向引用/跟随导航属性加载回原始对象并创建循环的情况下加载一层深度(例如,包括用户的 ID 和名称)?
【问题讨论】:
-
Include应该这样做。你确定User.AuditEntries不是懒加载吗? -
如果在上下文被释放后序列化对象呢?
-
一开始我也这么认为,但我不认为这是延迟加载——从我的所有导航属性中删除虚拟关键字并明确禁用延迟加载似乎没有帮助。我认为这是因为我有双向的导航属性,例如用户有一个 AuditEntries 列表,AuditEntries 定义了它所属的用户。我想查询 AuditEntries 并包含用户信息,但我不希望每个顶级 AuditEntry 对象都包含该用户的所有其他 AuditEntries 的列表。这很棘手,因为我什至难以描述发生了什么!
-
我上传了一张图片,希望能更清楚地显示我的问题:s11.postimage.org/ar61ybyf7/EF_Question.png 所有相关代码都在左边(我已经从导航属性中排除了虚拟关键字以确保没有任何东西被延迟加载)。红色框突出显示了我不满意的不必要数据。谢谢
-
好的,但是,当上下文被释放时你会序列化吗?
标签: entity-framework