Laden...

ASP.NET statische readonly Klasse innerhalb einer Session (Employee) - Wie?

Erstellt von skynet74 vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.777 Views
skynet74 Themenstarter:in
5 Beiträge seit 2016
vor 8 Jahren
ASP.NET statische readonly Klasse innerhalb einer Session (Employee) - Wie?

Hallo zusammen!

Ich bin seit einiger Zeit stiller Leser des Forums und habe mich nun einmal angemeldet, da ich bei einem sicherlich trivialen Problem auf dem Schlauch stehe. Ich habe schon viel gegoogelt, aber ich komme einfach nicht weiter. Ich komme aus der C Ecke und irgendwie fällt es mir schwer, in Objekten zu denken, zumal ich auch nicht mehr der Jüngste bin 😁

Mein Problem kurz umrissen:

Ich baue eine Webseite mit einem Login als default.aspx. Der User kann sich dort mit Daten anmelden, die über einen Webservice gerpüft werden. Das funktioniert auch alles tadellos. Nun sollen weitere Daten (email usw.) von einem SQL Server zu dem User nachgeladen werden. Auch das ist kein Problem. Diese gesamten Daten befinden sich in einer Klasse (Employee) mit gettern und werden nur einmal initial geladen. Employee.LoadByNo(12345) Die Klasse soll danach nur noch readonly und nur innerhalb der Session dieses Users verfügbar sein.

Frage a) Wie deklariere ich die Klasse sauber, zur Verfügbarkeit auf allen Unterseiten, aber nur innerhalb der Session?

Frage b) Wie kann ich die Session/statische Klasse beim Logout zerstören?

Ich entschuldige mich für die beiden Fragen und mein Problem, aber meine Suchen ergaben immer nur Windowsform basierte Ergebnisse.

Ich würde mich sehr freuen, wenn mir jemand bei dem Thema helfen kann.

Ein sonniges Wochenende!

PS: Eine Buchemfpehlung für den Einstieg in ASP.NET/Klassen mit guten embedded C und DB Kenntnissen würde ich mich auch freuen.

low level Byteschieber (automotive)

T
50 Beiträge seit 2010
vor 8 Jahren

Hallo,

man kann kleinere Objekte problemlos serverseitig in der Session ablegen. Die Klasse sollte aber mit dem Attribut [Serializable] dekoriert werden, da die Session serverseitig auch serialisiert werden kann - je nach Konfiguration.

this.Page.Context.Session["Key"] = instance;
HttpContext.Current.Session["Key"] = instance;

Über diesen Mechanismus kann man auf diese Objekte wieder zugreifen. Beim Zerstören der Session werden alle Einträge ebenfalls gelöscht, man kann dies aber auch explizit machen.

Deine Klasse könnte eine Methode ForSession() implementieren, die dafür sorgt, dass eine für die Session vorgesehene Klasse über den Konstruktor befüllt wird. Dann kann diese auch readonly sein.

Grüße

P.S.: Das Beispiel gilt für ASP.NET Forms, ASP.NET MVC funktioniert aber ähnlich.

skynet74 Themenstarter:in
5 Beiträge seit 2016
vor 8 Jahren

Das heisst, ich instanziere meine Employee-Klasse (Serializable) so:

private Employee oEmp = new Employee;
Session["Employee"] = oEmp;

und zum Auslesen dann halt wieder

private Employee oEmp;
oEmp = (Employee)Session["oEmp"];

low level Byteschieber (automotive)

skynet74 Themenstarter:in
5 Beiträge seit 2016
vor 8 Jahren

Ich bin es noch einmal.

Ist es nicht besser, wenn ich meine Klasse "cEmployee" in der Global.asax instanziere, mit dem scope "Session"?

Bsp:

<object id="Employee" runat="server" scope="session" class="cEmployee">

und dann bei:


void Session_Start(object sender, EventArgs e)
{
        if(Employee == null) {
            cEmployee Employee = new cEmployee;
        }
}

void Session_End(object sender, EventArgs e)
{
       if(Employee != null) {
          Employee.Dispose;
       }
}

