在 ASP.NET 中支援資料庫緩衝相關性

來源:互聯網
上載者:User

Jeff Prosise

下載本文的代碼: WickedCode0304.exe (135KB)

開發人員都喜歡 ASP.NET 應用程式緩衝。 一個原因是 ASP.NET 能夠在放入緩衝中的項與檔案系統中的檔案之間建立相關性。 如果相關性所針對的檔案更改,ASP.NET 會自動將相關項目從緩衝中刪除。 通過與緩衝刪除回叫(當快取項目刪除時向所有關注方廣播通知)結合,緩衝相關性為開發人員提供了方便,使他們得以通過盡量減少耗時的檔案訪問來最大限度地提高效能,因為這使他們可以放心地允許檔案資料緩衝,而不必擔心資料變得陳舊。

儘管緩衝相關性非常實用,但是在 ASP.NET 1.0 中還缺乏一項至關重要的功能,這項功能一旦存在,將會使緩衝相關性隨著開發人員的美夢成真而得到證明。 這項功能就是對資料庫實體的支援。 在現實情況中,大多數 Web 應用程式都是從資料庫中提取資料,而不是從檔案中提取資料。 儘管 ASP.NET 能夠非常出色地將快取項目連結到檔案,但無法將快取項目連結到資料庫實體。 也就是說,可以將檔案內容讀入 DataSet 中,然後緩衝 DataSet,並使 DataSet 在初始化時所在的檔案更改時自動從緩衝中刪除。 但是,無法使用資料庫查詢來初始化 DataSet,因此也就無法緩衝 DataSet 並使 DataSet 自動在資料庫更改時廢棄。 這確實太糟糕了,因為正是由於資料庫訪問過多(例如,檔案 I/O 過多)而導致應用程式效能下降。

ASP.NET 不支援資料庫相關性並不意味著資料庫相關性不可能實現。 這一部分 Wicked Code 展示了擴充 ASP.NET 應用程式緩衝以支援資料庫相關性的技術。 它包含資料庫觸發器及擴充預存程序。 儘管這裡展示的實現僅適用於 Microsoft? SQL Server?,但是大體技術也適用於支援與檔案系統互動的觸發器和使用者定義過程的任何資料庫。

活動的資料庫相關性

先看一個示範。 圖 1 包含 ASP.NET 頁的原始碼,該 ASP.NET 頁顯示從名為 Quotes 的 SQL Server 資料庫中隨機播放的語錄。 要建立資料庫,請運行安裝指令碼。圖 2 顯示的是縮減形式的安裝指令碼。 完整的指令碼包含在本專欄附帶的可下載 zip 檔案中。 (可以在 SQL Server 查詢分析器內部執行該指令碼,或者使用 OSQL 命令從命令列執行該指令碼。) 每次提取該頁時,Page_Load 都使用資料庫的 Quotations 表中的所有記錄初始化一個 DataSet,然後從該 DataSet 中隨機播放一個記錄,並將其寫入到該頁中。 按 F5 若干次,您將看到出自某些著名(以及不那麼有名的)人士的各種隨機語錄, 3 所示。

圖 3 隨機語錄

由於某一原因,該頁被命名為 DumbDBQuotes.aspx。 每次請求該頁時都查詢資料庫並不是很明智的做法。 在每一次訪問該頁時都訪問資料庫(尤其是當資料庫是由遠程伺服器承載時)是產生不具延展性的資料庫的可靠方法。

ASP.NET 應用程式緩衝可解決資料庫訪問過多的問題。 如果 DataSet 已緩衝,便可以直接從記憶體(也就是緩衝)中提取它,從而避免了多餘的資料庫訪問。 DataSet 的緩衝非常容易。應用程式緩衝接受從 System.Object 派生的任何類型的執行個體。在 Microsoft .NET Framework 中,這意味著任何託管類型(包括 DataSet)的執行個體。 問題在於,如果在 DataSet 緩衝之後,它底層的資料庫更改,您為使用者提供的將是陳舊的資料。 可以實現一個定期重新查詢資料庫的解決方案,但是理想的解決方案應該滿足以下條件:不需要輪詢,並且在資料來源中的已更新資料一旦變得可用時便立即將其交付。

請看圖 4 和 圖 5,這兩個圖中包含更智能的語錄應用程式的原始碼。 SmartDBQuotes.aspx 不從資料庫中檢索語錄,而是從應用程式緩衝中擷取語錄。 Global.asax 填充緩衝,並在資料庫更改時重新整理緩衝。 下面是這兩段原始碼的試用說明:

在 Web 服務器的 C: 磁碟機的根目錄中建立一個名為 AspNetSql 的子目錄。 在 AspNetSql 內部,建立一個名為 Quotes.Quotations 的零位元組檔案。 確保 Everyone,或者至少 SYSTEM 和 ASPNET(安裝 ASP.NET 時建立的特殊帳戶)有權訪問 Quotes.Quotations。

