Отключенное поведение Entity Framework при обновлении графа объектов
В настоящее время я работаю с проектом, который использует следующие технологии.
- ASP.net MVC - уровень представления
- Уровень обслуживания данных - (WCF)
- Слой объектов передачи данных (DTO) с Auto Mapper
- Уровень домена (POCO, Code First Entity Framework)
- Слой репозитория + Entity Framework 4.3 + DbContext.
Мы используем DTO для преобразования объектов домена наоборот с помощью автоматического сопоставления и отправки во внешний интерфейс с помощью службы WCF.
Кроме того, мы создаем DBContext для каждого запроса на уровне WCF для каждого запроса, и наш контекст службы WCF создается с помощью функции "За вызов" и "Без отслеживания" в клиентских DTO, и он полностью отключен.
Также у нас есть следующий граф объектов.
public class User : BaseEntity
{
public virtual Identity Identity { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public int IdentityId { get; set; }
public virtual IList<Group> Groups{ get; set; }
}
public class Identity : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual IList<Email> Emails { get; set; }
public virtual IList<PhoneNumber> PhoneNumbers { get; set; }
}
Наша структура Dto больше похожа на доменную.
Мои вопросы:
Когда дело доходит до обновления графа объектов. Например: UpdateUser (User user); Каков наилучший подход с Entity Framework?
Теперь мы используем отдельные функции для сохранения навигационных данных, например:UpdateEmail (userId, Email)(сохраняет только примитивные данные, а не отношения); так что он делает много вставок и обновлений в базе данных, когда мы рассматриваем один UnitOfWork.
Текущая реализация следующим образом
public void UpdateUser(User user)
{
UpdateEmail(user.userId, user.Idenity.Emails);
UpdatePhone(user.userId, user.Identity.PhoneNumbers);
etc.............
UpdateUser(user);
UnitOfWork.Commit();// Calling DbContext.SaveChanges();
}
Есть ли какой-либо шаблон или лучшие практики, которые мы можем использовать с Entity Framework в описанной выше ситуации с отключенным графом объектов?
3 ответа
Существует не так много вариантов, чтобы решить эту проблему. EF не имеет прямой поддержки для обновления отключенных графов объектов. Вы должны закодировать логику обновления, и обычно есть два способа сделать это:
- Когда вы получите обновленного пользователя из запроса на обслуживание, вы вызовете базу данных и получите текущее состояние базы данных = пользователь со всеми затронутыми отношениями. Вы будете использовать версию базы данных и обновленную версию для создания действительного набора изменений, поэтому в конце EF будет обновлять, вставлять и удалять только те данные, которые действительно изменились.
- Вы также измените свои DTO на состояние транспорта, и ваш клиент будет отвечать за установку типа модификации, которую он сделал в DTO. Вы будете использовать эту информацию для правильной настройки
ChangeTracker
для каждого полученного лица.
Является ли ваша проблема сейчас, когда вы используете EF, и он делает много звонков для обновления? Я не вижу возможности обойти это, поскольку ваши номера телефонов и электронные письма - это отдельные таблицы. Вы можете создать сплющенную сущность для пользователя, содержащую по пять штук каждого, и сопоставить с процедурой для вашей вставки. Это уменьшит количество звонков, но не самое чистое ИМХО. Если вы обрабатываете много пользователей одновременно, то, возможно, разбейте UOW, чтобы действовать только на пользователя, чтобы у вас были более короткие транзакции. Есть ли в настоящее время проблема производительности или просто будущая проблема? -
Без выравнивания вы ничем не отличаетесь от сценария, не используя EF. Я не понимаю, почему подумал, что из-за того, что вы используете DDD, вы не можете вводить сущности, специфичные для отображений данных. Ваши сущности все еще можно использовать, просто у вас есть новая сущность с сопоставлениями. Фактически вы можете сделать это без сущностей в своем хранилище позже (хранилище запрашивает измененные объекты, выравнивает и отправляет на уровень доступа к данным для вызова proc)