循环引用和堆栈溢出异常

时间:2014-08-22 08:40:16

标签: sql-server asp.net-mvc linq

我在KundeInfo和HovedKategori之间有很多这样的关联,我已经在我的MS SQL数据库中映射了这样的: enter image description here

我已经实现了KundeInfo.HovedKategoris:

方法
public IEnumerable<KundeInfo> KundeInfos
{
    get
    {
        using (var dc = new DataClassesBSMAKSDataContext())
        {
            dc.DeferredLoadingEnabled = false;
            var kundeInfoHovedKategoris = dc.KundeInfoHovedKategoris.Where(x => x.HovedKategori_Id == Id);
            var kundeInfos = dc.KundeInfos.Where(x => kundeInfoHovedKategoris.Any(y => y.KundeInfo_Id == x.Id));

            return kundeInfos.ToList();
        }
    }
}

...和HovedKategori.KundeInfos:

public IEnumerable<HovedKategori> HovedKategoris
{
    get
    {
        using (var dc = new DataClassesBSMAKSDataContext())
        {
            var kundeInfoHovedKategoris = dc.KundeInfoHovedKategoris.Where(x => x.KundeInfo_Id == Id);
            var hovedKategoris = dc.HovedKategoris.Where(x => kundeInfoHovedKategoris.Any(y => y.HovedKategori_Id == x.Id));

            return hovedKategoris.ToList();
        }
    }
}

这将从特定的HovedKategori中检索关联的KundeInfos。问题不在于序列化。当我调用ToList(),或将这些对象序列化为JSON时,linq将首先尝试跟随HovedKategori.KundeInfos返回的所有引用,如果它是我首先调用的那个方法,然后它将为每个返回的对象,尝试按照KundeInfo.HovedKategoris返回的所有引用,等等,直到它会抛出堆栈溢出异常。

如果我能以某种方式阻止linq使用[Ignore]属性或某些东西来跟踪某些属性,它会起作用,但我还没有找到类似的东西。

在这种情况下我该怎么办?

2 个答案:

答案 0 :(得分:1)

这部分是设计问题。你应该真正问自己的是,你是否需要在每个可能的方向上使用导航属性。例如,如果你只是添加一个Kategori ID而不是一个导航属性,你仍然可以查询你的上下文(通过使用ID),但你真的需要总是得到所有基础数​​据的所有Kategori?

如果你的属性是虚拟的,你也有延迟加载,只有你获取信息。包括它或明确引用它。

答案 1 :(得分:0)

好的 - 所以我解决了这个问题,只需将它放到相应类的方法中,它应该首先应用,因为它从数据库中检索这些实体。所以是的,部分设计问题。

虚拟无法正常工作,我考虑过使用投影和抽象类,但它会是一个大型的继承和阶级演员,它甚至不值得考虑。

public IEnumerable<KundeInfo> KundeInfos()
{

    using (var dc = new DataClassesBSMAKSDataContext())
    {
        var kundeInfoHovedKategoris = dc.KundeInfoHovedKategoris.Where(x => x.HovedKategori_Id == Id);
        var kundeInfos = dc.KundeInfos.Where(x => kundeInfoHovedKategoris.Any(y => y.KundeInfo_Id == x.Id));

        return kundeInfos.ToList();
    }
}