在不首先加载实体的情况下更新ASP.NET MVC + EF4中的相关实体的最佳实践

时间:2010-11-24 21:02:13

标签: .net asp.net-mvc asp.net-mvc-2 orm entity-framework-4

我看过一些与主题相关的问题,但找不到这种情况的答案。

我的结构很像 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不会持久存储到db中并以动态形式使用。 PhonesRepository Attach()是相同的。

我正在做这样的所有更新,因为我需要尽可能减少数据库调用次数。也许这有一个已知的最佳实践?

感谢=)

1 个答案:

答案 0 :(得分: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。您应该附加到特定人员的Phones ObjectSet`。

顺便说一句 - 我假设您已禁用延迟加载?如果没有,那些通过ICollection的LINQ操作将导致无声往返。

除了以上几点(主要与设计相关)之外,优化方面你的代码对我来说很好。

最后一点 - 还有另一种推荐技术(Alex James)用于更新分离上下文(也称为MVC)中的实体,称为“stub techinque”。

我几天前问了一个问题(并自己解决了),如果你感兴趣,check it out

HTH。