2016-08-15 6 views
8

Это то, что прослушивало меня со времени перехода на EF 6. Как мы теперь сопоставляем коллекции, чтобы просматривать модели, такие, что изменение отображения не мучительно с помощью IEnumerables. Вот фрагмент кода ниже демонстрирует мою проблему:Сопоставление объектов EF с ViewModels, поддерживающих ICollection и ленивую загрузку

Entity - SS.Entity.Event

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 
public virtual ICollection<SS.Entity.User> Broadcasters { get; set; } 
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] 
public virtual ICollection<SS.Entity.User> Viewers { get; set; } 

Модель - SS.Model.Event

public virtual ICollection<SS.Model.User> Broadcasters { get; set; } 
public virtual ICollection<SS.Model.User> Viewers { get; set; } 

Mapping Назад Организация после изменения коллекции

Broadcasters = e.Broadcasters.Select(u => new SS.Entity.User 
{ 
    Id = u.Id, 
    SkypeId = u.SkypeId, 
    Name = u.Name 
}).ToList(), // THIS IS THE PROBLEM 
Viewers = e.Viewers.Select(u => new SS.Entity.User 
{ 
    Id = u.Id, 
    SkypeId = u.SkypeId, 
    Name = u.Name 
}).ToList() // THIS IS THE PROBLEM 

Проблема заключается в том, что я не могу сопоставить ICollection с другим ICollection, поскольку Select создает IEnumerable, который после этого возвращает свойства отображения в EF, поскольку мне нужно воссоздать коллекцию или перечислить ее для ее обновления. Я знаю, что мне не хватает чего-то очевидного, я обновил ICollection, чтобы быть виртуальным, как описано в других ответах, но мне непонятно, как это помогает.

Любая помощь была бы принята с благодарностью!

Gerard

+0

Почему не 'Вещательные = e.Broadcasters'? Очень неясно, о чем вы спрашиваете. Есть один класс «Пользователь» или два? И как эта ленивая загрузка связана с этим? –

+0

Я попытался сделать это яснее, добавив пространства имен. По существу, мой вопрос заключается в том, как вы можете отображать изменения коллекции в EF6. Я не вижу ясного способа сделать это без использования ToList(). Поэтому при работе с большими коллекциями наблюдается значительное повышение производительности. –

+0

".... собирать карты для просмотра моделей, таких, что отображение изменений обратно не является болезненным с использованием IEnumerables" ..... это не ясно. Что вы подразумеваете под «картографическими коллекциями через». Как показано на вашем посте, вы создаете новые типы из своих DTO ..... почему это не работает для вас? – Sam

ответ

1

На вашем ViewModel, они могут быть просто IEnumerable<T>, если вам не нужно будет делать .Add() на них позже. Это может быть то, что вы хотите. Кроме того, они не должны быть виртуальными на Модели, потому что у вас нет EF, чтобы создать производный тип вашей модели (опять же, если у вас нет других причин).

Чтобы вернуть их к объекту DTO, если вы просто хотите установить его напрямую и не проверять отдельные свойства, вы можете использовать .ToList(), чтобы он выполнил требование ICollection<T>.

// Assuming "var model" is coming in as a parameter 
var station = context.Viewers.First(); 
station.Broadcasters = model.Broadcasters.Select(b => new User { 
    Id = b.Id, 
    SkypeId = b.SkypeId, 
    Name = b.Name 
}).ToList(); 
station.Viewers = model.Viewers.Select(v => new User { 
    Id = v.Id, 
    SkypeId = v.SkypeId, 
    Name = v.Name 
}); 
+0

Это использовалось для работы в версиях до EF6, но больше не работает. Создание новых объектов даже при обратном отображении заставляет создавать новые объекты для каждого обновления, а не просто обновлять коллекцию. –

+0

Также ToList() перечисляет коллекцию, которая, если эта коллекция огромна, вызывает проблемы с производительностью. –

+0

Коллекция будет повторена, несмотря ни на что. По крайней мере, ваш вопрос очень неясно, какова ваша проблема. Что происходит сейчас с EF6, чего не было в EF5? – krillgar

2

Предполагая, что ваш ".ToList()" проблема при сохранении обратно в базу данных, это то, что ваш ищете ?:

var event = new SS.Entity.Event {Name = "New Name" and other properties}; 

IEnumerable<SS.Entity.User> broadcasters = e.Broadcasters 
     .Select(u => new SS.Entity.User 
      { 
       Id = u.Id, 
       SkypeId = u.SkypeId, 
       Name = u.Name 
      }); 

var viewers = e.Viewers.Select(u => 
      new SS.Entity.User 
      { 
      Id = u.Id, 
      SkypeId = u.SkypeId, 
       Name = u.Name 
      }); 

//add broadcasters to event 
event.Broadcasters.AddRange(broadcasters); 

//add viewers to event 
event.Viewers.AddRange(viewers); 

dataContext.Events.Add(event); 
dataContext.SaveChanges(); 
+0

Это хорошая идея ... У меня нет доступа к коду на данный момент, чтобы попробовать, но позвольте мне взглянуть завтра. Добавляет ли диапазон значение IEnumerable? –

+0

@ Герард - да, он делает. https://msdn.microsoft.com/en-us/library/system.data.entity.dbset.addrange(v=vs.113).aspx – Developer

+0

@GerardWilkinson, удачи с этим? – Developer

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