【问题标题】:Serializing EF relationships in ASP NET在 ASP NET 中序列化 EF 关系
【发布时间】:2018-11-03 12:54:54
【问题描述】:

我正在尝试使用以下类在 WebApi 中创建一个简单的应用程序。

AuthorBookAuthor 具有以下属性。

public class Author
{
    public int AuthorId{ get; set; }

    public string Name { get; set; }

    public virtual List<Book> Books { get; set; } 
}

Book 具有以下属性。

public class Book
{
    public int BookId{ get; set; }

    public string Title{ get; set; }

    public virtual Author Author{ get; set; } 
}

我有一个看起来像这样的数据库上下文

public class DatabaseContext : DbContext
{
    public DatabaseContext() : base("dbCon")
    {
        Database.CreateIfNotExists();
        Configuration.ProxyCreationEnabled = false;
    }

    public DbSet<Author> Authors { get; set; }

    public DbSet<Books> Books { get; set; }
}

在我看来,我正在尝试显示所有作者及其相关书籍。这是我的js 代码。

function getData() {
    $.ajax({
        url: '/api/Author',
        type: 'GET',
        dataType: 'json',
        contentType: 'application/json',
        success: function (data) {
            console.log(data);
            showData(data);
        }
    });
}

function showData(data) {
    var string = '';
    $.each(data, function (i, a) {
        string += '<h1>Question title: ' + a.Name + '</h1>';
        $.each(q.Books, function (j, b) {
            string += '<p>' + b.Title + '</p><br>';
        });
    });
    $('.divclass').html(res);
}

返回所有作者和相关书籍的控制器方法。

public List<Author> Get()
{
    return db.Authors.Include(a => a.Books).AsNoTracking().ToList();
}

当我尝试运行项目时,我的控制台中出现错误。

下面的错误说:

“System.Collections.Generic.List`1[[WebApplication1.Models.Books, WebApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]”类型的对象图包含循环,如果出现以下情况则无法序列化参考跟踪被禁用。并且异常类型是 System.Runtime.Serialization.SerializationException。

我使用代码优先迁移来为数据库做种,我知道数据库不是空的。我该如何解决?还有什么问题?

【问题讨论】:

  • 这是什么项目? “Web.Api”、“MVC”?
  • 一开始就说,是webapi :)
  • 哦,对不起,也请添加标签。
  • 不幸的是,我没有足够的经验来选择该标签。我是新用户:)
  • 检查this link

标签: javascript c# json entity-framework


【解决方案1】:

正如错误消息告诉您的,您的数据模型具有循环引用。具体来说,您的Book 类引用了Author 类,Author 引用了Book。如果您不序列化书籍的作者(您来自对象树中的作者,因此此信息不会丢失),您可以打破循环。您可以使用ScriptIgnoreAttribute

public class Book
{
    public int BookId{ get; set; }

    public string Title{ get; set; }

    [ScriptIgnore]
    public virtual Author Author{ get; set; } 
}

另一种选择是更改 JSON 序列化设置,如 this Q&A 中所述。

【讨论】:

    【解决方案2】:

    问题的一部分是实体框架的延迟加载,每当访问引用属性时,它就会出去并要求数据库提供数据。这对您自己的代码很方便,但 JSON 序列化读取每个属性。

    因此,对于每个 Author 记录,它会读取您已经请求的 Books 列表。然后,当它浏览每一本书时,它会点击每本书的Author 属性,并要求数据库提供作者信息。然后,当它遍历Author 的属性时,它会点击Books 属性并询问数据库该作者的所有书籍。这将永远重复,但它足够聪明,只需停止并抛出异常。

    因此,另一种解决此问题的方法是在您返回实体类型时禁用延迟加载。像这样的:

    public List<Author> Get()
    {
        db.Configuration.LazyLoadingEnabled = false;
        return db.Authors.Include(a => a.Books).AsNoTracking().ToList();
    }
    

    这样,它只会序列化已经从数据库下载的数据。所以在这种情况下,当它序列化每本书时,它会看到 Author 属性,看到它是 null 并继续前进。

    【讨论】:

      猜你喜欢
      • 2021-05-20
      • 2011-05-31
      • 2021-09-15
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      相关资源
      最近更新 更多