ASP.NET-Session與複雜數據類型

原文連接:http://www.cnblogs.com/fish-li/archive/2013/05/28/3104750.htmlhtml

Session與複雜數據類型程序員

Session有三種工做模式,拿ASPX頁面來講,EnableSessionState指令有三個可選值:true, false, ReadOnlyweb

第一個

EnableSessionState="false",這個容易理解:不使用Session。sql

第二個

EnableSessionState="ReadOnly",從字面上來講,就是Session是隻讀的。
只讀的控件不容許用戶修改,然而Session的只讀模式是說:你能夠改,但我不保存你的修改。 這樣理解沒有問題吧。數據庫

第三個

EnableSessionState="true",表示Session支持可讀可寫。
當你更新了Session的內容以後,當前會話的全部Session數據將會被從新保存。安全

進程內Session容易丟失,且不支持多臺Web服務器共享數據,所以選擇這種保存方法的人很少, 大多數人會選擇狀態服務或者SQL Server來保存,那麼這裏就有一個問題須要關注了: 當Session模式是EnableSessionState="true"時,若是你訪問了一個複雜對象(不是系統值類型也不是字符串), 無論你有沒有修改它,Session的保存操做都會執行。 對於進程外Session,保存操做意味着須要執行序列化,還能夠會有網絡傳輸的開銷,它們會影響性能。服務器

若是上面的描述不容易理解的話,請看下面的示例代碼:cookie

string sessionValue = Session["s2"] as string;
if( sessionValue == null ) {
    Session["s2"] = "Fish Li";
    sessionValue = Session["s2"] as string;
}

當這個頁面首次運行時,Session被修改了,所以會有保存的操做發生。可是後面的訪問就不會有保存的動做。網絡

再看另外一段代碼:session

// TestData是一個自定義類型。
TestData sessionValue = Session["s1"] as TestData;
if( sessionValue == null ) {
    Session["s1"] = new TestData { IntValue = 5, StrValue = "Fish Li" };
    sessionValue = Session["s1"] as TestData;
}

此時每次執行這段代碼時,都會有保存操做發生(只要是EnableSessionState="true")。

我再重申一遍:這個問題只有當EnableSessionState="true",且訪問複雜對象(不是系統值類型也不是字符串)纔會發生。 對於進程內Session來講,這個問題的影響不大,可是對於進程外Session來講,會對性能產生一些影響, 到底有多大的影響,要根據Session的數據量以及用戶的併發度來決定。

列出這個問題只是想告訴你們:若是你確實須要使用Session,請儘可能在Session中保存【不可變】的簡單數據, 尤爲是不要保持Session的默認設置(EnableSessionState="true")。

檢驗這個問題的方法是:實現一個自定義的SessionStateStoreProviderBase派生類,而後調試觀察。 SessionStateItemCollection的二個索引器也會給你一個答案。

引伸一下服務器端的Session管理,web form作例子

web form網頁是基於HTTP的,它們沒有狀態, 這意味着它們不知道全部的請求是否來自 同一臺客戶端計算機,網頁是受到了破壞,以及是否獲得了刷新,這樣就可能形成信息的 丟失。因而,狀態管理就成了開發網絡應用程序的一個實實在在的問題。在ASP中可以經過Cookie 、查詢字符串、 應用程序、會話(Session) 等輕易解決這些問題。 如今在ASP.NET環境中,咱們依然可使用這些功能,而且功能更增強大。

狀態管理分爲服務端和客戶端兩種狀況, 這裏只是介紹 服務端狀態管理:

與Application對象不一樣的是, ASP.NET 的Session對象能夠在IIS服務器或者工做進程從新啓動時 恢復啓動前的狀態而不丟失其中的數據。這是由於存儲在Session中的因此信息都缺省的存儲在 一個做爲Windows服務運行的狀態服務器進程中。狀態能夠被序列化並以二進制形式保存在內存中。 程序員能夠懸着使用Microsoft Sql server數據庫來存儲數據。

狀態服務器服務和狀態信息能夠和web應用程序一塊兒存在於同一臺服務器上,也能夠保存到外部的 狀態服務器上。 爲了指定如何存儲信息,程序員能夠在web.config文件中編寫適當的配置。

ASP.NET會話狀態模塊在Web.config文件中<System.web>標記下的 標記的mode屬性來決定 該屬性的四種可能的值:** Off、 Inproc StateServer 和SQLserver**。

 1 Inproc是缺省的設置

它容許「無Cookie」的會話,以及在服務器以外存儲 會話數據。ASP.NET會話狀態模塊在Web.config文件中像下面這樣配置:

<sessionState mode="InProc" cookieless="false" timeout="20" />

