Question

Nous développons une application .Net avec l'architecture suivante: couche de présentation (en utilisant le modèle MVC avec ASP.Net MVC 2), la couche de service, couche d'accès aux données (en utilisant modèle référentiel sur Entity Framework)

.

Nous avons décidé de mettre la gestion des transactions dans la couche de service, mais nous ne sommes pas sûr de la façon de la mettre en œuvre. Nous voulons contrôler la transaction entièrement au niveau de la couche de service. C'est, chaque fois qu'un contrôleur appelle une méthode dans la couche de service, il doit être une opération atomique en ce qui concerne les mises à jour de base de données.

S'il n'y avait pas de relation entre les différents services fournis dans la couche de service, il serait alors simple: chaque méthode doit valider les modifications à la fin de son exécution (qui est, appelez la méthode de sauvegarde sur le contexte, il utilise). Mais parfois des services au travail de la couche de service ensemble.

par exemple: nous offrons un service d'expédition qui a une méthode de confirmation qui reçoit les paramètres suivants: l'identifiant de l'expédition, un drapeau indiquant si elle correspond à un nouveau client ou un existant, l'identifiant du client (dans le cas où la confirmation de l'expédition est pour un client existant) et un nom de client (dans le cas où il est pour un nouveau client). Si le drapeau est réglé sur « nouveau client », puis la couche de service doit (a) créer le client et (b) confirmer l'expédition. Pour (a) le service d'expédition appelle le service à la clientèle (qui implémente déjà les validations et la logique nécessaires pour créer un nouveau client et le stocker dans la base de données).

Qui devrait engager les changements dans ce scénario?

  • Au cas où le service à la clientèle le faire? il ne peut pas valider les modifications après la création du nouveau client, parce que quelque chose peut mal tourner plus tard dans la méthode de confirmation d'expédition, mais il doit engager ses changements dans le cas, il est appel directement (dans d'autres cas d'utilisation, à condition de créer un client).
  • Au cas où le contrôleur appelant la méthode de service le faire? mais le contrôleur ne devrait pas savoir quoi que ce soit sur les transactions, nous avons décidé de mettre tous knowladge des transactions dans la couche de service.
  • Un gestionnaire de transactions dans la couche de services? Comment concevoir ?, qui l'appelle et quand?

Y at-il un modèle de conception pour cela que nous devons suivre?

Était-ce utile?

La solution

J'ai un Commit () sur mon service, cela n'engage que si le UnitOfWork est créé par le service, si elle est adoptée dans le constructeur le commit ne fait rien.

I a utilisé un deuxième constructeur (interne) pour le service:

public class MyService
{
private IUnitOfWork _uow;
private bool _uowInternal;

public MyService()
{
    _uow = new UnitOfWork();
    _uowInternal = false;
}

internal MyService(IUnitOfWork uow)
{
    _uow = uow;
    _uowInternal = true;
}
public MyServiceCall()
{
    // Create second service, passing in my UnitOfWork:
    var svc2 = new MySecondService(_uow);

    // Do your stuff with both services.
    ....
    // Commit my UnitOfWork, which will include all changes from svc2:
    Commit();
}

public void Commit()
{
    if(!_uowInternal)
        _uow.Commit();
}
}

Autres conseils

Dans une architecture similaire avec WCF et L2S au lieu de EF, nous avons choisi d'utiliser des transactions dans la classe principale de mise en œuvre de l'interface de service. Nous avons utilisé TransactionScope pour y parvenir:

public void AServiceMethod() {
    using(TransactionScope ts = new TransactionScope()) {
         service1.DoSomething();
         service2.DoSomething();
         ts.Complete();
    }
}

Le principal inconvénient est que la transaction peut devenir gros. Dans ce cas, si par exemple l'un des appels de service dans le bloc de transaction ne nécessite qu'un accès en lecture seule, nous envelopper dans un bloc imbriqué TransactionScope(TransactionScopeOption.Suppress) pour empêcher les lignes / tables de verrouillage supplémentaire dans la durée de vie de la transaction.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top