Сериализация Entity Framework Object с использованием Json.Net - PullRequest
8 голосов
/ 24 июня 2009

Как мне сериализовать объект каркаса сущности в JavaScript Object (JSON)? Я попытался использовать JSON.NET , но я получаю следующее исключение, когда пытаюсь его сериализовать.

Исключение: Newtonsoft.Json.JsonSerializationException, Message = "Самостоятельная ссылка"

Hitesh

Ответы [ 3 ]

7 голосов
/ 24 июня 2009

Похоже, у вас та же общая проблема, что и у оригинального сериализатора DataContract, в отношении циклических ссылок. Хотя объекты, ссылающиеся друг на друга, довольно распространены среди графов объектов в памяти, такие циклические ссылки неизбежно приводят к бесконечным рекурсиям при сериализации, если сериализатор не учитывает это специально. Существует немного, если таковые имеются, установленных стандартов для работы с циклическими ссылками в распространенных недвоичных форматах сериализации (наиболее распространенными являются XML и JSON).

Microsoft решила циклическую проблему для сериализатора DataContract в .NET 3.5 SP1 с помощью семантики ref в xml. Насколько мне известно, для JSON такого не существует, возможно, именно поэтому JSON.NET мешает вам сериализовать ваш граф объектов.

Я бы удостоверился, что у вас есть только ссылки в графе объектов, которые являются односторонними, а не двусторонними (то есть только от родителя к потомку, а не от потомка к родителю.) Наиболее распространенные типы циклических ссылок. Может также случиться так, что нижестоящий дочерний элемент в конечном счете ссылается на корень графа, вызывая создание косвенного циклического графа (однако, они, как правило, встречаются гораздо реже, чем циклы родитель / потомок).

Как только вы удалите все циклические ссылки в графе объектов, вы сможете сериализовать.

4 голосов
/ 15 апреля 2012

У меня была эта проблема, и я решил ее, добавив атрибут Newtonsoft.Json.JsonIgnoreAttore к свойству, вызывающему цикл. Очевидно, что это свойство не будет сериализовано. Чтобы решить эту проблему, у меня обычно есть и внешний ссылочный идентификатор, и иностранный класс в моих сущностях. Я понимаю, что это не интуитивно (или супер отличное ОО), но это способ, рекомендованный Джулией Лерман в ее книге «Программирование Entity Framework: Code First». Я обнаружил, что это помогает сгладить некоторые проблемы с Entity Framework.

 public class SomeEntity
 {
      [JsonIgnore]
      public ForeignEntity SomeForeignEntity {get;set;}
      public Guid ForeignEntityId {get;set;}
 }

Обновление: я забыл упомянуть, что мне также нужно отключить прокси на DbContext, например:

dataContext.Configuration.ProxyCreationEnabled = false;

Если вы пишете код для службы (что, вероятно, при сериализации), то это, вероятно, не проблема, но есть некоторые вещи, которые вы теряете, когда создание прокси отключено. Смотрите здесь: http://www.sellsbrothers.com/posts/Details/12665 для более подробной информации.

Я использую MS Web Api, поэтому я просто отключаю создание прокси при создании контроллера:

public class MailingApiController : ApiController
{
    public MailingApiController()
    {
        PreventDeepSerialization();
    }

    private static void PreventDeepSerialization()
    {
        var dataContext = Injector.Get<IIntertwyneDbContext>();
        dataContext.Configuration.ProxyCreationEnabled = false;
    }
      ....
1 голос
/ 07 сентября 2012

Чтобы обойти это, я сначала преобразовал свои сущности в код на основе POCO. Для этого щелкните правой кнопкой мыши в окне edmx и выберите:

Добавить элемент генерации кода> вкладка Код> EF POCO Entity Generator.

Обратите внимание, что вам может потребоваться установить его с помощью nuget, если вы его не видите.

Однако во время выполнения EF добавляет прокси-классы к этим объектам для целей отслеживания, но они, как правило, портят процесс сериализации. Чтобы предотвратить это, мы можем просто установить ProxyCreationEnabled в false следующим образом:

var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;

var results = context.YourEntity.Take(100).ToList();

Затем можно безопасно возвращать сериализованные данные JSON.NET, пропустив цикл ссылок по умолчанию следующим образом:

return JsonConvert.SerializeObject(results, Formatting.Indented, 
    new jsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...