» »

Session v ASP.NET

Session v ASP.NET

King80 ::

Pozdravljeni,

v asp.netu razvijam neko zadevo, ki glede na logiranega uporabnika nariše drevo (uporabljam TreeView objekt). Kako je najbolje delati z Sessioni v aspju. Zdaj imam narejeno tako, da mi drevo nariše z podatki iz ArrayLista. S tem ko uporabnik klika po treeviewu mu sproti gradim ArrayList, ki ga ob post backu zopet narišem.
Nekako tako:
Session["podatki"] = MyArrayList;

Obstaja kakšna boljša rešitev v tem primeru, ker mislim da bi moral dati kar cel treeview v Session, da bi mi pravilno delovalo, kar pa zna biti precej počasno ?

Hvala in lp

King80 ::

Je kdo, ki bi mi znal pomagat ?

NavadniNimda ::

ArrayList in drugi reference type objekti spravijo v Session (ali kamorkoli) le referenco, torej pointer. Ni se ti treba sekirati zaradi tega, paziti moraš le na sinhronizacijo v primeru, če obstaja možnost, da se v nek objekt piše in bere hkrati. Ker je Session serializiran, torej NI PROBLEMA, hitrost bo največja možna.

Če bi pa pisal v recimo Application ali Cache objekt, pa bi moral paziti, saj bi do njega lahko dostopali tudi drugi thread-i.

BlueRunner ::

@NavadniNimda: Beep. Nepopoln odgovor.

Če ima stran @Page atribut Session="ReadOnly", potem je možno iz Session seznama samo brati, pri čemer pa ni serializacije dostopov, temveč se uporablja reader-writer vzorec zaklepanja: to pomeni, da lahko več tako označenih strani istočasno dobi isto instanco objekta, saj se med seboj ne blokirajo. Seveda, če je vsebina seznama shranjena po metodi InProc. Če uporabljaš karkoli drugega, razen InProc sistema shranjevanja instanc objektov, potem morajo biti objekti označeni kot Serializable, njihovo spreminjanje pa sledi neki drugi logiki.

Če je objekt spremenljiv (mutable) oziroma če ne uporablja sinhronizacije, potem so težave praktično zagotovljene. Najlažje se jim je izogniti z uporabo vzorca copy-on-write. Narediš kopijo stanja, jo po potrbi dopolniš, nato pa originalno vrednost nadomestiš s kopijo (novimi podatki). Nekoliko potratno s pomnilnikom, ampak predvidljivo, enostavno in predvsem varno za uporabo.

@King80: Tako kot si jo opisal, je tvoja rešitev čisto OK. Kaj ti daje slab občutek, da morda nekaj ni prav?

King80 ::

Občutek, da nekaj ni prav mi daje gradnik TreeView, ker sta v bistvu 2 in eden je lahko tudi visible=false. Verjetno bi moral tudi to kdaj je kateri visible zapisat v Session 8-O

BlueRunner ::

Hm... sicer bi moral poznati strukturo aplikacije, ki jo izdeluješ, vendar pa se mi zdi, da poskušaš narediti navigacijo po drevesu.

Če to delaš na eni sami .aspx strani (npr. navigacija po katalogu tipov artiklov), potem lahko morda izkoristiš ViewState, pa se ti bo ta vrednost prenašala preko HTML-ja (skrito INPUT polje z ViewState podatki).

Če pa je to skupna komponenta za več strani (npr. navigacija po spletnem mestu), pa razmisli, če jo lahko izločiš v .master stran in potem na njej uporabiš ViewState.

Pri temu pa samo razmisli, če je smiselno uporabljati ViewState, saj ti bo ta dal na vsako zahtevo in odgovor še vse podatke, ki jih drevo v določenem trenutku vsebuje. Kar pomeni, da bodo zahteve po velikosti precej narasle, posledično pa bi odzivnost strani upadla.

Session je tako smotrno uporabiti, kadar postane ViewState večji od nekaj kB, saj s tem odplača nekaj več kode in konstantne porabe pomnilnika na strežniku z veliko večjo odzivnostjo spletnega mesta. V tem primeru pa poglej tudi to, da ViewState-a na komponenti ne uporabljaš (privzeto je vključen), saj boš s tem povezavo po nepotrebnem obremenjeval (višja latenca == slabša odzivnost).

