Сериализация отношений EF в ASP NET - PullRequest
0 голосов
/ 03 ноября 2018

Я пытаюсь создать простое приложение в WebApi со следующими классами.

Author и Book, Author имеет следующие атрибуты.

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 = нейтральный, PublicKeyToken = null]]' содержит циклы и не может быть сериализован, если отслеживание ссылок отключено. И тип исключения - System.Runtime.Serialization.SerializationException.

Я использую код первой миграции для заполнения базы данных, и я знаю, что база данных не пуста. Как это исправить? А что не так?

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

Частично проблема заключается в отложенной загрузке Entity Framework, когда он выходит из системы и запрашивает данные в базе данных при каждом обращении к ссылочному свойству. Это удобно для вашего собственного кода, но 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, и просто движется дальше.

0 голосов
/ 03 ноября 2018

Как говорится в сообщении об ошибке, ваша модель данных имеет циклические ссылки. В частности, ваш класс 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, как описано в в этом разделе вопросов и ответов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...