在這個例子中,mode屬性設爲InProc(默認值),代表會話狀態要由ASP.NET存儲到內存中,並且 不用Cookie來傳遞會話ID。相反,會話ID要直接插入一個網頁URL的查詢字符串中。例如,採用 InProc模式並創建一個會話以後,調用一個假想的ASP.NET網頁時,須要採用下面這樣的URL:

http://my.website.com/(12mfju55vgblubjlwsi4dgjq)/education.aspx

圓括號中長長的字母、數字字符串12mfju55vgblubjlwsi4dgjq就是會話ID。ASP.NET引擎從查詢字符中提取會話ID,並將用戶 請求與特定會話聯繫起來。採起這種方式,無論Cookie仍是隱藏表單字段都用不着了。 因此,即便網頁中沒有使用表單,也能加入會話。

可是這種方法,應用程序的狀態將依賴於 ASP.NET進程, 當IIS進程崩潰或者正常重啓時,保存在 進程中的狀態將丟失。

 2 mode屬性設爲Off

和從前的ASP同樣,ASP.NET的會話狀態管理是要產生開銷的。因此,假如某個網頁不須要訪問 Session對象,開發者應將那個頁的Page預編譯指令的EnableSessionState屬性設爲False。 要爲整個網站禁用會話狀態,可在Web.config文件中將sessionState元素的mode屬性設爲Off。

爲了克服inproc 模式的缺點, ASP.NET 提供了兩種進程外保存會話狀態的方法。

 3 StateServer會話管理

將mode屬性設爲StateServer,也就是將會話數據存儲到單獨的內存緩衝區中,再由單獨一臺機器上運行

的Windows服務來控制這個緩衝區。狀態服務全稱是「ASP.NET State Service 」(aspnet_state.exe),

它由Web.config文件中的stateConnectionString屬性來配置。該屬性指定了服務所在的服務器,以及要監視的端口: 在這個例子中,狀態服務在一臺名爲myserver的機器的42424端口(默認端口)運行。要在服務器上改變端口,可編輯HKLM\SYSTEM\CurrentControlSet\Services\aspnet_state註冊表項中的Port值。
顯然,使用狀態服務的優勢在於進程隔離,並可在Web form中共享。 使用這種模式,會話狀態的存儲將不依賴於iis進程的失敗或者重啓,然而,一旦狀態服務停止,全部會話數據都會丟失。換言之,狀態服務不像SQL Server那樣能持久存儲數據;它只是將數據存儲在內存中。

4 用SQL Server進行會話管理

ASP.NET還容許將會話數據存儲到一個數據庫服務器中,方法是將mode屬性變成SqlServer。 在這種狀況下,ASP.NET嘗試將會話數據存儲到由sqlConnectionString屬性(其中包含數據源以及登陸服

務器所需的安全憑證)指定的SQL Server中。 爲了用恰當的數據庫對象來配置SQL erver,管理員還須要建立ASPState數據庫, 方法是運行WinDir\Microsoft.Net\Framework\Version文件夾中的InstallState.sql腳本(WinDir是服務

器的Windows文件夾,而Version是你使用的.NET框架版本的安裝文件夾)這個腳本文件我沒有找到,等作這個功能的時候再處理這個問題。 要配置SQL服務器,能夠在命令行中運行SQL Server 提供的命令行工具osql.exe

osql -S [ server name] -U [user] -P [password] <InstallSqlState.sql 例如 osql -S (local)\NetSDK -U sa -P "" -i InstallSqlState.sql

在這裏用戶名必須是SQL服務器上的sa賬號,或者具備同等權限的其餘賬號。有興趣的讀者能夠打開 這個腳本文件來了解ASP.NET是如何和SQL Server配合實現狀態管理的。
卸載這些表和存儲過程,可使用UninstallSqlState.sql腳本,使用方法與上面相似。

作好必要的數據庫準備工做後,將web.config 文件中的sessionstate 元素的mode改成"sqlserver" ,而且指定SQL鏈接字符串。具體以下:

mode="sqlserver" sqlConnectionString="data source=127.0.0.1; userid=sa; password="

配置好SQL Server後,應用程序代碼運行時就和InProc模式沒有什麼區別。但要注意的是,因爲數據不存

儲在本地內存,因此存儲會話狀態的對象須要進行序列化和反序列化,以便經過網絡傳給數據庫服務器,

以及從數據庫服務器傳回。這固然會影響性能。經過在數據庫中存儲會話狀態,可分別針對擴展性及可靠

性來有效地平衡性能。另外,能夠利用SQL Server的集羣,使狀態存儲不依賴於單個的SQL Server, 這樣就能夠爲應用程序提供極大限度的可靠性。

相關文章
相關標籤/搜索