2016-02-16 2 views
3

У меня проблема с использованием EF7 в веб-приложении, с помощью которого я мог бы воспользоваться некоторой помощью. В настоящее время я использую EF7 RC1.Как я могу предотвратить EF7 от надежной фиксации свойств навигации?

Некоторые модели, которые иллюстрируют мою проблему.

Контакт

public class Contact 
{ 
    public Guid Id { get; set; } 

    public string Desc { get; set; } 
    public ContactType ContactType { get; set; } 
} 

ContactType

public class ContactType 
{ 
    public Guid Id { get; set; } 
    public string Desc { get; set; } 

    public ICollection<Contact> Contacts { get; set; } 
} 

Эти модели связаны через Fluent API, как это:

modelBuilder.Entity<Contact>(entity => { 
    // abridged for clarity 

    entity 
     .HasOne(c => c.ContactType) 
     .WithMany(ct => ct.Contacts) 
     .IsRequired();     
}); 

Мои потребности должны быть в состоянии извлечь коллекция контактных объектов из базы данных с включенным свойством ContactType. EF делает это довольно легко:

using(var context = new MyDbContext()) { 
    var contacts = await context 
     .Contacts 
     .Include(c => c.ContactTypes) 
     .Where(/* some search criteria */) 
     .ToListAsync(); 
} 

Проблема в том, что при загрузке свойства ContactType из контактных лиц (что происходит из-за вызов .INCLUDE() в запросе), EF также услужливо нагружает Контакты недвижимость каждого объекта ContactType, что приводит к бесконечной цепочке контактов, указывающих на ContactTypes и ContactTypes, указывающие на контакты. Я понимаю, почему это поведение по умолчанию и что оно полезно во многих случаях, но мои потребности - сериализовать эти объекты в JSON и отправить их клиенту - это ситуация, доступная только для чтения.

Желаемое поведение для EF - вернуть коллекцию контактов с загруженными (не нулевыми) свойствами ContactType, у которых их свойство «Контакты» установлено равным нулю. Может ли это что-то сделать EF? Есть ли способ закончить с графиком объекта? Я хочу, чтобы вручную отключить свойства, которые я не хочу заполнять?

Вещи, которые я пробовал:

  • .AsNoTracking Добавление данных() в запросе EF (который, кажется, не остановить в Контакты свойство ContactType объекта из загружаемой)
  • рассказывающие не Json.NET сериализовать бесконечные опорные петли (которая необходимые, чтобы избежать бесконечной рекурсии во время сериализации, но все равно результаты в большом количестве дополнительных данных сериализовано)

ответ

3

Вы не можете избежать EF для загрузки коллекции ContactType.Contacts, так как она фактически не загружает ее, а заполняет коллекцию загруженными экземплярами контактов. Вот почему использование AsNoTracking не имеет никакого эффекта, потому что это не проблема ленивой загрузки или ChangeTracker.

У вас есть три возможных решения:

  1. Используйте Json.NET ReferenceLoopHandling = ReferenceLoopHandling.Ignore, но, как вы заявили, что будет генерировать много unnecesary данных, как вы получите коллекцию Контакты для каждого ContactType
  2. Использование [JsonIgnore] атрибут на ContactType.Contacts, поэтому он будет игнорироваться сериализатором.Но он будет игнорировать его всегда, я не знаю, если вам это нужно и в других ситуациях
  3. Определение DTO, использовать что-то вроде Automapper для отображения данных в нем (без контактов коллекции) и сериализовать его

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

+0

Принимая это как ответ - я боялся, что это так, но я ценю вашу помощь. Automapper не был на моем радаре и может удовлетворить наши потребности. – Jammer

0

У меня такой же вопрос Entity Framework 7 Core disable auto loading

добавить AsNoTracking()

IQueryable<ScheduleModel> q = _db.Schedules; 
q = q.AsNoTracking(); 
q = q.Include(x => x.ElementItem); 
q = q.Include(x => x.ScheduleHours); 

Свойства не заселить автоматический в настоящее время.

Смежные вопросы