當(dāng)前位置:首頁>>軟件教程>>新聞內(nèi)容  
為ASP.NET應(yīng)用緩存Oracle數(shù)據(jù)
作者:Narayan Veeramani(原作),ern(翻譯) 發(fā)布時(shí)間:2004-1-16 15:29:26 | 【字體:

為了創(chuàng)建可擴(kuò)展、高性能的基于WEB的應(yīng)用,ASP.NET提供一個稱為數(shù)據(jù)緩存(Data Caching)的特性。數(shù)據(jù)緩存支持將頻繁訪問的數(shù)據(jù)對象可編程地存放在內(nèi)存中。這一特性可擴(kuò)展以廣泛地提高查詢Oracle數(shù)據(jù)庫中數(shù)據(jù)的ASP.NET應(yīng)用的性能。本文講述一個策略,可用于采用Web Farm環(huán)境中的ASP.NET Web應(yīng)用緩存Oracle數(shù)據(jù)庫數(shù)據(jù)。這個技巧允許在內(nèi)存中緩存頻繁訪問的Oracle數(shù)據(jù)庫數(shù)據(jù),而不是頻繁訪問數(shù)據(jù)庫來取數(shù)據(jù)。這可以幫助避免到Oracle數(shù)據(jù)庫服務(wù)器的不必要的遠(yuǎn)路。進(jìn)一步的,文章提出了一個保持緩存數(shù)據(jù)以使其始終與Oracle數(shù)據(jù)同步的實(shí)現(xiàn)。

ASP.NET中的數(shù)據(jù)緩存

ASP.NET中的數(shù)據(jù)緩存由Cache類和System.Web.Caching命名空間中的CacheDependency類支持。Cache類提供向緩存插入和從中取出數(shù)據(jù)的方法。CacheDependency類允許為緩存中數(shù)據(jù)項(xiàng)的指定其依賴項(xiàng)。當(dāng)我們用InsertAdd方法將項(xiàng)目加入緩存中,可以指定一個項(xiàng)目的過期(expiration)策略。我們可以用Insert方法的absoluteExpiration屬性來定義緩存中一個項(xiàng)目的生命期。這個屬性允許你指定相應(yīng)數(shù)據(jù)項(xiàng)過期的準(zhǔn)確時(shí)間。也可以使用slidingExpiration屬性來指定項(xiàng)目過期的流逝時(shí)間(基于它被訪問的時(shí)間)。一旦一個項(xiàng)目過期,它從緩存中被清除。除非它再次被加入緩存中,否則再試圖訪問,將返回一個空值。

設(shè)定緩存依賴

ASP.NET使我們可以基于一個外部文件、目錄或另一個緩存項(xiàng)來定義一個緩存項(xiàng)的依賴,即所謂文件依賴與鍵依賴。若一個依賴項(xiàng)改變,緩存項(xiàng)自動失效并被從緩存中清除。當(dāng)相應(yīng)的數(shù)據(jù)源改變時(shí),我們可以用這種方法來從緩存中刪除項(xiàng)目。例如,若我們的應(yīng)用從一個XML文件中取數(shù)據(jù)并顯示在一個表格(grid)中,我們可以把文件中的數(shù)據(jù)存放到緩存中,并設(shè)定緩存依賴于那個XML文件。當(dāng)XML文件被更新,數(shù)據(jù)項(xiàng)就從緩存中被清除出去。這一事件發(fā)生時(shí),應(yīng)用重新讀入XML文件,最新的數(shù)據(jù)項(xiàng)副本被再一次插入緩存中。進(jìn)一步的,回調(diào)事件處理器可被設(shè)定為一個監(jiān)聽者,當(dāng)緩存項(xiàng)被刪除時(shí)得到通知。這使得我們不需要反復(fù)輪詢緩存來確定數(shù)據(jù)項(xiàng)是否已無效。

Oracle數(shù)據(jù)庫上的ASP.NET緩存依賴

現(xiàn)在考慮這樣一個情景:數(shù)據(jù)存放于Oracle數(shù)據(jù)庫中,一個ASP.NET應(yīng)用通過ADO.NET來訪問。進(jìn)一步,我們假設(shè)數(shù)據(jù)庫表中的數(shù)據(jù)一般是靜態(tài)的,并被這個Web應(yīng)用頻繁訪問。表上的DML操作很少而對數(shù)據(jù)有很多Select。這種情況是數(shù)據(jù)緩存技術(shù)的理想應(yīng)用。但不幸的是,ASP.NET并不允許設(shè)定一個緩存項(xiàng)依賴于存放在數(shù)據(jù)庫表中的數(shù)據(jù)。進(jìn)一步,現(xiàn)實(shí)世界中,基于Web的系統(tǒng),Web服務(wù)器和Oracle數(shù)據(jù)庫服務(wù)器總是會運(yùn)行在不同的機(jī)器上,使得緩存無效操作更有挑戰(zhàn)性。另外,多數(shù)基于Web的應(yīng)用采用Web farms,同一個應(yīng)用的實(shí)例在不同的Web服務(wù)器上跑以負(fù)載均衡。這種情況使得數(shù)據(jù)庫緩存問題稍稍復(fù)雜一些。

