2010-11-24 52 views
4

我已經看到一些與主題相關的問題,但無法找到針對此方案的答案。在不加載實體的情況下更新ASP.NET MVC + EF4中的相關實體的最佳實踐

我有一個像我的控制器

// 
// 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"); 
} 


alt text

部分在我的倉庫IM結構做這樣的事情:

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和是否新款不會持續到DB並以動態形式使用。 PhonesRepository Attach()是一樣的。

我正在做這樣的所有更新,因爲我需要儘可能減少數據庫調用次數。也許有這樣的一個已知的最佳做法?

謝謝=)

回答

4

這並不糟糕。非常類似於我們的設置。

兩個指針:

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。您應該附加到特定人員的ObjectSet`上。

順便說一句 - 我假設你有延遲加載禁用?如果不是,那麼通過ICollection進行的LINQ操作將導致無聲的往返行程。

除了上述幾點(主要是設計相關的)之外,優化你的代碼對我來說看起來不錯。

最後一點 - 還有一種推薦技術(亞歷克斯詹姆斯)用於更新被稱爲「stub techinque」的分離上下文(又名MVC)中的實體。

前幾天我問了一個問題(並且自己解決了)如果您有興趣,check it out

HTH。