转换为JSON时.net circularReferenceException。如何限制引用?

时间:2015-10-20 12:35:13

标签: c# json jsonserializer

我有两个模型类,地址和产品,它们在数据库中处于多对多关系。

当我尝试使用Include()加载地址以获取产品时,当我尝试将其转换为JSON时,我得到一个circularReferenceException。这很有道理,JSON会变得无限长。

我知道,我可以通过将[ScriptIgnore]置于一个引用列表之上来解决此问题。

但是这会导致一个新问题:我需要在两个方向上解决关系,并根据情况将它们放入JSON中。我的意思是,根据具体情况,我需要产品和引用的地址,我需要在其他地方寻找他们的产品参考;

以下是我的课程(缩短):

public class Product
{

    ...

    [ScriptIgnore]
    public List<Address> Addresses { get; set; }
}

地址类:

   public class Address
{
    ....

    public List<Product> Products { get; set; }

    ...
}

获取数据:

        public JsonResult GetAllOrders()
    {
        EFDbContext context = new EFDbContext();
        return Json(context.Addresses.Include(a => a.Products).ToList(), JsonRequestBehavior.AllowGet);
    }

有没有办法告诉序列化器哪些引用忽略哪些引用?在上述情况下,我希望尊重Address-&gt; Product引用,但忽略其子代中的Product-&gt; Address。

我想到的唯一解决方案是遍历每个地址及其产品并删除引用。但我希望有更优雅的方式。

2 个答案:

答案 0 :(得分:0)

您需要浏览一个没有循环引用的新对象。例如:

public static object ToAnonymousType(this Address address)
{
    var products = address.Products.Select(p => p.ToAnonymousType());
    return new { Id = address.Id, Products=products };
}

public static object ToAnonymousType(this Product product)
{
    return new { Id = product.Id };
}

public JsonResult GetAllOrders()
{
    using(var context = new EFDbContext())
    {
        var addresses = context.Addresses.Include(a => a.Products).ToList().Select(a => a.ToAnonymousType());
        return Json(addresses, JsonRequestBehavior.AllowGet);
    }
}

答案 1 :(得分:0)

在此代码中,您没有像这样定义的virtual关键字:

public virtual IList<Product> Products { get; set; }

因此,对于看起来不错的部分,请不要添加虚拟关键字。

如果您需要使用Include来加载属性,则意味着延迟加载被禁用,以防您可以尝试强制禁用它

public class EFDbContext: DbContext 
{ 
    public EFDbContext() 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
    } 
}

您还为[ScriptIgnore]属性添加了Addresses,但是如何将其添加到Products呢?

public class Address
{
    ....

    [ScriptIgnore]
    public List<Product> Products { get; set; }

    ...
}

您应该查看此链接以获取更多说明:Loading Related Entities