為了進(jìn)一步研究上述問題的解決方案,我們舉一個Web應(yīng)用的例子來說明如何實(shí)現(xiàn)。例子中,我們使用VB.NET實(shí)現(xiàn)的ASP.NET應(yīng)用,通過Oracle Data Provider for .NET (ODP)來訪問 Oracle 9i數(shù)據(jù)庫。

這個例子使用Oracle數(shù)據(jù)庫中一個名為Employee的表。我們?yōu)樵摫砩?/SPAN>insert, update, delete設(shè)定觸發(fā)器。這些觸發(fā)器調(diào)用一個封裝了一個Java存儲過程的PL/SQL函數(shù)。這個Java存儲過程負(fù)責(zé)更新緩存依賴的文件。

ASP.NET TierVB.NET實(shí)現(xiàn)

我們設(shè)計(jì)了含一個回調(diào)方法的監(jiān)聽類來處理緩存項(xiàng)無效時(shí)的通知。這個回調(diào)方法RemovedCallback用一個代理(delegate)函數(shù)來注冊;卣{(diào)方法onRemove的聲明必須與CacheItemRemovedCallback代理聲明又相同的簽名。

   Dim onRemove As CacheItemRemovedCallback = Nothing

   onRemove = New CacheItemRemovedCallback(AddressOf RemovedCallback)

       監(jiān)聽事件處理方法RemovedCallback負(fù)責(zé)處理數(shù)據(jù)庫觸發(fā)器的通知,其定義如下。若緩存項(xiàng)失效,可用數(shù)據(jù)庫方法調(diào)用getRecordFromdatabase()從數(shù)據(jù)庫取出數(shù)據(jù)。參數(shù)”key”指從緩存中刪除的項(xiàng)的索引位置。參數(shù)”value”指從緩存中刪除的數(shù)據(jù)對象。參數(shù)"CacheItemRemovedReason"指從緩存中刪除數(shù)據(jù)項(xiàng)的原因。

PublicSub RemovedCallback(ByVal key AsString, ByVal value AsObject,                                                  ByVal reason As CacheItemRemovedReason)

        Dim Source As DataView

        Source = getRecordFromdatabase()

        Cache.Insert("employeeTable ", Source, New

             System.Web.Caching.CacheDependency("d:\download\tblemployee.txt"),

             Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,

             CacheItemPriority.Normal, onRemove)

EndSub

       方法getRecordFromdatabase()負(fù)責(zé)查詢數(shù)據(jù)庫表Employee并返回一個DataView對象引用。它使用一個名為getEmployee的存儲過程來抽象從Employee表中取數(shù)據(jù)的SQL。這個方法有一個名為p_empid的參數(shù),表示Employee的主鍵。

PublicFunction getRecordFromdatabase (ByVal p_empid As Int32) As DataView

 

     Dim con As OracleConnection = Nothing

     Dim cmd As OracleCommand = Nothing

     Dim ds As DataSet = Nothing

 

      Try

          con = getDatabaseConnection(                             "UserId=scott;Password=tiger;Data Source=testingdb;")

          cmd = New OracleCommand("Administrator.getEmployee", con)

          cmd.CommandType = CommandType.StoredProcedure

          cmd.Parameters.Add(New OracleParameter("employeeId",                        OracleDbType.Int64)).Value = p_empid

          Dim param AsNew OracleParameter("RC1", OracleDbType.RefCursor)

          cmd.Parameters.Add(param).Direction = ParameterDirection.Output

          Dim myCommand AsNew OracleDataAdapter(cmd)

          ds = New DataSet

          myCommand.Fill(ds)

          Dim table As DataTable = ds.Tables(0)

          Dim index As Int32 = table.Rows.Count

          Return ds.Tables(0).DefaultView

 

    Catch ex As Exception

        ThrowNew Exception("Exception in Database Tier Method                                getRecordFromdatabase () " + ex.Message, ex)

        Finally

           Try

               cmd.Dispose()

           Catch ex As Exception

           Finally

               cmd = Nothing

           EndTry

           Try

               con.Close()

           Catch ex As Exception

           Finally

               con = Nothing

           EndTry

       EndTry

EndFunction

函數(shù)getDatabaseConnection接受一個連接字符串(connection stirng)為參數(shù),返回一個OracleConnection對象引用。

PublicFunction getDatabaseConnection(ByVal strconnection as string) As                   OracleConnection

       Dim con As Oracle.DataAccess.Client.OracleConnection = Nothing

       Try

           con = New Oracle.DataAccess.Client.OracleConnection

           con.ConnectionString = strconnection

           con.Open()

           Return con

       Catch ex As Exception

               ThrowNew Exception("Exception in Database Tier Method                                    getOracleConnection() " + ex.Message, ex)

       EndTry

EndFunction

Oracle數(shù)據(jù)庫Tier實(shí)現(xiàn)

       定義Employee表上DML事件的觸發(fā)器體如下。這個觸發(fā)器簡單的調(diào)用一個PL/SQL包裹函數(shù)來更新名為tblemployee.txt的操作系統(tǒng)文件。文件副本在兩臺機(jī)器(機(jī)器1和機(jī)器2)上更新。兩臺機(jī)器運(yùn)行同一個Web應(yīng)用的不同實(shí)例來均衡負(fù)載。這里administratorOracle數(shù)據(jù)庫的方案(schema)對象所有者。

begin

   administrator.plfile('machine1\\download\\ tblemployee.txt');

   administrator.plfile('machine2\\download\\ tblemployee.txt');

end;

       為更新緩存依賴文件,我們需要寫一個C函數(shù)或Java存儲過程。我們的例子中選擇了Java存儲過程,因?yàn)?/SPAN>Oracle數(shù)據(jù)庫服務(wù)器有一個內(nèi)置的JVM,使得書寫Java存儲過程很方便。必須有足夠的內(nèi)存分配給Oracle實(shí)例的系統(tǒng)全局區(qū)(SGA)中的Java池。靜態(tài)方法updateFile接受一個絕對路徑作為參數(shù),并在合適的目錄中創(chuàng)建緩存依賴文件。若文件已經(jīng)存在,則先刪除然后創(chuàng)建。

