19

Après avoir lu beaucoup d'articles, je ne suis toujours pas sûr des responsabilités du modèle d'unité de travail lors de l'interaction avec les dépôts.Interaction entre l'unité de travail et les modèles de dépôt

Référentiels sont responsables pour le chargement et l'enregistrement des entités de racine d'agrégation, alors pensez à l'exemple de code suivant:

using(IUnitOfWork uow = container.CreateUnitOfWork()) 
{ 
    Repository<ARoot> roots = container.GetRepository<ARoot>(); 
    ARoot root = root.FindByName("ARoot"); 
    root.Name = "ANewName"; 

    roots.Save(root); 
    uow.Commit(); 
} 

L'unité d'interface de travail serait définie par les méthodes suivantes:

public interface IUnitOfWork 
{ 
    void Insert(object); 
    void Update(object);   
    void Delete(object); 
    void Commit(); 
    void Rollback(); 
} 

Lets indique que le référentiel est implémenté à l'aide d'un SQL Mapper très simple, donc le FindByName contient du SQL direct pour renvoyer ARoot, l'implémentation de Save ressemblerait-elle à ceci:

public void Save(T entity) 
{ 
     IUnitOfWork uow = GetUnitOfWork(); 
     // Tell the UOW we are updating this entity 
     uow.Update(entity); 
} 

Le code de validation d'unité de travail construirait alors tout le SQL requis pour mapper l'entité dans le DB?

Question 2)

Si j'ajoute une racine globale dans l'unité de travail, est l'unité de travail responsable de persisiting la racine, et ses enitities enfants, ou devrait être la méthode Save du référentiel ajouter la changé les entités dans l'unité de travail? par exemple

public void Save(T entity) 
{ 
     IUnitOfWork uow = GetUnitOfWork(); 
     // Tell the UOW we are updating this entity 
     uow.Update(entity); 
     uow.Update(entity.AChildObject); 
} 

OU ... Alternativly

Est-ce une unité de travail ne traitent avec des racines globales, et quand commited appelle le référentiel des méthodes Enregistrer pour chaque objet dans son ensemble de changement, en gardant le code de mappage SQL persisteront l'entité dans le référentiel, en changeant le premier exemple de code à

using(IUnitOfWork uow = container.CreateUnitOfWork()) 
{ 
    Repository<ARoot> roots = container.GetRepository<ARoot>(); 
    ARoot root = root.FindByName("ARoot"); 
    root.Name = "ANewName"; 

    //roots.Save(root); 
    uow.Update(root); 
    // and commit 
    uow.Commit(); 
} 

Merci,

James

Répondre

3

Dans notre projet, nous utilisons un référentiel pour se comporter comme une collection d'entités, et UnitOfWork est utilisé pour suivre les changements sur ces entités et pour les réécrire dans le magasin de données. Si vous utilisez LinqToSql ou un autre OR Mapper, cela risque d'implémenter un pattern UnitOfWork en lui-même, si souvent nous ne sommes que l'instance ORMapper dans notre propre IUnitOfWork.

Notre interface référentiel est généralement quelque chose comme ..

IEnumerable<Order> FindByCustomerId(string customerId); 
    void Add(Order order); 
    void Remove(Order order); 

Nous n'avons une méthode de sauvegarde dans le référentiel. Si nous n'avons pas besoin d'UnitOfWork, les méthodes Ajout/Suppression agissent directement sur la banque de données.

Si nous avons besoin d'un UnitOfWork, l'interface publique est quelque chose comme ...

void Commit(); 
void Rollback(); 

Le dépôt dispose d'une interface interne avec le UnitOfWork, donc quand on interroge le référentiel, les objets retournés sont suivis par l'UnitOfWork pour les changements. La méthode commit écrit les modifications dans le magasin de données, la méthode d'annulation efface simplement ses modifications.Lorsque nous utilisons LinqToSql, le DataContext se charge du suivi des modifications. Lors de la restauration, nous ne faisons qu'instancier un nouveau contexte. La persistance est gérée, à travers la racine et ses enfants. Une instance UnitOfWork est partagée entre tous les référentiels. Lorsque nous n'utilisons pas LinqToSql, alors nous implémentons notre propre UnitOfWork, peut-être qu'il appelle un service web ou quelque chose, dans ce cas nous changeons le suivi dans les classes d'entités eux-mêmes en utilisant une classe EntityBase.

Nous avons un dépôt pour chaque racine, mais parfois les enfants d'une racine sont utilisés comme racines elles-mêmes, donc nous avons souvent besoin de quelque chose comme un OrderLineRepository, parce que nous avons un cas d'utilisation Commander des lignes

3

Généralement, la manière dont je souhaite que cela se fasse est que l'UoW suit les changements qui sont enregistrés en appelant directement IRepository.Save().

Je préfère aussi que le code UoW soit traité comme un aspect et en dehors des interactions avec le domaine. Cela signifie qu'il est géré par certains gestionnaires de commandes globaux ou par le code de services Web dans le cadre de la demande. En d'autres termes commencer une requête ouvre une unité de travail, la terminant la ferme. De cette façon, le domaine peut être ignorant de l'UoW et de sa mise en œuvre.

La validation de l'unité de travail entraîne alors la persistance des modifications apportées en appelant .Save() et d'autres méthodes de modification. Très probablement, l'UoW est ce qui suit ces changements d'une manière ou d'une autre.

2
  • UnitOfWork est votre transaction gestionnaire
  • Repository fait le travail acutal pour charger/enregistrer des objets à le magasin de données

J'utilise des définitions similaires à:

IUnitOfWork { Commit(); } 
IRepository { GetAll(); GetById(); Add(T item); Remove(T item); } 

Je n'aurais pas créé UnitOfWork SQL - cette logique serait dans votre Repository. Quel magasin de données utilisez-vous?