как в json сериализовать отношения entity Framework многие ко многим без циклической ссылки

#linq #json #asp.net-mvc-3 #serialization #entity-framework-4

#linq #json #asp.net-mvc-3 #сериализация #entity-framework-4

Вопрос:

У меня есть 3 таблицы в моей базе данных — Conference ActivityTypes и таблица соединений ConferenceActivities . Каждая конференция может иметь ноль или много стандартных действий, и каждое действие может происходить в ноль или более конференций.

Конференция (ConferenceID, ConferenceName)

ConferenceActivities (ConferenceID,ActivityTypeID)

ActivityTypes (ActivityTypeID, ActivityTypeDesc)

Я использовал Entity framework поверх своей существующей базы данных, с помощью шаблонов .tt в приложении MVC3 я сгенерировал DbContext и объекты POCO, отметив, что он генерирует всего два объекта, ActivityType и Conference , что приятно, кажется, понимает промежуточную таблицу.

Он также добавляет набор действий в мою конференцию

  public virtual ICollection<ActivityType> ActivityTypes { get; set; }
  

И коллекция конференций для моей деятельности.

 public virtual ICollection<Conference> Conferences { get; set; }
  

Я хотел бы вернуть с помощью JSON объект, соответствующий определенной конференции.. это включает в себя ActivityTypes . Некоторые могут описать этот объект как «shaped» или «jagged», потому что в нем есть коллекция.

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

 public JsonResult GetConference(int conferenceId)
{
    Conference x = context.Conferences.Include("ActivityTypes").FirstOrDefault<Conference>(i => i.EventID == eventId);
    return Json(x, JsonRequestBehavior.AllowGet);
}
  

Похоже, что это не работает «из коробки», и я вижу много вопросов о переполнении стека, которые, похоже, связаны, но, несмотря на попытки множества разных подходов, но все они создают ошибку о рекурсии или конструкторах без параметров.. Я начинаю сомневаться, возможно ли это вообще.

Я попытался присоединить [IgnoreDataMemberAttribute] or [ScriptIgnore] к другим свойствам, чтобы остановить его, пытаясь сериализовать рекурсивные отношения (я думаю, что форма не имеет значения, но когда вы в отчаянии ..), И я все еще получаю ту же ошибку.

Я пробовал такой подход, который генерирует ошибку без параметров

     var thing = from r in context.Conferences
                select new
                {
                    r.ConferenceID,
                    r.ConferenceName,
                    ActivityTypes = new List<ActivityType>(
                        (from c in r.ActivityTypes
                         select new ActivityType()
                         {
                             ActivityTypeDesc = c.ActivityTypeDesc,
                             ActivityTypeID = c.ActivityTypeID
                         }).Cast<ActivityType>())
                };
     return Json(thing, JsonRequestBehavior.AllowGet);
  

Другим предложением было установить Lazy Loading Enabled для свойства модели значение false.. что не имело никакого значения, я все еще получаю ошибку рекурсии.

Я попытался удалить Virtual ключевое слово, которое, как я полагаю, отключает отложенную загрузку .. и пытается.Включить (..) но опять никакой радости.

Другим предложением было изменить метод доступа с public на internal , однако это не отличалось от сериализации.

Кто-то также предложил удалить коллекцию конференций из класса activityType, что на самом деле не то, что я хочу сделать .. но выполнение этого просто приводит к ошибке «Указанная схема недействительна». в любом случае.

Я использую, я полагаю, последнюю версию nuget и связанные с ней EF, строительные леса и шаблоны.

Это то, чего я пытаюсь достичь, что должно работать из коробки? Если да, то какие настройки я мог бы пропустить, и если нет, то какова наилучшая практика здесь — единственный способ, которым я знаю, что могу выполнить эту работу, — это создать объект вручную самостоятельно.

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

Ответ №1:

не передавайте свои классы моделей. создайте viewmodel с данными, необходимыми для представления, или, в вашем случае, выводом json. я вижу, где вы пытались спроецировать его в анонимный тип, но спроецируйте его в конкретную viewmodel, и он должен работать идеально.