import java.io.*;

public class UpdFile {public static void updateFile(String filename)

{

   try {

        File f = new File(filename);

       f.delete();

       f.createNewFile();

   }

   catch (IOException e)

   {

      // log exception

   }

};

PL/SQL包裹實(shí)現(xiàn)如下。包裹函數(shù)以文件名為參數(shù),調(diào)用Java存儲過程中updateFile方法。

(p_filename IN VARCHAR2)

AS LANGUAGE JAVA

NAME 'UpdFile.updateFile (java.lang.String)';

Web Farm部署中的Oracle數(shù)據(jù)緩存

正如我們討論的例子中所示,Web服務(wù)器1和機(jī)器2構(gòu)成了一個Web Farm來為我們的Web應(yīng)用提供負(fù)載均衡。每臺機(jī)器運(yùn)行同一個Web應(yīng)用的一個實(shí)例。在這個情況下,每個實(shí)例可以擁有自己的存放在Cache對象中的緩存數(shù)據(jù)副本。當(dāng)Employee表改變,相應(yīng)的數(shù)據(jù)庫觸發(fā)器更新兩臺機(jī)器上的文件tblemployee.txt。每個實(shí)例都指定一個到tblemployee.txt的緩存依賴,Web Farm的兩個實(shí)例都可以正確更新,使得兩個實(shí)例上的數(shù)據(jù)緩存可以和數(shù)據(jù)庫表Employee保持同步。

結(jié)論

數(shù)據(jù)緩存是優(yōu)化Oracle數(shù)據(jù)庫上ASP.NET應(yīng)用的有效技巧。盡管ASP.NET不允許設(shè)定緩存的數(shù)據(jù)庫依賴,Oracle觸發(fā)器協(xié)同Java存儲過程可以擴(kuò)展ASP.NET緩存的威力從而允許Oracle數(shù)據(jù)庫緩存。這個技巧也可以適用于Web Farm部署。


文章來源:西部E網(wǎng)
 放生
 愚愛
 夠愛
 觸電
 白狐
 葬愛
 光榮
 畫心
 火花
 稻香
 小酒窩
 下雨天
 右手邊
 安靜了
 魔杰座
 你不像她
 邊做邊愛
 擦肩而過
 我的答鈴
 懷念過去
 等一分鐘
 放手去愛
 冰河時(shí)代
 你的承諾
 自由飛翔
 原諒我一次
 吻的太逼真
 左眼皮跳跳
 做你的愛人
 一定要愛你
 飛向別人的床
 愛上別人的人
 感動天感動地
 心在跳情在燒
 玫瑰花的葬禮
 有沒有人告訴你
 即使知道要見面
 愛上你是一個錯
 最后一次的溫柔
 愛上你是我的錯
 怎么會狠心傷害我
 不是因?yàn)榧拍畔?/a>
 親愛的那不是愛情
 難道愛一個人有錯
 寂寞的時(shí)候說愛我