Wäre das so richtig und ein gangbarer Weg? Könnte ich dann nach dem Login auf der default.aspx das Sessionobjekt aufrufen, etwas so:

       Global.Employee.LoadByNo(12345);

low level Byteschieber (automotive)

16.840 Beiträge seit 2008
vor 8 Jahren

Du solltest sowas eigentlich überhaupt nicht in der Session speichern, dafür ist die Session nicht gedacht.
Wenn der Anwender zwei Fenster zeitgleich auf hat und das Session-Objekt bearbeitet, dann bekommst Du Seiteneffekte, die Du sicherlich nicht haben willst.

Von globalen Elementen sollte man ganz die Finger weg lassen bei Webanwendungen.
Du weisst nie, ob der Anwender wirklich die nächste Seite öffnet oder nicht, oder wann das passiert.
Du müllst Dir also im schlimmsten Fall den RAM mit Objekten voll, die Du nicht (mehr) brauchst.

skynet74 Themenstarter:in
5 Beiträge seit 2016
vor 8 Jahren

Okay, das verstehe ich gut. Die Frage ist, wie würdest Du ca. 10 String Variablen eines angemeldeten Users und ggf. noch 10 weitere Umgebungsvariablen (GUID unsere Telefonanlage) halten? Sprich Username/Name/Vorname/eMail usw. Die benötige auf nahezu jeder Seite. Soll ich die immer und immer wieder neu aus der DB laden? Das geht auch nur bedingt, da nach dem Login auch über webservices entschieden wird, ob es ein User aus Gruppe A oder B ist. Die Klasse ist auch readonly und wird nur 1x nach dem Login geladen.

Alles Andere wird logischerweise auf jeder Seite neu instanziert.

Hast Du eine bessere Idee?

low level Byteschieber (automotive)

T
2.224 Beiträge seit 2008
vor 8 Jahren

Wenn du deine Daten häufig brauchst, dann nutzt den Cache.
Dafür gibt es im HttpContext die entsprechende Property.
Du musst dich dann eben nur selbst darum kümmern, dass der Cache und die DB Daten synchron sind.

MSDN Link:
https://msdn.microsoft.com/en-us/library/system.web.caching.cache%28v=vs.110%29.aspx

Bau dir am besten einen Wrapper wie CacheManager/CacheHelper der dann die Opterationen zum lesen/schreiben und ggf. auch löschen umsetzt.
Dann hast du auch direkt einen Zentralen Anlaufpunkt um deine Daten zu speichern und zu synchronieren.
Die Session ist eher dafür gedacht Benutzerdaten zu speichern.
Aber du willst ja eher Anwendungsweit deine Daten zwischenspeichern.
Und genau dafür ist der Cache gedacht 😃

Hoffe du hast jetzt einen guten Anlaufpunkt und kannst dein Problem damit lösen.

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.840 Beiträge seit 2008
vor 8 Jahren

Das Read-Only hab ich irgendwie überlesen; dann ist es halb so schlimm, solang Du es nicht überladest.
Du kannst in der Session nicht grenzenlos große Objekte ablegen. Ansonsten musst Du einen anderen Cache-Container verwenden.

Dann würde ich dennoch nicht von der Action oder der View direkt auf die Session zugreifen, sondern Du erstellst einen zB. ICachingService, der in seiner Logik einfach auf die Session zugreift (Dependency Injection).

In der Action fragst Du dann einfach den ICachingService nach dem aktuellen Objekt.
So kannst Du bei Bedarf die Logik sehr schnell (zB. auf einen Redis Cache) austauschen, ohne, dass Du die Webanwendung anfassen musst.

skynet74 Themenstarter:in
5 Beiträge seit 2016
vor 8 Jahren

Vielen Dank Abt, ich schau mir die Interfaces ebenfalls an.

Danke auch an T-Virus für den Cache-Tipp.

Ich schau mir beides genau an und entscheide dann. Es handelt sich wie gesagt um wenige Variablen und die sind alle ReadOnly.

low level Byteschieber (automotive)