如何防止EF7急切地修复导航属性?

Jam*_*mer 4 entity-framework-core

我在Web应用程序中使用EF7时遇到问题,我可以使用它来帮助我.我目前正在使用EF7 RC1.

以下是一些说明我问题的模型.

联系

public class Contact
{
    public Guid Id { get; set; }

    public string Desc { get; set; }
    public ContactType ContactType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

ContactType

public class ContactType
{
    public Guid Id { get; set; }
    public string Desc { get; set; }

    public ICollection<Contact> Contacts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这些模型通过Fluent API相关,如下所示:

modelBuilder.Entity<Contact>(entity => {
     // abridged for clarity

     entity
        .HasOne(c => c.ContactType)
        .WithMany(ct => ct.Contacts)
        .IsRequired();                
});
Run Code Online (Sandbox Code Playgroud)

我的需求是能够从加载了ContactType属性的数据库中检索Contact实体的集合.EF使这很容易:

using(var context = new MyDbContext()) {
    var contacts = await context
        .Contacts
        .Include(c => c.ContactTypes)
        .Where(/* some search criteria */)
        .ToListAsync();
}
Run Code Online (Sandbox Code Playgroud)

问题是在加载Contact实体的ContactType属性时(由于在查询中调用.Include()而发生),EF还有助于加载每个ContactType实体的Contacts属性,从而导致无限的Contacts指向链指向在ContactTypes和ContactTypes指向Contacts.我理解为什么这是默认行为,并且在许多情况下它很有用,但我的需求是将这些实体序列化为JSON并将它们发送到客户端 - 这是一个只读的情况.

我希望的行为是EF返回一个Contacts的集合,其中的Contacts(非null)ContactType属性的Contacts属性设置为null.EF可以做什么?有没有办法最终得到对象图我想要手动归零我不想填充的属性?

我试过的事情:

  • 将.AsNoTracking()附加到EF查询(似乎不会阻止加载ContactType实体的Contacts属性)
  • 告诉Json.NET不要序列化无限引用循环(这是在序列化期间避免无限递归所必需的,但仍会导致大量额外数据被序列化)

ted*_*e24 5

您无法避免EF加载ContactType.Contacts集合,因为它实际上并未加载它,而是使用加载的Contact实例填充集合.这就是使用AsNoTracking没有效果的原因,因为这不是延迟加载和ChangeTracker的问题.

您有三种可能的解决方案:

  1. 使用Json.NET ReferenceLoopHandling = ReferenceLoopHandling.Ignore,但正如您所说,它将生成大量不必要的数据,因为您将获得每个ContactType的联系人集合
  2. [JsonIgnore]在ContactType.Contacts上使用属性,因此序列化程序将忽略它.但它总会忽略它,我不知道你是否需要它在其他情况下
  3. 定义DTO,使用类似Automapper的内容来映射数据(没有Contacts集合)并将其序列化

我更喜欢第3个选项,因为我不喜欢将域模型对象发送到客户端,并且它避免向与域无关的域模型添加属性.