2009-03-31 10 views
2

Ich habe eine Webanwendung, die derzeit den aktuellen HttpContext verwendet, um einen LINQ-Datenkontext zu speichern. Der Kontext wird für die aktuelle Anforderung besteht, auf einer Basis pro Benutzer, pro Rick Strahl's blog:Serverseitiges Äquivalent von 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 
} 

Allerdings habe ich einige Skripte, die aus der Datei global.asax ausführen, dass nicht einen Httpcontext verfügen. Der HttpContext.Current ist NULL, weil der Server derjenige ist, der die "Anfrage" macht.

Gibt es ein äquivalentes Objekt, das ich verwenden kann, um den Datenkontext zu speichern? Also muss ich mir keine Gedanken darüber machen, sie neu zu erstellen und Objekte anzuhängen/abzutrennen? Ich möchte nur den Kontext für die Lebensdauer meiner Prozesse beibehalten.

AKTUALISIERT:

ich derzeit versuche in meiner DAL Helfer Klasse eine statische Variable zu verwenden. Beim ersten Aufruf einer der Methoden in der Klasse wird der DataContext instanziiert und in der statischen Variablen gespeichert. Am Ende meines Prozesses rufe ich eine andere Methode auf, die Dispose für den DataContext aufruft und die statische Variable auf NULL setzt.

+0

In welchen Ereignissen laufen Ihre Skripte? Ich nehme Session_Start und End an? – JoshBerke

+0

Ich habe einige Timer, die regelmäßig ausgeführt werden. Sie werden während des Application_Start-Ereignisses erstellt. Sie laufen von Zeit zu Zeit, überprüfen die Datenbank nach Dingen und schießen einige E-Mails ab. –

+0

Bitte klären Sie - Sie haben eine Methode, die aktuellen Kontext zurückgibt (neue erstellen, wenn es nicht existiert). Und Sie möchten, dass diese Methode sowohl mit HttpContext verfügbar ist als auch ohne sie (im Timer-Callback). Recht? – XOR

Antwort

4

Können Sie nicht einfach eine statische Variable speziell für diese Skripts verwenden? Das wird die gleiche Lebensdauer wie die AppDomain haben. Sie sollten sich sorgfältig Gedanken über Nebenläufigkeitsprobleme machen, aber es klingt wie der einfachste Weg, um einen Wert herum zu halten.

(Ich habe gerade überprüft, und obwohl eine Instanz von HttpApplication kann verwendet werden, um mehrere Anfragen zu bedienen, jeder nur dient nur eine Anfrage zu einem Zeitpunkt - was darauf hindeutet, dass mehrere Instanzen für gleichzeitige Anfrage Verarbeitung erstellt werden. t validiert dies, aber es klingt wie es wäre nicht sicher, es in einer Instanzvariable zu halten.)

EDIT: Josh's Antwort schlägt vor, dass Sie dies per-Thread wollen. Das hört sich für mich etwas merkwürdig an, denn wenn diese Ereignisse nicht auftreten, wird es sehr wahrscheinlich sein, dass sie nur auf verschiedenen Threads ausgeführt werden, wodurch das ganze Sharing-Geschäft sinnlos wird. Wenn Sie wirklich diese Art von Sache wollen, würde ich vorschlagen, nur eine Instanzvariable in der HttpApplication-abgeleiteten Klasse zu verwenden - genau aus dem im obigen Absatz beschriebenen Grund :)

+0

Jon, das ist richtig. Jede Anwendung dient nur einer Anfrage zur Zeit. – XOR

+0

Meinst du "jede bereitgestellte Webanwendung" oder "jede Instanz von HttpApplication"? Erstellt eine einzelne Webanwendung mehrere Instanzen? Das Serialisieren aller Anfragen an eine bereitgestellte Anwendung klingt für mich nach Performance-Tod - das kann doch nicht der Fall sein. –

+0

Ich habe nur 1 Instanz dieser Webanwendung auf 1 Box ausgeführt. Ich will nur, dass diese Prozesse im Hintergrund laufen und etwas arbeiten. Wenn sie ausgeführt werden, möchte ich, dass der Datenkontext während des Vorgangs beibehalten wird, sodass ich mich nicht darum kümmern muss, sie neu zu erstellen und Entitäten anzuhängen. –

1

