转换为 JSON 时出现 .net circularReferenceException。如何限制引用?
.net circularReferenceException when converting to JSON. How to Limit references?
我有两个模型 class,地址和产品,它们在数据库中处于 many-to-many 关系。
当我尝试使用 Include()
加载地址以同时获取产品时,当我尝试将其转换为 JSON 时出现 circularReferenceException。这完全有道理,JSON 会变得无限长。
我知道,我可以通过将 [ScriptIgnore]
放在一个引用列表的顶部来解决这个问题。
但这又引发了一个新的问题:我需要根据情况把两个方向的关系解析成一个JSON。我的意思是,根据情况,我需要产品和引用的地址,我需要地址和他们的产品参考;
这是我的 classes(缩写):
public class Product
{
...
[ScriptIgnore]
public List<Address> Addresses { get; set; }
}
地址class:
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->Product reference 得到尊重,但他们 children 中的 Product->Address 被忽略。
我想到的唯一解决方案是遍历每个地址及其产品并删除引用。但我希望有更优雅的方式。
您需要遍历一个没有循环引用的新对象。例如:
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);
}
}
好吧,在这段代码中,您没有像这样定义的 virtual
关键字:
public virtual IList<Product> Products { get; set; }
所以这部分看起来不错,就不要加virtual关键字了。
如果您需要使用 Include
来进行 属性 加载,这意味着延迟加载已被禁用,但以防万一您可以尝试强制禁用它
public class EFDbContext: DbContext
{
public EFDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
还有一件事是您为 Addresses
添加了 [ScriptIgnore]
属性,但是将它也添加到 Products
呢?
public class Address
{
....
[ScriptIgnore]
public List<Product> Products { get; set; }
...
}
您应该查看此 link 以获得更多解释:Loading Related Entities
我有两个模型 class,地址和产品,它们在数据库中处于 many-to-many 关系。
当我尝试使用 Include()
加载地址以同时获取产品时,当我尝试将其转换为 JSON 时出现 circularReferenceException。这完全有道理,JSON 会变得无限长。
我知道,我可以通过将 [ScriptIgnore]
放在一个引用列表的顶部来解决这个问题。
但这又引发了一个新的问题:我需要根据情况把两个方向的关系解析成一个JSON。我的意思是,根据情况,我需要产品和引用的地址,我需要地址和他们的产品参考;
这是我的 classes(缩写):
public class Product
{
...
[ScriptIgnore]
public List<Address> Addresses { get; set; }
}
地址class:
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->Product reference 得到尊重,但他们 children 中的 Product->Address 被忽略。
我想到的唯一解决方案是遍历每个地址及其产品并删除引用。但我希望有更优雅的方式。
您需要遍历一个没有循环引用的新对象。例如:
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);
}
}
好吧,在这段代码中,您没有像这样定义的 virtual
关键字:
public virtual IList<Product> Products { get; set; }
所以这部分看起来不错,就不要加virtual关键字了。
如果您需要使用 Include
来进行 属性 加载,这意味着延迟加载已被禁用,但以防万一您可以尝试强制禁用它
public class EFDbContext: DbContext
{
public EFDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
还有一件事是您为 Addresses
添加了 [ScriptIgnore]
属性,但是将它也添加到 Products
呢?
public class Address
{
....
[ScriptIgnore]
public List<Product> Products { get; set; }
...
}
您应该查看此 link 以获得更多解释:Loading Related Entities