选择显示字体大小

asp.net应用中缓存oracle数据(2)

     oracle数据库上的asp.net缓存依赖
  
    现在考虑这样一个情景:数据存放于oracle数据库中,一个asp.net应用通过ado.net来访问。进一步,我们假设数据库表中的数据一般是静态的,并被这个web应用频繁访问。表上的dml操作很少而对数据有很多select。这种情况是数据缓存技术的理想应用。但不幸的是,asp.net并不允许设定一个缓存项依赖于存放在数据库表中的数据。进一步,现实世界中,基于web的系统,web服务器oracle数据库服务器总是会运行在不同的机器上,使得缓存无效操作更有挑战性。另外,多数基于web的应用采用web farms,同一个应用的实例在不同的web服务器上跑以负载均衡。这种情况使得数据库缓存问题稍稍复杂一些。
  
    为了进一步研究上述问题的解决方案,我们举一个web应用的例子来说明如何实现。例子中,我们使用vb.net实现的asp.net应用,通过oracle data provider for .net (odp)来访问 oracle 9i数据库
  
    这个例子使用oracle数据库中一个名为employee的表。我们为该表上insert, update, delete设定触发器。这些触发器调用一个封装了一个java存储过程的pl/sql函数。这个java存储过程负责更新缓存依赖的文件。
  
    asp.net tier的vb.net实现
  
    我们设计了含一个回调方法的监听类来处理缓存项无效时的通知。这个回调方法removedcallback用一个代理(delegate)函数来注册。回调方法onremove的声明必须与cacheitemremovedcallback代理声明又相同的签名。
  
  dim onremove as cacheitemremovedcallback = nothing
  onremove = new cacheitemremovedcallback(addressof removedcallback)
  
    监听事件处理方法removedcallback负责处理数据库触发器的通知,其定义如下。若缓存项失效,可用数据库方法调用getrecordfromdatabase()从数据库取出数据。参数”key”指从缓存中删除的项的索引位置。参数”value”指从缓存中删除的数据对象。参数"cacheitemremovedreason"指从缓存中删除数据项的原因。
  
  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()负责查询数据库表employee并返回一个dataview对象引用。它使用一个名为getemployee的存储过程来抽象从employee表中取数据的sql。这个方法有一个名为p_empid的参数,表示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
  
    函数getdatabaseconnection接受一个连接字符串(connection stirng)为参数,返回一个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数据库tier实现
  
    定义employee表上dml事件的触发器体如下。这个触发器简单的调用一个pl/sql包裹函数来更新名为tblemployee.txt的操作系统文件。文件副本在两台机器(机器1和机器2)上更新。两台机器运行同一个web应用的不同实例来均衡负载。这里administrator指oracle数据库的方案(schema)对象所有者。
  
  begin
   administrator.plfile('machine1\\download\\ tblemployee.txt');
   administrator.plfile('machine2\\download\\ tblemployee.txt');
  end;
  
    为更新缓存依赖文件,我们需要写一个c函数或java存储过程。我们的例子中选择了java存储过程,因为oracle数据库服务器有一个内置的jvm,使得书写java存储过程很方便。必须有足够的内存分配给oracle实例的系统全局区(sga)中的java池。静态方法updatefile接受一个绝对路径作为参数,并在合适的目录中创建缓存依赖文件。若文件已经存在,则先删除然后创建。
  
  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包裹实现如下。包裹函数以文件名为参数,调用java存储过程中updatefile方法。
  
  (p_filename in varchar2)
  
  as language java
  
  name 'updfile.updatefile (java.lang.string)';
  
    web farm部署中的oracle数据缓存
  
    正如我们讨论的例子中所示,web服务器1和机器2构成了一个web farm来为我们的web应用提供负载均衡。每台机器运行同一个web应用的一个实例。在这个情况下,每个实例可以拥有自己的存放在cache对象中的缓存数据副本。当employee表改变,相应的数据库触发器更新两台机器上的文件tblemployee.txt。每个实例都指定一个到tblemployee.txt的缓存依赖,web farm的两个实例都可以正确更新,使得两个实例上的数据缓存可以和数据库表employee保持同步。
  
    结论
  
    数据缓存是优化oracle数据库asp.net应用的有效技巧。尽管asp.net不允许设定缓存的数据库依赖,oracle触发器协同java存储过程可以扩展asp.net缓存的威力从而允许oracle数据库缓存。这个技巧也可以适用于web farm部署。
    


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons