Контроллер C # EF API не загружает массив «многие ко многим»

У меня есть следующие два класса в приложении С# ASP.Net для установки кода Entity Framework.

Класс объекта;

public class Facility
{
    public int Id { get; set; }
    public string Name {get; set; }
    public ICollection<SubscriberList> SubscriberLists {get; set;}
}

Класс списка подписчиков;

Public class SubscriberList
{
    public SubscriberList()
    {
        Facilities = new HashSet<Facility>(); //not sure if I need this.
    }
    public int Id { get; set; }
    public int ClientId { get; set; }
    public ICollection<Facility> Facilities { get; set; }
}

Со следующей конфигурацией;

public class SubscriberListConfiguration : EntityTypeConfiguration<SubscriberList>
{
    public SubscriberListConfiguration()
    {
        HasMany(w => w.Facilities)
            .WithMany(s => s.SubscriberLists)
            .Map(m =>
            {
                m.ToTable("SubscriberListFacilities");
                m.MapLeftKey("SubscriberListId");
                m.MapRightKey("FacilityId");
            });
    }
}

Теперь у меня есть следующий ApiController

public List<SubscriberList> GetSubscriberLists()
{
    var list = _context.SubscriberLists
        .Include(c => c.Facilities)
        .ToList();
    return list;
 }

При вызове запроса Get в /api/SubscriberLists я получаю следующий Json, в котором отсутствует «имя объекта»

[
    {
        "Id": 2,
        "ClientId": 1000001,
        "Facilities": [
            {
                "$id": "1"
            }
        ]
    },
    {
        "Id": 3,
        "ClientId": 1000002,
        "Facilities": [
            {
                "$id": "2"
            },
            {
                "$id": "3"
            }
        ]
    }
]

Как видите, он не возвращает Facility.Name, только Facility.Id. Я попытался добавить ключевое слово virtual перед ICollection. Попытался изменить ICollection<> на IList<>, а также на List<> Также попытался добавить атрибут [JsonProperty("Facilities")] поверх поля Facilities. Также попытался повторить возвращенный список, запрашивая средства для запуска загрузки. Пока ничего не помогло.

Интересно то, что в режиме отладки я вижу, что все загружено, как и ожидалось, я вижу, что все поля Facility.Name заполнены. Я боюсь, что проблема здесь заключается в сериализаторе Json, но я понятия не имею, как это устранить.

Какой мой следующий шаг?

заранее спасибо

Изменить;

Стоит добавить. При переходе к URL-адресу API в браузере, который приводит к получению данных XML вместо Json, я получаю следующий результат в массиве Facilities.

<Facilities>
    <Facility xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" z:Id="i1"/>
</Facilities>

person Aron Einhorn    schedule 03.01.2017    source источник
comment
Вы уверены, что объект с идентификатором 4 имеет имя, отличное от «нулевого» в вашей БД?   -  person Vadim Martynov    schedule 04.01.2017
comment
@VadimMartynov Да, у Facility Id 4 (теперь 2) есть имя, но это еще более странно, что возвращаемые им числа $id на самом деле не из базы данных, а просто увеличиваются для каждого экземпляра в возвращаемых данных. (Я пропустил несколько ответов для простоты. Теперь я обновил его до 1,2 и 3)   -  person Aron Einhorn    schedule 04.01.2017
comment
Это похоже на результат сериализатора JSON, для которого ReferenceLoopHandling задано значение Ignore. У вас есть проблемы с десериализацией этого JSON?   -  person Ivan Stoev    schedule 04.01.2017
comment
@VadimMartynov на самом деле понял, что $id не представляет фактическое поле Id, возвращаемое из базы данных. Это просто заполнитель Json.PreserveReferencesHandling. Напрашивается вопрос, почему вместо реальных данных возвращается только это.   -  person Aron Einhorn    schedule 04.01.2017
comment
@IvanStoev Я добавил следующую строку в файл WebApiConfig.cs, но проблема не устранена. config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize; Это то, что вы рекомендовали, или поясните, пожалуйста.   -  person Aron Einhorn    schedule 04.01.2017
comment
В вопрос добавлена ​​версия сериализации XML.   -  person Aron Einhorn    schedule 04.01.2017


Ответы (1)


Я думаю, что ваше сопоставление немного не так, может быть, попробуйте это

modelBuilder.Entity<Facility>()
.HasMany<SubscriberList>(s => s.Facilities)
.WithMany(c => c.SubscriberLists )
.Map(cs =>
 {
   cs.MapLeftKey("FacilityId");
   cs.MapRightKey("SubscriberListId");
   cs.ToTable("SubscriberListFacilities");
});

Настроить многие ко многим отношения

person Nonik    schedule 04.01.2017
comment
Я не совсем уверен, что вы добавили в свой ответ. Единственное, что я вижу, это то, что вы начали настройку с Facility, а я начал настройку с SubscribeList. (В отношениях «многие ко многим» нет разницы, в каком классе вы выполняете настройку). Я обновил вопрос, включив в него весь класс конфигурации, чтобы вы получили полную картину. Дайте мне знать, если вы все еще видите, что я что-то пропустил из вашего ответа. Спасибо. - person Aron Einhorn; 04.01.2017
comment
Более. Я не думаю, что проблема здесь в моем отображении. База данных выглядит точно так, как ожидалось, и я получил правильные результаты с помощью обычного контроллера MVC, и я вижу правильные данные в режиме отладки при проверке локальных переменных. Единственная проблема здесь заключается в получении данных через контроллер API. - person Aron Einhorn; 04.01.2017
comment
Я вижу, в вашем случае может быть проблема с включением. stackoverflow .com/questions/28055327/. - person Nonik; 04.01.2017
comment
Кроме того, чтобы увидеть фактические запросы, созданные EF, вы можете включить журнал blogs.msdn.microsoft.com/mpeder/2014/06/16/ - person Nonik; 04.01.2017
comment
Не могли бы вы уточнить, что не так с моим заявлением о включении, я не вижу в этом проблемы. - person Aron Einhorn; 04.01.2017
comment
Включение не является гарантией. Я могу ошибаться, но, похоже, вы пытаетесь загрузить отношения, а EF отбрасывает ваше включение. Причина, по которой я говорю, что вы выполняете активную загрузку, заключается в том, что вы не отметили свои дочерние коллекции как виртуальные. Вы можете сравнить отложенную загрузку и нетерпеливую загрузку, у обеих есть свои минусы и плюсы, в зависимости от потребностей вашего проекта. - person Nonik; 04.01.2017
comment
Несколько решений, которые могут вам помочь Решение 1: var dbResult = _context.SubscriberLists; var list= dbResult.Include(c => c.Facilities).ToList(); список возврата - person Nonik; 04.01.2017
comment
Решение 2: var list= _context.SubscriberLists.Select(s => new { s, s. Средства }).ToList(); Entity Framework извлекает сущности SubscriberLists и Features из базы данных по отдельности, но склеивает их вместе с помощью процесса, называемого исправлением отношений. Как видите, Include не обязательно, чтобы это произошло. stackoverflow .com/questions/28055327/ - person Nonik; 04.01.2017
comment
Решения 3: вы можете включить ленивую загрузку для всей БД в конфигурации или вы можете включить ленивую загрузку для определенного свойства, сделав его виртуальным. - person Nonik; 04.01.2017