Сериализация объектов EF4.1 с использованием JSON.Net

Я создаю приложение, используя MVC3, механизм просмотра Razor, шаблон репозитория с единицей работы и использую код EF4.1 Code First для определения моей модели данных.

Вот немного фон (закройте его, если хотите).

Само приложение представляет собой просто «Меню» интрасети.

Двумя основными объектами являются MenuItem и Department, из которых:

  • MenuItem может иметь много отделов
  • Departments может иметь много MenuItems
  • MenuItem может иметь MenuItem как родительский

Вот как я определил свои Entities

public class MenuItem
{
   public int MenuItemId { get; set; }
   public string Name { get; set; }
   public string Url { get; set; }
   public virtual ICollection<Department> Departments { get; set; }
   public int? ParentId { get; set; }
   public virtual MenuItem ParentMenuItem { get; set; }
}

public class Department
{
   public int DepartmentId { get; set; }
   public string Name { get; set; }
   public virtual ICollection<MenuItem> MenuItems { get; set; }
}

Я использую FluentAPI для определения Self Reference Many-to-Many для MenuItem.

Проблема, с которой я сталкиваюсь, заключается в передаче MenuItem в представление через JSON. Основные проблемы заключаются в том, что у меня есть циклическая ссылка между моими объектами, с которыми встроенный анализатор JSON не может справиться, и у меня все еще включена отложенная загрузка и создание прокси.

Я использую библиотеку JSON.net из Nuget в качестве своего JSON Сериализатор, поскольку это, кажется, хороший способ решить проблему с круговой ссылкой. Теперь я не знаю, как «исправить» проблему с генерацией прокси. В настоящее время сериализатор выдает Объект RelationshipManager не может быть сериализован. Этот тип объекта не может быть сериализован, если RelationshipManager принадлежит объекту сущности, который не реализует IEntityWithRelationships.

Кто-нибудь может мне с этим помочь? Если я отключу создание прокси, у меня будет чертовски много времени на загрузку всех дочерних элементов MenuItem, поэтому я очень хочу оставить это включенным. Я прочитал довольно много, и, похоже, есть множество разных ответов, включая проецирование сущностей в другой объект, сериализацию его и т. Д. И т. Д. В идеале можно было бы каким-то образом настроить JSON.net, чтобы игнорировать объект RelationshipManager?

Обновление

Вот то, что я использовал в качестве Custom ContractResolver для сериализатора JSON.Net. Кажется, это решило мою проблему.

public class ContractResolver : DefaultContractResolver
{
    private static readonly IEnumerable<Type> Types = GetEntityTypes();
    private static IEnumerable<Type> GetEntityTypes()
    {
        var assembly = Assembly.GetAssembly(typeof (IEntity));
        var types = assembly.GetTypes().Where(t => String.Equals(t.Namespace, "Namespace", StringComparison.Ordinal));
        return types;
    }

    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        if (!AllowType(objectType))
            return new List<MemberInfo>();

        var members = base.GetSerializableMembers(objectType);
        members.RemoveAll(memberInfo => (IsMemberEntityWrapper(memberInfo)));
        return members;
    }

    private static bool AllowType(Type objectType)
    {
        return Types.Contains(objectType) || Types.Contains(objectType.BaseType);
    }

    private static bool IsMemberEntityWrapper(MemberInfo memberInfo)
    {
        return memberInfo.Name == "_entityWrapper";
    }
}

IEntity - это интерфейс, который реализуют все мои объекты сущностей Code First.

6
задан Matt Demler 10 August 2011 в 01:28
поделиться