Как я разрешил кольцевую ошибку сравнения сериализации Json?

Существует сообщение здесь, в котором спрашивается, как решить круговую опорную ошибку при возврате сериализованного объекта через EF4 CTP5. Я столкнулся с этой проблемой с проектом веб-форм WCF некоторое время назад.

Я смог "решить" эту проблему в моем проекте WCF/веб-форм и в моем проекте MVC3. Я не думаю, что это важно, какой тип проекта, как кажется, является "серией" сериализации EF.

Я решил проблему, отключив ProxyCreation в моем конструкторе ObjectContext следующим образом:

public class MyObjectContext : DbContext, IDbContext
{
     public MyObjectContext(string connectionStringName) : base(connectionStringName)
     {
        ((IObjectContextAdapter)this).ObjectContext.ContextOptions.ProxyCreationEnabled = false;
     }
     public DbSet<Product> Products {get;set;}
     //etc.
} 

Мой вопрос: может ли кто-нибудь объяснить, почему это, по-видимому, решит проблему?

Я думаю, что проблема связана с свойствами навигации в моем POCO, но после этого я в тупике. Спасибо.

Ответы

Ответ 1

Если вы отключите создание прокси, вы также отключите ленивую загрузку. Когда сериализация объекта происходит, он посещает все свойства навигации. Если включена ленивая загрузка, она загружает все связанные объекты и пытается их сериализовать. Опять же, он посещает все свои свойства, включая свойства навигации, указывающие на родительский объект. На этом этапе вы должны сказать сериализацию, что это свойство является циклическим эталоном, или оно будет сериализовать объект снова и продолжить в бесконечном цикле.

Трюк здесь может заключаться в том, чтобы аннотировать свойство круговой навигации в дочернем объекте с атрибутом ScriptIgnore.

Ответ 2

Круговая ссылка происходит, потому что вы используете активную загрузку объекта.

У вас есть несколько методов:

  • Отключить загрузку при загрузке запроса (linq или lambda)  DbContext.Configuration.ProxyCreationEnabled = false;
  • Удалить ключевое слово virtual из Domainmodel
  • Включить их при загрузке объектов
  • Отсоедините объекты (= нет загружаемых функций и прокси)
    • Repository.Detach(EntityObject)
    • DbContext.Entry(entityObject).EntityState = EntityState.Detached
  • Клонировать свойства
    • Вы можете использовать что-то вроде AutoMapper для клонирования объекта, не используйте интерфейс ICloneable, потому что он также клонирует ProxyProperties в объекте, так что это не сработает.
  • Если вы создаете API, попробуйте использовать проект separte с другой конфигурацией (которая не возвращает прокси)

PS. Proxies - это объект, созданный EF при его загрузке из Entity Framework. Короче: это означает, что он содержит исходные значения и обновленные значения, чтобы их можно было обновить позже. Он обрабатывает другие вещи: -)

Ответ 3

Быстрое примечание: если вы все еще сталкиваетесь с исключением, помните, что вы избавились от

.Include("NestedObject")

В этом случае отношения родитель-потомок исчезнут, а также исключение