如何防止 EF7 急于修复导航属性? [英] How can I prevent EF7 from eagerly fixing up navigation properties?

查看:16
本文介绍了如何防止 EF7 急于修复导航属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Web 应用程序中使用 EF7 时遇到问题,我可以借助该应用程序获得一些帮助.我目前使用的是 EF7 RC1.

I have an issue using EF7 in a web application with which I could use some help. I'm currently using EF7 RC1.

这里有一些模型可以说明我的问题.

Here are some models that illustrate my problem.

联系方式

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

    public string Desc { get; set; }
    public ContactType ContactType { get; set; }
}

联系人类型

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

    public ICollection<Contact> Contacts { get; set; }
}

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

These models are related via Fluent API like this:

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

     entity
        .HasOne(c => c.ContactType)
        .WithMany(ct => ct.Contacts)
        .IsRequired();                
});

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

My needs are to be able to retrieve a collection of Contact entities from the database with their ContactType property loaded. EF makes this quite easy:

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 的 Contacts 和指向 Contacts 的 ContactTypes.我理解为什么这是默认行为并且它在许多情况下很有用,但我需要将这些实体序列化为 JSON 并将它们发送给客户端 - 这是一种只读情况.

The issue is that in loading the ContactType properties of the Contact entities (which happens due to the call to .Include() in the query), EF also helpfully loads the Contacts property of each ContactType entity, resulting in an infinite chain of Contacts pointing at ContactTypes and ContactTypes pointing at Contacts. I understand why this is the default behavior and that it's helpful in many cases, but my needs are to serialize these entities to JSON and send them down to the client - it's a read-only situation.

我想要的行为是让 EF 返回一组带有已加载(非空)ContactType 属性的联系人,这些属性的 Contacts 属性设置为 null.这是EF可以做的吗?有没有什么方法可以结束我想要的对象图,而不是手动将我不想填充的属性清空?

我尝试过的事情:

  • 将 .AsNoTracking() 附加到 EF 查询(这似乎并没有停止正在加载的 ContactType 实体的 Contacts 属性)
  • 告诉 Json.NET 不要序列化无限引用循环(这是需要在序列化过程中避免无限递归,但仍然导致大量额外数据被序列化)

推荐答案

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

You can't avoid EF to load ContactType.Contacts collection, as it's not actually loading it but filling the collection with the loaded Contact instances. This is why using AsNoTracking has no efect, because is not a problem of lazy loading nor ChangeTracker.

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

You have three possible solutions:

  1. 使用 Json.NET ReferenceLoopHandling = ReferenceLoopHandling.Ignore,但正如您所说,它会生成大量不必要的数据,因为您将获得每个 ContactType 的联系人集合
  2. 在 ContactType.Contacts 上使用 [JsonIgnore] 属性,以便序列化程序忽略它.但是它总是会忽略它,不知道你在其他情况下是否需要它
  3. 定义一个 DTO,使用 Automapper 之类的东西来映射你的数据(没有联系人集合)并序列化它
  1. Use Json.NET ReferenceLoopHandling = ReferenceLoopHandling.Ignore, but as you stated it will generate lot of unnecesary data, as you will get the collection of Contacts for every ContactType
  2. Use [JsonIgnore] attribute on ContactType.Contacts so it will be ignored by the serializer. But it will ignore it always, I don't know if you need it in other situations
  3. Define a DTO, use something like Automapper to map your data in it (without Contacts collection) and serialize it

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

I would prefer the 3rd option as I don't like sending domain model objects to the client, and it avoid adding attributes to domain model not related with domain.

这篇关于如何防止 EF7 急于修复导航属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