使用实体框架我只想包含第一个子对象而不是子对象的子对象(子的子对象) [英] Use Entity framework I want to include only first children objects and not child of child(sub of sub)

本文介绍了使用实体框架我只想包含第一个子对象而不是子对象的子对象(子的子对象)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用实体框架我只想包含第一级子对象而不是子对象

Useing Entity framework I want to include an only the first level of children objects and not the children of child

我有这两个类:

public class BusinessesTBL
{
    public string ID { get; set; }
    public string FirstName { get; set; }
    public string lastName { get; set; }

    public ICollection<OffersTBL> OffersTBLs { get; set; }
}

public class OffersTBL 
{
    public int ID { get; set; }
    public string Name { get; set; }

    public int CatId { get; set; }

    public string BusinessesTBLID { get; set; }
    public virtual BusinessesTBL BusinessesTBLs { get; set; }
}

当我尝试根据 CatId 字段提供所有优惠时,我还需要返回 BusinessesTBLs,但该方法还会根据每个 BusinessesTBL obj 再次返回优惠,我的代码是:

when I try to bring all offers according to CatId field, I need to return the BusinessesTBLs also, but the method also return offers again per each BusinessesTBL obj , My code is :

public IQueryable<OffersTBL> GetOffersTBLsCat(int id)
{
    db.OffersTBLs.Include(s => s.BusinessesTBLs);
}

您可以在以下位置看到错误的结果:http://mycustom.azurewebsites.net/api/OffersApi/GetOffersTBLsCat/4

You can see the wrong result on : http://mycustom.azurewebsites.net/api/OffersApi/GetOffersTBLsCat/4

正如您所看到的,它返回每个业务对象下的所有报价,而每个报价下的业务对象都返回报价,而我只想返回带有业务对象的报价,而没有业务对象下的报价.

As you can see it return all offers under each Business object while business object under each offer, And I want only to return offers with its Business object without offer under Business obj.

有人可以帮忙吗?

推荐答案

一个反对票让我重新注意到这个答案(谢谢).我现在看到其中很大一部分是无稽之谈.

A downvote brought this answer back into my attention (thank you). I now see that a big part of it is nonsense.

果然,死循环的原因是关系修复.但是你不能阻止 EF 这样做.即使在使用AsNoTracking 时,EF 也会在在一个查询中具体化的对象中执行关系修复.因此,您使用 Include 的查询将生成完全填充的导航属性 OffersTBLsBusinessesTBLs.

Sure enough, the reason for the endless loop is relationship fixup. But you can't stop EF from doing that. Even when using AsNoTracking, EF performs relationship fixup in the objects that are materialized in one query. Thus, your query with Include will result in fully populated navigation properties OffersTBLs and BusinessesTBLs.

信息很简单:如果您不想在结果中出现这些引用循环,则必须投影到视图模型或 DTO 类,如 其他答案之一.在我看来,在进行序列化时,另一种不太有吸引力的方法是将序列化器配置为忽略引用循环.另一个不太有吸引力的替代方法是使用 AsNoTracking 单独获取对象,然后自己有选择地填充导航属性.

The message is simple: if you don't want these reference loops in your results, you have to project to a view model or DTO class, as in one of the other answers. An alternative, less attractive in my opinion, when serialization is in play, is to configure the serializer to ignore reference loops. Yet another less attractive alternative is to get the objects separately with AsNoTracking and selectively populate navigation properties yourself.

原答案:

发生这种情况是因为实体框架执行关系修复,这是当上下文中存在属于那里的对象时自动填充导航属性的过程.因此,使用循环引用,即使禁用延迟加载,您也可以无休止地向下钻取导航属性.Json 序列化程序正是这样做的(但显然它被指示处理循环引用,因此它不会陷入无限循环).

This happens because Entity Framework performs relationship fixup, which is the process that auto-populates navigation properties when the objects that belong there are present in the context. So with a circular references you could drill down navigation properties endlessly even when lazy loading is disabled. The Json serializer does exactly that (but apparently it's instructed to deal with circular references, so it isn't trapped in an endless loop).

诀窍是防止发生关系修复.关系修复依赖于上下文的 ChangeTracker,它缓存对象以跟踪它们的更改和关联.但如果没有什么可追踪的,就没有什么可修复的.您可以通过调用 AsNoTracking() 来停止跟踪:

The trick is to prevent relationship fixup from ever happing. Relationship fixup relies on the context's ChangeTracker, which caches objects to track their changes and associations. But if there's nothing to be tracked, there's nothing to fixup. You can stop tracking by calling AsNoTracking():

db.OffersTBLs.Include(s => s.BusinessesTBLs)
             .AsNoTracking()

除此之外,如果您还在上下文中禁用延迟加载(通过设置 contextConfiguration.LazyLoadingEnabled = false),您将看到仅 OffersTBL.BusinessesTBLs 填充在 Json 中字符串,并且 BusinessesTBL.OffersTBLs 是空数组.

If besides that you also disable lazy loading on the context (by setting contextConfiguration.LazyLoadingEnabled = false) you will see that only OffersTBL.BusinessesTBLs are populated in the Json string and that BusinessesTBL.OffersTBLs are empty arrays.

一个好处是 AsNoTracking() 提高了性能,因为更改跟踪器并不忙于跟踪 EF 实现的所有对象.事实上,您应该始终在断开连接的环境中使用它.

A bonus is that AsNoTracking() increases performance, because the change tracker isn't busy tracking all objects EF materializes. In fact, you should always use it in a disconnected setting.

这篇关于使用实体框架我只想包含第一个子对象而不是子对象的子对象(子的子对象)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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