2010-11-24 54 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。