2010-11-24 7 views
4

J'ai vu quelques questions liées au sujet, mais je n'ai pas trouvé de réponse pour ce scénario.Meilleure pratique pour mettre à jour des entités associées dans ASP.NET MVC + EF4 sans charger d'entité en premier

Je structure comme
alt text

Une partie de mon contrôleur

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

Dans mon dépôt im faire quelque chose comme ceci:

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 et ISNEW ne sont pas conservées dans db et utilisé sous forme dynamique. PhonesRepository Attach() est identique.

Im faisant toutes mes mises à jour comme ceci parce que je dois réduire le nombre d'appels de DB autant que possible. Peut-être qu'il existe une meilleure pratique connue pour cela?

Merci =)

Répondre

4

Ce n'est pas mal du tout. Très similaire à notre configuration.

Couple de pointeurs:

1 - Utilisez génériques pour vos Référentiels. Votre code pour joindre est très simple, et ne devrait pas avoir besoin d'être dupliqué parmi les entités. Si vous avez créé un GenericRepository<T>, votre attach code serait:

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 - Je séparer la méthode UpdatePhones dans les méthodes séparées. Je ne compterais pas sur un drapeau (IsDeleted, etc) pour déterminer le cours de l'action. Je serais plus explicite.

3 - On dirait que vous avez un PhoneRepository? Pourquoi? Person est votre racine agrégée, et Phone est toujours liée à un Person particulier, par conséquent vous ne devriez avoir qu'un PersonRepository dans cette limite globale. Vous devez attacher au Phones ObjectSet` d'une personne en particulier.

BTW - je suppose que vous avez chargement paresseux désactivé? Si ce n'est pas le cas, ces opérations LINQ sur ICollection provoqueront des allers-retours silencieux. En dehors des points ci-dessus (qui sont principalement liés au design), en termes d'optimisation, votre code me semble bon.

Et une note finale - il existe une autre technique recommandée (Alex James) pour mettre à jour des entités dans un contexte détaché (aka MVC) appelé le «stub techinque».

J'ai posé une question (et l'ai résolu moi-même) il y a quelques jours si vous êtes intéressé, check it out.

HTH.

Questions connexes