具有多对多关系的EF5在序列化为JSON时创建循环引用

时间:2013-06-27 10:34:39

标签: asp.net-mvc json entity-framework knockout.js

我有一个具有多对多关系的Entity Framework 5 Code First模型 即。

Public class Product
{
    public int ProductId {get;set;}
    public ICollection<Category> Categories {get;set;}
}

Public class Category
{
    public int CategoryId {get;set;}
    public ICollection<Product> Products {get;set;}
}

我正在以流利的方式创建实际关系,因此;

modelBuilder.Entity<Product>()
            .HasMany(p => p.Categories)
            .WithMany(c => c.Products)
            .Map(m =>
                {
                    m.ToTable("ProductsToCategories");
                    m.MapLeftKey("Products_ProductId");
                    m.MapRightKey("ProductCategories_ProductCategoryId");
                });

现在,当我检索我的数据时,检索产品,将产品检索为一堆类别,但每个类别中也包含一堆产品,因此它会在周围进行处理。

问题在于,当我将其序列化为JSON供前端使用时,这会造成严重破坏(我使用的是KnockOut,但这有点无关紧要)。

我试过关闭Lazy loading,当我拿到我的产品时,我使用了include;

db.Products.Include("Categories").ToList()

但是这仍然在每个类别中执行产品的递归收集。

有什么想法吗?

此致

3 个答案:

答案 0 :(得分:3)

您也可以使用业务对象而不是直接使用数据库对象。通过这种方式,您只能从侧面引用,例如:

Public class Product
{
    public int ProductId {get;set;}
    public IList<Category> Categories {get;set;}
}

Public class Category
{
    public int CategoryId {get;set;}

}

答案 1 :(得分:1)

您在产品和类别之间引用了循环。 换句话说,产品与类别和类别有关系与产品有关系。 所以,你需要做的是删除其中一个关系。

我会这样做:

var categoriesGraph = db.Categories.Include("Products").ToList();
var data = categoriesGraph.Select(c => new
{
    c.CategoryId,
    Products = c.Products.Select(p = > new {
        p.ProductId,
        CategoriesID = p.Categories.Select(c => c.CategoryId).ToArray(),
         // don't add the categories.
    }).ToArray()
}).ToArray();

我希望它有所帮助。

答案 2 :(得分:0)

你可以告诉Json.Net忽略循环引用:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

如果您想要引用现有数据,那么请查看this article

中的修订2