將包含在本專欄的可下載程式碼範例中的 XSP.dll 複製到 SQL Server 的 binn 目錄(例如,C:\Program Files\Microsoft SQL Server\MSSQL\Binn)中,或者複製到 Web 服務器上 Windows 將在其中自動搜尋 DLL 的任意位置(例如,C:\Windows\System32)。

使用圖 6 中的已修改指令碼重建資料庫。

將 Global.asax 和 SmartDBQuotes.aspx 部署到 Web 服務器上的虛擬目錄(例如,wwwroot)中。

在瀏覽器中請求 SmartDBQuotes.aspx。 將頁面重新整理若干次,直到“The use of COBOL cripples the mind; its teaching should therefore be regarded as a criminal offense”語錄出現。

使用 SQL Server 企業管理器或您選擇的工具在 Quotes 資料庫的 Quotations 表中修改該語錄。 將它更改為“The use of Visual Basic? enriches the mind; its teaching should therefore not be regarded as a criminal offense”。 然後重新整理該頁,直到修改後的語錄出現。 請注意,出現的是新語錄而不是舊語錄,儘管查詢結果現在儲存在應用程式緩衝中。

剛才展示了 ASP.NET 應用程式緩衝現在可以與資料庫相關性結合起來,從而產生高效率的資料驅動應用程式。 問題是怎樣才能將兩者結合起來呢? 怎樣在緩衝的 DataSet 與資料庫之間形成連結,以及解決方案的延展性如何呢?

資料庫相關性的工作原理

從外部來看,DumbDBQuotes.aspx 和 SmartDBQuotes.aspx 很相似,產生的輸出也完全相同。 從內部來看,則兩者截然不同。 前者在每次被請求時都執行資料庫訪問,後者從應用程式緩衝中提取資料。 此外,SmartDBQuotes.aspx 使用資料庫相關性來確保快取資料隨著資料庫的更改而更改。 如果資料庫不更改,在應用程式的生命期中,將僅僅查詢一次資料庫。 如果資料庫更改,將再查詢一次資料庫以更新緩衝。

圖 7 資料庫相關性

圖 7 說明了資料庫相關性的工作原理。 當 Global.asax 將 DataSet 放入緩衝中時,在該 DataSet 與 C:\AspNetSql 目錄中名為 Quotes.Quotations 的檔案之間建立檔案系統相關性。Quotes.Quotations 是一個零位元組的訊號檔案,它唯一的作用是觸發 ASP.NET 應用程式的緩衝刪除邏輯。 下面是 Global.asax 中的語句,它建立將 DataSet 連結到 Quotes.Quotations 的 CacheDependency 對象:

new CacheDependency ("C:\\AspNetSql\\Quotes.Quotations")

Global.asax 還註冊自己的 RefreshCache 方法。當 DataSet 從緩衝中刪除(也就是當訊號檔案更改時)將調用該方法。該方法的代碼如下:

new CacheItemRemovedCallback (RefreshCache)

RefreshCache 的任務是查詢資料庫並將所產生的 DataSet 放入應用程式緩衝中。 它在應用程式啟動時調用一次,並在 DataSet 從緩衝中刪除時再調用一次。

這隻是整個體系的一半。 另一半涉及到資料庫。 圖 6 中是修改後的資料庫安裝指令碼,該指令碼在資料庫的 Quotations 表中添加一個 insert/update/delete 觸發器。

CREATE TRIGGER DataChanged ON QuotationsFOR INSERT, UPDATE, DELETEAS EXEC master..xsp_UpdateSignalFile 'Quotes.Quotations'GO

當在表中添加或刪除記錄以及當記錄更改時此觸發器觸發。 觸發器的工作原理是怎樣的呢? 它調用一個名為 xsp_UpdateSignalFile 的擴充預存程序(擴充預存程序是 SQL Server 中用來指代 Win32? DLL 中的代碼的委婉用語)。 然後該擴充預存程序使用 Win32 CreateFile 函數來更新 Quotes.Quotations 的時間戳記。

緩衝 DataSet 的生命期通過普通的檔案系統快取相關性與 Quotes.Quotations 關聯;更新 Quotations 表會導致資料庫觸發器觸發;而該觸發器調用“更新”Quotes.Quotations 的擴充預存程序,從而促使 ASP.NET 將 DataSet 從應用程式緩衝中刪除,並調用 Global.asax 的 RefreshCache 方法,之後該方法將執行一個全新的資料庫查詢,並重新啟動整個過程。

這個難題的最後一個關鍵點是擴充儲存儲存。 它存放在以前安裝的 XSP.dll 中。 此 XSP.dll 是用 Visual C++? 6.0 在非託管的 C++ 中編寫的。 它的原始碼顯示在圖 8 中。 訊號檔案的路徑 C:\AspNetSql 寫入程式碼到了該 DLL 中,但是您可以根據需要對它變更,並使它像檔案名稱一樣成為一個輸入參數。

