2009-03-31 9 views
2

J'ai une application Web qui utilise actuellement le HttpContext actuel pour stocker un contexte de données LINQ. Le contexte est persisté à la demande actuelle, sur une base par utilisateur, par Rick Strahl's blog:Equivalent côté serveur de HttpContext?

string ocKey = "ocm_" + HttpContext.Current.GetHashCode().ToString("x") 
Thread.CurrentContext.ContextID.ToString(); 

if (!HttpContext.Current.Items.Contains(ocKey)) 
{ 
    // Get new Data Context and store it in the HTTP Context 
} 

Cependant, j'ai quelques scripts qui exécutent à partir du fichier global.asax, que n'ont pas un HttpContext. Le HttpContext.Current est NULL, car le serveur est celui qui effectue la "requête".

Existe-t-il un objet équivalent que je puisse utiliser pour stocker le contexte de données? Donc, je n'ai pas à m'inquiéter de le recréer et d'attacher/détacher des objets? Je veux seulement persister le contexte pour la durée de vie de mes processus.

MISE À JOUR:

Je suis actuellement en train d'utiliser une variable statique dans ma classe d'aide DAL. Lors du premier appel à l'une des méthodes de la classe, DataContext est instancié et stocké dans la variable statique. À la fin de mon processus, j'appelle une autre méthode qui appelle Dispose sur le DataContext et définit la variable statique sur NULL.

+0

Dans quels événements vos scripts s'exécutent-ils? Je suppose que Session_Start et End? – JoshBerke

+0

J'ai quelques timers qui sont créés pour fonctionner périodiquement. Ils sont créés au cours de l'événement Application_Start. Ils courent de temps en temps, vérifiant la base de données pour trouver des choses et renvoyer certains courriels. –

+0

Veuillez clarifier - vous avez une méthode qui retourne le contexte actuel (en créer un nouveau s'il n'existe pas). Et vous voulez que cette même méthode fonctionne à la fois avec HttpContext disponible et sans elle (en rappel de minuterie). Droite? – XOR

Répondre

4

Ne pouvez-vous pas utiliser une variable statique spécifiquement pour ces scripts? Cela aura la même durée de vie que le AppDomain. Vous devriez probablement réfléchir aux problèmes de concurrence, mais cela semble être le moyen le plus simple de conserver une valeur.

(Je viens de vérifier, et bien qu'une instance de HttpApplication puisse être utilisée pour traiter plusieurs requêtes, chacune ne sert qu'une requête à la fois - ce qui suggère que plusieurs instances sont créées pour le traitement de requêtes simultanées. Cela a été validé, mais il semble qu'il ne serait pas prudent de le conserver dans une variable d'instance.)

EDIT: La réponse de Josh suggère que vous voulez que ce soit par thread. Cela me semble un peu étrange, car à moins que vous n'ayez un lot de ces événements, il est fort probable que vous les verrez seulement exécuter sur des threads différents, ce qui rendra inutile toute l'activité de partage. Si vous voulez vraiment ce genre de chose, je suggère simplement d'utiliser une variable d'instance dans la classe HttpApplication -derived - exactement pour la raison décrite dans le paragraphe ci-dessus :)

+0

Jon, c'est vrai. Chaque application ne sert qu'une seule demande à la fois. – XOR

+0

Voulez-vous dire "chaque application Web déployée" ou "chaque instance de HttpApplication"? Une seule application Web crée-t-elle plusieurs instances? Sérialiser toutes les demandes à une application déployée me semble être la mort de la performance - cela ne peut sûrement pas être le cas. –

+0

J'ai seulement 1 instance de cette application web fonctionnant sur 1 case. Je veux juste que ces processus fonctionnent en arrière-plan et que je fasse un peu de travail. Quand ils s'exécutent, je veux que le contexte de données soit maintenu pendant l'opération, ainsi je n'ai pas à craindre de le recréer et d'attacher des entités. –

1

Pourquoi ne pas utiliser le HttpContext actuel? Les scripts de votre fichier global.asax sont tous le résultat d'une requête arrivant sur le serveur, il devrait donc y avoir un contexte associé à cette requête que vous pouvez récupérer.

Je ne comprends pas la nécessité de générer la clé basée sur le code hash ou le thread. Il y aura une instance distincte de HttpContext pour chaque requête qui arrive, et cette instance va être spécifique au thread qui traite la requête. À cause de cela, la clé est à peu près sans valeur quand elle est basée sur l'instance de HttpContext et le thread.

De même, comment disposez-vous du DataContext lorsque vous avez terminé? Il implémente IDisposable pour une raison, donc je recommanderais contre une instance partagée comme celle-ci.


MISE À JOUR

Dans les commentaires, il indique qu'il ya une minuterie qui est en cours d'exécution qui exécute les scripts.Au lieu de la minuterie, je recommande de mettre en place une tâche planifiée qui appellera un webservice ou une page prédéterminée sur le site qui effectuera la tâche. Ensuite, vous aurez toujours un HttpContext à travailler avec.

+0

J'ai eu la même réflexion sur son HttpContext mais comme il générait des threads, il n'y aurait pas de contexte. – JoshBerke

+0

@Josh: Il n'y a aucune indication qu'il génère des threads pour exécuter ces scripts. Les fonctions sont dans global.aspx. Si c'est l'ensemble standard d'événements pour ce module, alors ils viennent en réponse aux demandes au serveur. – casperOne

+0

Vérifiez son commentaire. Il dit qu'il a quelques minuteries qui s'exécutent périodiquement pendant App_Start – JoshBerke

0

HttpContext.Current est une méthode statique qui devrait être disponible à partir de n'importe où, tant que le code s'exécute dans le contexte d'une requête.

Dans votre cas, vous ne pouvez pas exécuter dans le contexte d'une requête, vous pouvez utiliser Application.Cache mais je vous déconseille de conserver un DataContext ouvert. Je ne suis pas très familier avec linq pour les entités, donc je peux me tromper, mais généralement mettre en cache des éléments liés à la base de données tels que les connexions est mauvais.

Je vous recommande également d'envisager de déplacer la logique de votre global.asax et d'un service Windows. Cela vous permettrait d'avoir plus de contrôle sur ces tâches, par exemple vous pouvez les fermer séparément sur le site Web.

Modifier

Comme JS rappelle que vous pouvez utiliser une variable statique. Vous pouvez également définir une variable d'instance marquée avec l'attribut ThreadLocal. Cela donnera à chaque thread sa propre copie de la variable, et peut éliminer la contention. Puisque vous voulez que chaque thread ait sa propre copie de toute façon.

0

Y a-t-il une raison pour laquelle celles-ci doivent être traitées de la même manière que les autres DataContexts? Il me semble que si le contexte est seulement nécessaire dans la routine de gestion des événements, vous ne devriez pas avoir besoin de le garder. Surtout si c'est dans Application_Start (selon votre commentaire), je ne dérange pas la mise en cache nulle part - il suffit de l'utiliser localement et de le passer aux autres méthodes si nécessaire.

0

Définissez DataContext comme paramètre d'état lors de la création du temporisateur. Basé sur l'information que vous avez posté sur les commentaires, il me semble que votre DataContext est plus lié aux minuteurs qu'autre chose.

Évitez également d'utiliser le même DataContext pour des temporisations différentes, car vous obtiendriez des modifications mixtes à partir des différents temporisateurs. Assurez-vous également que la même logique de temporisation n'est pas exécutée deux fois, car cela entraînerait la même période, c'est-à-dire trop courte, sans contrôle.