2010-03-04 3 views
2

Je sais que l'utilisation de WCF dans SA est obsolète car elle passera à SA Contrib. Mais jusqu'à ce qu'il l'ait fait, je suppose que je dois utiliser le support en SA. Cela dit, j'ai un problème avec la fermeture de la session NHibernate sous-jacente après l'appel d'un service WCF. DbContext.Session de mon référentiel est fermé après le premier appel, donc je ne peux pas appeler mon service plus d'une fois au cours d'une seule requête HTTP.WCF/S # arpArch: ISession sous-jacente est fermée après le premier appel dans une requête

J'ai configuré WCF dans mon projet basé sur l'exemple d'application Northwind. L'exemple appelle uniquement un service WCF une fois par requête, ce problème ne s'affiche donc pas. Le problème est facilement reproduit, en dupliquant la ligne suivante dans le TerritoriesController:

territoires = territoiresWcfService.GetTerritories();

Ceci déclenche une exception ObjectDisposedException: "Session is closed! Object name: 'ISession'".

Des idées?

Répondre

3

J'ai réussi à le résoudre. En inspectant le code source SharpArch.Wcf, j'ai constaté qu'avant d'envoyer la réponse du service WCF, il ferme toujours toutes les sessions NHibernate. Ceci en soi est une bonne chose.

En outre, j'ai constaté que mes usines proxy client ne tiraient qu'une seule fois par requête Web, tandis que le second appel de service devait induire une nouvelle instance de proxy. Le résultat était que le deuxième appel de service échouerait car la session NHibernate sous-jacente était déjà fermée. J'ai résolu cela en décorant mes classes proxy client avec le Castle.Core.TransientAttribute, ce qui laisse la gestion de la durée de vie jusqu'à l'usine qui crée le client. Le résultat de cela est que nos usines proxy sont appelées chaque fois qu'un proxy est demandé.

En second lieu, je devais enregistrer les procurations comme celui-ci (dans la ComponentRegistrar classe):

container.AddFacility("WcfSessionFacility", new WcfSessionFacility()); 

container.Kernel.AddComponentWithExtendedProperties(
    "AccountService", 
    typeof(IAccountService), 
    typeof(AccountServiceClient), 
    new Dictionary<string, object>() 
     { 
      { WcfSessionFacility.ManageWcfSessionsKey, true } 
     }); 

Le WcfSessionFacility gère la fermeture/du client abandon, en fonction de son état. Cela garantit que le canal client est fermé chaque fois que le proxy du client est détruit, donc nous n'avons pas besoin de placer nos appels dans des blocs try-catch.Comme moi, vous pourriez penser à configurer la gestion de la durée de vie tout en ajoutant le composant au lieu d'utiliser un attribut, mais apparemment il n'y a pas de surcharge de AddComponentWithExtendedProperties qui le permet.

1

Je ne suis pas familier avec SharpArchitecture, mais il semble que vous avez au moins deux options:

  1. Du côté client, disposer le service WCF après la premier appel et nouveau un autre WCF Service avant de faire le deuxième appel , obtenant ainsi une nouvelle ISession. Rendre le service WCF plus intelligent sur l'élimination des sessions de sorte que vous pouvez garder la session ouverte plus longtemps. Il y a plusieurs façons de faire cela et cela implique probablement une bonne quantité de nouvelle logique dans le service WCF, mais il devrait être totalement réalisable.

+0

Merci pour votre réponse, votre première suggestion a été utile. –

Questions connexes