I have seen some questions related to topic, but could not find answer for this scenario.
I have structure like

Part of my controller
//
// 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");
}
In my repository im doing something like this:
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 and IsNew are not persisted into db and used in dynamic form. PhonesRepository Attach() is same.
Im doing all of my updates like this because i need to reduce number of db calls as much as possible. Maybe there is a known best practice for this?
Thanks=)
That’s not bad at all. Very similar to our setup.
Couple of pointers:
1 – Use generics for your Repositories. Your code for Attach is very simple, and should not need to be duplicated amongst entities. If you created a
GenericRepository<T>, then your attach code would be:2 – I would seperate the
UpdatePhonesmethod into seperate methods. I wouldn’t rely on a flag (IsDeleted, etc) to determine the course of action. I would be more explicit.3 – Looks like you have a
PhoneRepository? Why?Personis your aggregate root, andPhoneis always related to a particularPerson, therefore you should only have aPersonRepositoryin this aggregate boundary. You should be attaching to thePhonesObjectSet` of a particular person.BTW – i assume you have lazy loading disabled? If not, those LINQ operations over the ICollection will cause silent round trips.
Apart from the above points (which are mainly design related), optimization-wise your code looks good to me.
And a final note – there is another recommended technique (Alex James) for updating entities in a detached context (aka MVC) called the “stub techinque”.
I asked a question (and solved it myself) a few days ago if your interested, check it out.
HTH.