Лучшие практики для обновления связанных сущностей в ASP.NET MVC + EF4 без предварительной загрузки сущностей - PullRequest
4 голосов
/ 25 ноября 2010

Я видел некоторые вопросы, связанные с темой, но не смог найти ответ для этого сценария.

У меня есть структура, как
alt text

Часть моего контроллера

//
// GET: /Person/Edit/5

public ActionResult Edit(int id)
{
    var viewModel = new PersonViewModel(PersonRepository.Get(id));
    return View(model);
}

//
// POST: /Person/Edit

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(PersonViewModel model)
{
    PersonRepository.Update(model.Person, model.Phones);
    return RedirectToAction("Index");
}

В моем хранилище я делаю что-то вроде этого:

public void Update(Person person, ICollection<Phone> phones)
{
    using (var unitOfWork = UnitOfWork.Current)
    {
         Attach(contact);
         UpdatePhones(contact, phones);
         unitOfWork.Commit();
    }
}
public Person Attach(Person person)
{
     Context.AttachTo("Persons", entity);
     Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
     return entity;
}
public void UpdatePhones(Person person, ICollection<Phone> phones)
{
    if (phones == null || phones.Count == 0) return;
    foreach (var phone in phones.Where(o => o.IsDeleted && !o.IsNew))
    {
         PhoneRepository.Delete(phone);
    }
    foreach (var phone in phones.Where(o => !o.IsDeleted && o.IsNew))
    {
         party.Phones.Add(phone);
    }
    foreach (var phone in phones.Where(o => !o.IsDeleted && !o.IsNew))
    {
         phone.PartyID = party.ID;
         PhoneRepository.Attach(phone);
    }
}

IsDeleted и IsNew не сохраняются в БД и используются в динамической форме. Присоединение PhonesRepository () такое же.

Я делаю все свои обновления, как это, потому что мне нужно максимально уменьшить количество вызовов в БД. Может быть, есть известная лучшая практика для этого?

Спасибо =)

1 Ответ

4 голосов
/ 25 ноября 2010

Это совсем не плохо. Очень похоже на нашу настройку.

Пара указателей:

1 - Используйте дженерики для ваших репозиториев. Ваш код для Attach очень прост, и его не нужно дублировать среди сущностей. Если вы создали GenericRepository<T>, тогда ваш код вложения будет:

public T Attach<T>(T entity) where T : class
{
     Context.GetEntitySet<T>.Attach(entity); // pluralization on (typeof)T.name to get entity set
     Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
     return entity;
}

2 - я бы разделил метод UpdatePhones на отдельные методы. Я бы не стал полагаться на флаг (IsDeleted и т. Д.) Для определения направления действий. Я был бы более явным.

3 - Похоже, у вас есть PhoneRepository? Зачем? Person - это ваш сводный корень, а Phone всегда связан с конкретным Person, поэтому у вас должен быть только PersonRepository в этой совокупной границе. Вы должны присоединиться к Phones ObjectSet` определенного человека.

Кстати - я предполагаю, что у вас отложенная загрузка отключена? В противном случае эти операции LINQ над ICollection будут вызывать автоматические обходы.

Помимо вышеперечисленных моментов (которые в основном связаны с дизайном), с точки зрения оптимизации ваш код выглядит хорошо для меня.

И последнее замечание - есть еще один рекомендуемый метод (Алекс Джеймс) для обновления сущностей в отдельном контексте (он же MVC), который называется «технология-заглушка».

Я задал вопрос (и решил его сам) несколько дней назад, если вам интересно, проверьте его .

НТН.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...