Kar se pa tiče izgradnje celotnega drevesa v trenutku, ko se seja vzpostavlja, pa bi moral vedeti, če se to veže tudi na avtentikacijo (prijavo uporabnika). Če drevo gradiš šele po avtentikaciji (prijavi), potem ga je smiselno v celoti zgraditi že pri samem procesu prijave, čeprav bo to pomenilo krajši zastoj zaradi trajanja izdelave. Smiselno pa je to zato, ker je to zadnja točka, kjer bo uporabnik še toleriral sekundo ali celo dve sekundi pavze. Od prijave naprej pa morajo zadeve teči hitro in gladko.

Zgodovina sprememb…

King80 ::

To glede gradnje drevesa takoj po uspešni prijavi niti ni tako slaba ideja, ker potem uporabnik pride na stran kjer je že vse pripravljeno, edino še poklikat mora. Torej v tem primeru naj zgradim drevo takoj po prijavi in ga porinem v session ? Nisem tako vešč, vendar ali se da iz prijavne forme dostopat do glavne forme ? Viewstate je torej namenjen shranjevanju podatkov na gradnikih, da ga ni potrebno ob postbacku vedno na novo risat. Sem prav razumel ?

Lep pozdrav

NavadniNimda ::

@BlueRunner: za Session vemo, da se vsi requesti izvajajo na istem threadu, torej je serializacija že implicitna, odnosno ni pod vprašanjem. Za kompleksnejše R/w interakcije pa je prav gotovo potrebno izstresti iz rokava še kak trik, sicer se strežnik hitro odzove s kakšnim vetom. :)

King80: prosim nehaj komplicirati in daj TreeView objekt v Session kot si si zamislil in kot ti je nakazal BlueRunner. Vsi objekti so thread-varni, če ne pišeš v njih. Tule je pa njihov edini lastnik Session, ki laufa na enem threadu, torej so varni tudi, če pišeš v njih. Ko shranjuješ objekt se shrani le pointer, torej je tvoje prvotno vprašanje popolnoma rešeno (in se ni za bati, da boš imel počasno kodo zaradi tega).

BlueRunner ::

@NavadniNimda: tc, tc, tc... For most practical purposes and reasons. Ampak ...

@King80: Mah ja. NN ima prav. Skrajšaj si muke ni naredi aplikacijo takole:
- pri uspešni prijavi naredi drevo v pomnilniku (to je tisti tvoj ArrayList) in ga shrani v Session.
- pri vsaki zahtevi risanja drevesa, če je bila stran poklicana neposredno (!this.IsPostBack), preberi ta svoj ArrayList iz Session in premeči elemente v TreeView.
- na TreeView instanci pusti EnableViewState na true.

- Nikoli ne spreminjaj neposredno (dodajaj ali briši elementov) ArrayList, ki si ga "prebral" iz Session. Če moraš vsebino spremeniti, prepiši elemente v nov ArrayList, nato pa tega novega zapiši v Session.

- Nikoli ne spreminjaj neposredno vrednosti na objektih, ki jih imaš shranjene v tem ArrayList-u, temveč uporabi enak postopek kot zgoraj (naredi nov ArrayList, prenesi nespremenjene objekte, za "spremenjen" objekt naredi novega z novimi vrednostmi).

Na ta način ti bo aplikacija načeloma vedno delovala pravilno, ne glede končno izvedbo hranjenja stanja. Deloval ti bo tako Session v vseh odtenkih (InProc, Sql, SessionServer), kot tudi Cache, če ga boš začel uporabljati kdaj kasneje (morda za objekte, ki so skupni več sejam).

K.I.S.S.

King80 ::

Sem ubogal vaše nasvete, dal moje gradnike v Session in stvarca dela tako kot je treba.

Imam pa še eno butasto vprašanje :
je dobro dati tudi database connection v Session in se potem sklicevati na Session, ko ga rabim, ali pa je čisto OK, če je Connection "javen" ???

Hvala in lep pozdrav

Zgodovina sprememb…

  • spremenil: King80 ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Predstavitev dvojiškega drevesa z seznamom

Oddelek: Programiranje
141928 (1528) ktka
»

[Android] Bluetooth aplikacija

Oddelek: Programiranje
51082 (945) marjan_h
»

[ASP.NET] Dostop do dinamično kreiranih kontrol

Oddelek: Programiranje
81284 (1130) KalEl
»

[ ASP.NET ] Vprašanje glede podajanja parametrov

Oddelek: Programiranje
151562 (1293) salesky
»

[ASP.NET]

Oddelek: Programiranje
61319 (1173) OmegaM

Več podobnih tem