我在Web应用程序中使用EF7时遇到问题,我可以使用它来帮助您。我目前正在使用EF7 RC1。
以下是一些说明我问题的模型。
与
public class Contact
{
public Guid Id { get; set; }
public string Desc { get; set; }
public ContactType ContactType { get; set; }
}
ContactType
public class ContactType
{
public Guid Id { get; set; }
public string Desc { get; set; }
public ICollection<Contact> Contacts { get; set; }
}
这些模型通过Fluent API相关,如下所示:
modelBuilder.Entity<Contact>(entity => {
// abridged for clarity
entity
.HasOne(c => c.ContactType)
.WithMany(ct => ct.Contacts)
.IsRequired();
});
我的需求是能够从加载了ContactType属性的数据库中检索Contact实体的集合。 EF使这很容易:
using(var context = new MyDbContext()) {
var contacts = await context
.Contacts
.Include(c => c.ContactTypes)
.Where(/* some search criteria */)
.ToListAsync();
}
问题在于,在加载Contact实体的ContactType属性时(由于在查询中调用.Include()而发生),EF还有助于加载每个ContactType实体的Contacts属性,从而产生无限链指向ContactTypes和ContactTypes指向Contacts的Contacts。我理解为什么这是默认行为,并且在许多情况下它很有用,但我的需求是将这些实体序列化为JSON并将它们发送到客户端 - 这是一个只读的情况。
我希望的行为是EF返回一个Contact集合,其中的Contacts(非null)ContactType属性的Contacts属性设置为null。 EF可以做什么?有没有办法最终得到对象图我想要手动清空我不想填充的属性?
我尝试过的事情:
答案 0 :(得分:5)
你无法避免EF加载ContactType.Contacts集合,因为它实际上没有加载它,而是用加载的Contact实例填充集合。 这就是使用AsNoTracking没有效果的原因,因为这不是延迟加载和ChangeTracker的问题。
您有三种可能的解决方案:
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
,但正如您所说,它将生成大量不必要的数据,因为您将获得每个ContactType的联系人集合[JsonIgnore]
属性,因此序列化程序将忽略它。但它总是会忽略它,我不知道你是否在其他情况下需要它我更喜欢第3个选项,因为我不喜欢将域模型对象发送到客户端,并且它避免向与域无关的域模型添加属性。