2

Ok, voici le scénario. J'ai un site ASP.NET qui génère périodiquement un thread d'arrière-plan pour faire des travaux. l'exécution du thread consiste en un JobRunner qui parcourt une liste d'IJobs et appelle Execute() sur chacun d'eux. JobRunner et chaque IJob est créé par NInject. Un couple d'IJobs a une dépendance à IRepository <ModelType>. L'implémentation de IRepository que j'utilise est pour NHibernate, donc il a un argument constructeur pour ISession. Jusqu'à maintenant, j'ai demandé à NInject de renvoyer une ISession à partir d'une ISessionFactory, portée à chaque Request (InRequestScope).Étendre NHibernate ISession dans un thread généré avec NInject

Voici le problème: lorsque les différents IJobs effectuent leur traitement (ce qui implique l'enregistrement dans IRepository), les données ne sont jamais conservées car ISession.Flush() n'est jamais appelé. Chaque IJob ne sait rien de l'implémentation de l'IRepository qu'il utilise. De même, le JobRunner ne sait rien de l'implémentation de l'IJobs qu'il exécute. Pour le reste de l'application Web, cela fonctionne correctement car ISession.Flush() est appelée dans Application_EndRequest. J'ai essayé de placer ISession comme un argument constructeur au JobRunner afin que je puisse appeler Flush() quand tous les IJobs sont traités, mais il semble avoir une ISession différente de celle des IJobs (appel session.GetHashCode () renvoie des valeurs différentes pour JobRunner, mais pour tous les IJobs c'est pareil). J'ai configuré NInject à la portée ISession basée sur HttpContext s'il y en a un, sinon utilisez CurrentThread. J'ai pensé que, puisque JobRunner est sur un thread séparé, il aura une ISession portée à CurrentThread, et puisque tous les IJobs sont exécutés sur le même thread que JobRunner, ils devraient tous avoir la même ISession, mais ils ne le sont pas. Donc, ma question est la suivante: y a-t-il une meilleure façon de faire ce que j'essaie de faire? Quelqu'un sait pourquoi je voudrais obtenir une instance différente de ISession pour différentes demandes sur le même fil?

Pour l'instant j'ai une solution de contournement - je mets session.Flush() comme la dernière ligne de ma méthode NHibernateRepository.Save(), mais je ne suis pas heureux avec ça.

Répondre

1

bien j'ai trouvé la solution. mon objet JobRunner était instancié dans la méthode Application_Start de Global.asax, et en tant que tel détenait cet ID de thread au lieu de l'ID de thread d'arrière-plan.

J'ai créé une classe wrapper qui prend un type et utilise NInject pour créer une instance, et chaque fois que le thread d'arrière-plan arrive pour commencer le traitement, il utilise la classe wrapper pour obtenir une instance de JobRunner. Cela crée sur le thread approprié qui me permet d'obtenir la même ISession que mon IRepository pour que je puisse appeler session.Flush() après que tous les IJobs se soient terminés.

peut-être il y a une solution plus élégante, mais jusque-là, cela fonctionne bien.