在使用擴充預存程序之前,必須先安裝。 所執行的 SQL 安裝指令碼中的下列語句將 xsp_UpdateSignalFile 安裝到主要資料庫中,並對所有訪問者授予執行許可權:

USE masterEXEC sp_addextendedproc 'xsp_UpdateSignalFile', 'XSP.dll'GRANT EXECUTE ON xsp_UpdateSignalFile TO PUBLICGO

既然有 xp_cmdshell 這樣的內建擴充預存程序可以使用,為什麼要編寫自訂擴充預存程序來更新檔案的時間戳記呢? 這是出於安全方面的考慮:xp_cmdshell 可以用於所有形式的惡意企圖,而 xsp_UpdateSignalFile 則不然。 由於 xsp_UpdateSignalFile 差不多僅僅只是調用 Windows CreateFile 函數,因此還有著比 xp_cmdshell 更高的效率。

伺服器陣列

當 Web 服務器和資料庫伺服器安裝在同一台電腦上時,SmartDBQuotes.aspx 及相關的組件可以很好地工作,但是,如果資料庫安裝在另一台電腦上,會怎樣呢? 在 Web 場的情況下,又會怎樣呢? 基於資料庫觸發器、擴充預存程序以及檔案系統相關性的更改通知機制與多伺服器安裝相容嗎?

當然。 在群體環境下,基於檔案系統的 ASP.NET 緩衝相關性依賴於 Win32 檔案更改通知。 Win32 檔案更改通知還支援通用命名慣例 (UNC) 路徑名。 要在 Web 場中利用資料庫緩衝相關性,應讓訊號檔案駐留在資料庫伺服器上, 9 所示。 然後將指定訊號檔案網路地址的 UNC 路徑名傳遞給 CacheDependency 的建構函式:

new CacheDependency(@"\\ServerName\AspNetSql\Quotes.Quotations"),

圖 9 資料庫伺服器上的訊號檔案

要建立針對遠程檔案的相關性,最大的障礙是安全性。 預設情況下,當 ASP.NET 輔助進程與 Microsoft Internet Information Services (IIS) 5.0 配合工作,並配置為以相容模式運行在 IIS 6.0 下時,將以 ASPNET 身份運行。ASPNET 是無法在遠端電腦上進行身分識別驗證的本地帳戶。 在不更改配置的情況下,嘗試使用 UNC 路徑名建立緩衝相關性將產生拒絕訪問錯誤,即便為 Everyone 授予對遠程共用的存取權限也是如此。

有幾個相應的解決方案。 其中之一是將 ASP.NET 配置為使用可以在資料庫伺服器上進行身分識別驗證的域帳戶。 此更改非常容易實現: 只需在每個 Web 服務器的 Machine.config 中的<processModel> 部分指定該帳戶的使用者名稱和密碼即可。但是,許多公司的安全性原則可能禁止將密碼儲存在純文字的設定檔中。 如果您的公司就是這種情況,但是您仍然希望使用域帳戶來運行 ASP.NET,那麼可以升級到 .NET Framework 的 1.1 版(允許輔助進程憑據加密,從而使其可以安全地儲存在註冊表中),或者下載 1.0 版的Hotfix(作用相同)。 可以在 Stronger Credentials for processModel, identity, and sessionState 找到有關此Hotfix的資訊。

此技術的一種變化形式是:在兩台電腦上設定完全相同的本地帳戶(使用相同的使用者名稱和密碼),並將 ASP.NET 配置為以完全相同的本地帳戶在 Web 服務器上運行。

要解決包含訊號檔案的後端資料庫伺服器上的身分識別驗證問題,另一個方案是升級到 Windows Server 2003。這是 Windows Server 家族的最新成員,它內建 IIS 6.0,並允許 ASP.NET 輔助進程以 Network Service 的身份運行。 與 ASPNET 不同,Network Service 可以在遠端電腦上執行身分識別驗證。 或者,可以使用 ASP 中慣用的技巧,通過運行在 Web 服務器上的 COM+ 組件來訪問資料庫,並將該組件配置為以具有網路憑據的 principal 身份運行。

無論您選擇哪一種方案來使 ASP.NET 應用程式可以訪問遠程訊號檔案,關鍵的一點都是將資料庫緩衝相關性與 UNC 路徑名結合起來,以實現可伸縮的解決方案,也就是既可以很好地工作在 Web 場也可以很好地工作在單伺服器安裝情況下的解決方案。 無論是對於使用 ASP.NET 構建高效資料驅動應用程式的開發人員而言,還是對於使用者而言,這都是一個好訊息。

請通過 wicked@microsoft.com 將問題和評論發送給 Jeff

Jeff Prosise 是幾本書的作者,其中包括 Microsoft Press 出版的 Programming Microsoft .NET 和 Programming Windows with MFC。 他還是 Wintellect 的創辦人之一。Wintellect 是專攻 Microsoft .NET Framework 的諮詢和培訓公司。

轉到原英文頁面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.