Warum nicht den aktuellen HttpContext verwenden? Die Skripts in Ihrer global.asax-Datei sind das Ergebnis einer Anforderung, die auf den Server kommt. Daher sollte dieser Anfrage ein Kontext zugeordnet sein, den Sie abrufen können.

Ich verstehe nicht die Notwendigkeit, den Schlüssel basierend auf dem Hashcode oder dem Thread zu generieren. Es wird eine separate Instanz von HttpContext für jede eingehende Anfrage geben, und diese Instanz wird spezifisch für den Thread sein, der die Anfrage verarbeitet. Aus diesem Grund ist der Schlüssel ziemlich wertlos, wenn er auf der Instanz von HttpContext und dem Thread basiert.

Wie verfügen Sie auch über den DataContext, wenn Sie fertig sind? Es implementiert IDisposable aus einem bestimmten Grund, also würde ich empfehlen, eine solche gemeinsame Instanz zu verwenden.


UPDATE

In den Kommentaren zeigt an, dass es einen Timer, der das ausführt, die Skripte ausgeführt wird.Anstelle des Timers würde ich empfehlen, eine geplante Aufgabe einzurichten, die einen Webservice oder eine vorbestimmte Seite auf der Site aufruft, die die Aufgabe ausführen wird. Dann haben Sie immer einen HttpContext, mit dem Sie arbeiten können.

+0

Ich hatte den gleichen Gedanken über seinen HttpContext, aber da er Threads erzeugt, würde es keinen Kontext geben. – JoshBerke

+0

@Josh: Es gibt keinen Hinweis darauf, dass er Threads zum Ausführen dieser Skripte erzeugt. Die Funktionen sind in global.aspx. Wenn es sich um den Standardsatz von Ereignissen für dieses Modul handelt, werden sie als Antwort auf Anforderungen an den Server ausgegeben. – casperOne

+0

Überprüfen Sie seinen Kommentar. Er sagt, er hat einige Timer, die während App_Start periodisch ausgeführt werden. – JoshBerke

0

HttpContext.Current ist eine statische Methode und sollte von überall verfügbar sein, solange der Code im Kontext einer Anforderung ausgeführt wird.

In Ihrem Fall, dass Sie nicht im Kontext einer Anfrage ausführen, könnten Sie mit Application.Cache aussehen, aber ich würde davor warnen, einen DataContext offen zu halten. Ich bin nicht sehr familiär mit Linq zu Entitäten, so dass ich falsch liegen könnte, aber im Allgemeinen Datenbank-bezogene Elemente wie Verbindungen zu cachen ist schlecht.

Ich würde auch empfehlen, dass Sie in Betracht ziehen, die Logik aus Ihrem global.asax und einem Windows-Dienst zu verschieben. Dies würde Ihnen mehr Kontrolle über diese Aufgaben geben, zum Beispiel können Sie sie separat von der Website herunterfahren.

bearbeiten

Wie JS weist darauf hin, eine statische Variable verwenden könnte. Sie können auch eine Instanzvariable definieren, die mit dem ThreadLocal-Attribut markiert ist. Dies gibt jedem Thread eine eigene Kopie der Variablen und kann Konflikte eliminieren. Da Sie möchten, dass jeder Thread sowieso eine eigene Kopie hat.

0

Gibt es einen Grund, warum diese genauso behandelt werden müssen wie die anderen DataContexte? Es scheint mir, dass wenn der Kontext nur innerhalb der Ereignisbehandlungsroutine benötigt wird, Sie ihn nicht herum behalten müssen. Vor allem, wenn es in Application_Start ist (wie in Ihrem Kommentar), ich würde es nicht stören, es irgendwo zwischenzuspeichern - verwenden Sie es nur lokal und übergeben Sie es an die anderen Methoden wie benötigt.

0

Setzen Sie den DataContext als Zustandsparameter beim Erstellen des Timers. Basierend auf den Informationen, die Sie zu den Kommentaren gepostet haben, scheint mir, dass Ihr DataContext mehr mit den Timern als mit irgendetwas anderem zu tun hat.

Vermeiden Sie es auch, denselben DataContext für verschiedene Timer zu verwenden, da Sie sonst gemischte Änderungen von den verschiedenen Timern erhalten würden. Stellen Sie außerdem sicher, dass die gleiche Timer-Logik nicht zweimal ausgeführt wird, da dies die gleiche, d.h. zu kurze Zeit ohne Steuerung verursachen würde.

Verwandte Themen