-----------------------------------------------------------

New Message on MumbaiUserGroup

-----------------------------------------------------------
From: soniashish
Message 1 in Discussion

 
What is Caching?
Caching is a technique of persisting the data in memory for immediate access to 
requesting program calls. Many in the developer community consider caching as one of 
the features available to improve performance of Web applications.  
Why Caching?
Consider a page that has list of Employee name, contact numbers and mail-Ids of 
existing employees of a company on an intranet accessible by all employees. This is 
very useful information that is available throughout the company and could also be one 
of the most accessed pages. The functionality of adding, updating or deleting is 
usually less intensive compared to more transaction-based systems like Purchase 
ordering, Voucher creation etc. Now in a normal scenario the process of querying 
database for each request is not cost-effective in terms of server resources, hence is 
lot better to cache or persist the data to avoid this costly loss of resources.  
The .NET Advantage
ASP.NET provides the flexibility in terms of caching at different levels. 
Page Level Output Caching
This is at the page level and one of the easiest means for caching pages. This 
requires one to specify Duration of cache and Attribute of caching.
Syntax: <%@ OutputCache Duration="60" VaryByParam="none" %>
The above syntax specifies that the page be cached for duration of 60 seconds and the 
value "none" for VaryByParam* attribute makes sure that there is a single cached page 
available for this duration specified. * VaryByParam can take various "key" parameter 
names in query string. Also there are other attributes like VaryByHeader, VaryByCustom 
etc. Please refer to MSDN for more on this.  
Fragment Caching
Even though this definition refers to caching portion/s of page, it is actually 
caching a user control that can be used in a base web form page. In theory, if you 
have used include files in the traditional ASP model then this caching model is like 
caching these include files separately. In ASP.NET more often this is done through 
User Controls. Initially even though one feels a bit misleading, this is a significant 
technique that can be used especially when implementing "n" instances of the controls 
in various *.aspx pages. We can use the same syntax that we declared for the page 
level caching as shown above, but the power of fragment caching comes from the 
attribute "VaryByControl". Using this attribute one can cache a user control based on 
the properties exposed.  
Syntax: <%@ OutputCache Duration="60" VaryByControl="DepartmentId" %>
The above syntax when declared within an *.ascx file ensures that the control is 
cached for 60 seconds and the number of representations of cached control is dependant 
on the property "DepartmentId" declared in the control. Add the following into an 
*.ascx file. Please note the use of tag "Control" and the cache declaration. <%@ 
Control Language="C#"%> <%@ outputcache duration="60" varybycontrol="DepartMentId" %> 
<script runat="server">    private int _Departmentid=0;         public int 
DepartMentId   {     get{return _Departmentid;}     set{_Departmentid =value;}   }    
//Load event of control   void Page_Load(Object sender, EventArgs e)   {            
lblText.Text = "Time is " + DateTime.Now.ToString() + " for Department id = " + 
_Departmentid + "\n";        }  </script> <asp:Label id="lblText" 
runat="server"></asp:Label> Add the following to an *.aspx file. Please note the way 
"Register" tag is used; the declaration of control using syntax 
<[TagPrefix]:[TagName]>; Usage of property 
"DepartMentId". Open the page in two browsers and closely watch the Base form timing 
and the User control timing. Also note that the following page results in two copies 
or representation of user control in the cache. <%@ Page Language="C#" Trace="true" %> 
<%@ Register TagPrefix="CacheSample" TagName="Text" Src="CachingControl.ascx" %> 
<script runat="server">    void Page_Load(Object sender, EventArgs e)    {     
this.lbltime.Text ="Base form time is " + DateTime.Now.ToString() + "\n";   }  
</script> <html> <head> </head> <body>   <form runat="server">     <table>       
<tbody>         <tr>           <td>             <asp:Label id="lbltime" 
runat="server"></asp:Label>           </td>         </tr>         <tr>           <td>  
           <CACHESAMPLE:TEXT id="instance1" runat="Server" DepartMentId="0">           
      </CACHESAMPLE:TEXT>           </td>         </tr>         <tr>           <td>    
         <CACHESAMPLE:TEXT id="instance2" runat="Server" DepartMentId="1">           
</CACHESAMPLE:TEXT>           </td>         </tr>       </tbody>     </table>     
</form> </body> </html> Application Level Caching 
With Page level Output caching one cannot cache objects between pages within an 
application. Fragment caching is great in that sense but has limitations by using user 
controls as means to do. We can use the Cache object programmatically to take 
advantage of caching objects and share the same between pages. Further the 
availability of different overloaded methods gives a greater flexibility for our Cache 
policy like Timespan, Absolute expiration etc. But one of the biggest takes is the 
CacheDependancy. This means that one can create a cache and associate with it a 
dependency that is either another cache key or a file.  
In almost all Web applications there could be numerous master tables that act as 
lookups to application specific tables. For e.g. if you take up adding a Employee, 
usually one has master tables like "tblQualification" to get list of qualifications, 
"tblLocations" to get list of locations etc. These tables* are usually set during the 
initial application configuration phase and could be modified once a month or even 
less than that. Hence it makes sense for us to use them in our Cache rather than 
making calls to database on each request. But then what Cache Policy do we adopt?
We cannot hold these objects in Cache for entire application instance, because if 
anybody changes data in these tables one has to also refresh the cache. It is here 
that CacheDependancy can be used.  
<CLASS="SMALLESTBLACK">* Even though these tables are less frequently used for 
updates, they are extensively used in our select statements through out the 
applications.  
</CLASS>Find below the snippet that uses CacheDependancy. Here what I have done is to 
provide a list view of existing employees. You need to create a Database in Sql 
Server, setup some data before you can continue. The schema scripts are enclosed in 
the article.  
� Add database connection value in Web.Config and change the value as per your setup. 
<appSettings>   <add key="conn" value="Data 
Source=vishnu;trusted_connection=yes;Initial Catalog=Users"/> </appSettings>
� First I get the dataset into which I fill the user list. But before this I check for 
the cache initially if it exists I directly cast it to a dataset, if not create a 
cache again.
daUsers.Fill(dsUsers,"tblUsers");
� I create the cache with "Users" as key using Cache.Insert* and link this with a file 
"Master.xml". This "Master.xml" is a XML file that contains Master data of 
"tblQualifications" and "tbllocations". I have used "Server.MapPath" to get the 
physical path of the file on the server. The CacheDependancy instance will make sure 
that any change in this dependency file means that you need to recreate your cache key 
definition. This is a great feature to use since I can recreate my cache only when 
required instead of caching the data at the page level. 
Cache.Insert("Users",dsUsers,  new 
System.Web.Caching.CacheDependency(Server.MapPath("Master.xml")) , 
DateTime.Now.AddSeconds(45),TimeSpan.Zero); * For other overloaded parameters refer 
MSDN.   �  Also note how we could use trace within to add my own statements. 
HttpContext.Current.Trace.Write("from Database.."); <%@ Page Language="c#" 
Trace="true" %> <%@ import Namespace="System" %> <%@ import Namespace="System.Data" %> 
<%@ import Namespace="System.Data.SqlClient" %> <%@ import 
Namespace="System.Configuration" %> <%@ import Namespace="System.Web" %> <%@ import 
Namespace="System.Collections" %> <%@ import Namespace="System.IO" %> <script 
runat="server"> void Page_Load(Object sender, EventArgs e) {      DataSet dsUsers;   
try   {   if(Cache["Users"]==null)   {       SqlConnection cn ;   dsUsers = new 
DataSet("new");   cn = new 
SqlConnection(ConfigurationSettings.AppSettings.Get("conn"));   SqlDataAdapter 
daUsers;   daUsers = new SqlDataAdapter("Select * from tblUsers",cn);   cn.Open();   
daUsers.Fill(dsUsers,"tblUsers");      //Update the cache object   
Cache.Insert("Users",dsUsers, new 
System.Web.Caching.CacheDependency(Server.MapPath("Master.xml")),   
DateTime.Now.AddSeconds(45),TimeSpan.Zero);   
HttpContext.Current.Trace.Write(DateTime.Now.AddSeconds(45).ToString() + " is expiry 
time..");   cn.Close();   cn.Dispose();   HttpContext.Current.Trace.Write("from 
Database..");   lblChange.Text ="From the database....";   }   else   {     
HttpContext.Current.Trace.Write("From cache..");   lblChange.Text ="From the 
cache....";   dsUsers= (DataSet) Cache["Users"];   }      dlUsers.DataSource =dsUsers; 
  dlUsers.DataMember = dsUsers.Tables[0].TableName ;   //lblChange.Text += 
Server.MapPath("Master.xml");   this.DataBind();   }   catch(Exception ex)   {   
lblChange.Text = ex.Message;   }   }   </script> <!DOCTYPE HTML PUBLIC "-//W3C//DTD 
HTML 4.0 Transitional//EN" > <html> <head>   <title>Cache Dependency Tester</title>    
<meta content="Microsoft Visual Studio 7.0" name="GENERATOR" />   <meta content="C#" 
name="CODE_LANGUAGE" />   <meta content="JavaScript" name="vs_defaultClientScript" />  
 <meta content="http://schemas.microsoft.com/intellisense/ie5"; name="vs_targetSchema" 
/> </head> <body ms_positioning="GridLayout">   <form id="Form1" method="post" 
runat="server">     <asp:DataList id="dlUsers" style="Z-INDEX: 101; LEFT: 44px; 
POSITION: absolute; TOP: 104px"   runat="server" Height="148px" Width="343px" 
BorderWidth="1px" GridLines="Horizontal" CellPadding="4"    BackColor="White" 
ForeColor="Black" BorderStyle="None" BorderColor="#CCCCCC">       <SelectedItemStyle 
font-bold="True" forecolor="White"         backcolor="#CC3333"></SelectedItemStyle>    
   <FooterStyle forecolor="Black" backcolor="#CCCC99"></FooterStyle>       
<HeaderStyle font-bold="True" forecolor="White" backcolor="#333333"></HeaderStyle>     
  <ItemTemplate>         <table>           <tr>             <td>               
<%#DataBinder.Eval(Container.DataItem,"UserId")%></td>             <td>               
<%#DataBinder.Eval(Container.DataItem,"FirstName")%></td>             <td>             
  <%#DataBinder.Eval(Container.DataItem,"LastName")%></td>           </tr>         
</table>       </ItemTemplate>     </asp:DataList>     <asp:Label id="lblChange" 
style="Z-INDEX: 102; LEFT: 46px; POSITION: absolute; TOP: 63px" runat="server"  
Height="28px" Width="295px"></asp:Label>     <asp:Button id="btnMaster" 
style="Z-INDEX: 103; LEFT: 50px; POSITION: absolute; TOP: 293px"        
onclick="btnMaster_Click" runat="server" Text="Refresh Master"></asp:Button>   </form> 
</body> </html> We created the page that initiates and uses the Cache. For testing 
purpose we need another page that will overwrite this "Master.xml" on click of a 
button for which the code snippet is as follows. This ideally should be our master 
maintenance page that adds/updates Master records in database and overwrites the XML. 
But to make it easy I have just written an overwriting sample. <%@ Page Language="C#" 
Trace="true"%> <%@ import Namespace="System" %> <%@ import Namespace="System.Data" %> 
<%@ import Namespace="System.Data.SqlClient" %> <script runat="server">    void 
btnMaster_Click(Object sender, EventArgs e)     {       //Call save function       
this.Save();        }        void Save()     {       try       {            
SqlConnection cn ;         DataSet dsUsers = new DataSet("Users"); //I have used this 
to get the Connectionstring from the  //Configuration file. cn = new 
SqlConnection(ConfigurationSettings.AppSettings.Get("conn"));          SqlDataAdapter 
daQualification;         SqlDataAdapter daLocations;            daQualification = new 
SqlDataAdapter("Select * from tblqualifications",cn); daLocations = new 
SqlDataAdapter("Select * from tblLocations",cn);  cn.Open();         
daQualification.Fill(dsUsers,"tblqualifications");         
daLocations.Fill(dsUsers,"tblLocations");         
HttpContext.Current.Trace.Write("Masters data up.."); //Overwrite the XML file. Also 
please read MSDN on the overloaded parameters for WriteXml         
dsUsers.WriteXml(HttpContext.Current.Server.MapPath("Master.xml"),XmlWriteMode.WriteSchema);
         cn.Close();         cn.Dispose();          }       catch(Exception ex)       
{         throw new Exception(ex.Message);       }        }  </script> <html> <head> 
</head> <body>   <form runat="server">     <span>      <table>       <tbody>         
<tr>           <td>             <label id="lblRefresh" runat="server">Rewrite the XML 
File by clicking the button             below.</label>            </td>         </tr>  
       <tr align="middle">           <td>             <asp:Button id="btnMaster" 
onclick="btnMaster_Click" runat="server" Text="Write XML"></asp:Button>           
</td>         </tr>       </tbody>     </table>     </span>   </form> </body> </html> 
Now once you have created the above pages i.e. one that implements caching and other 
that overwrites the dependency file, create two instance of browser and open the cache 
implementation page and note for trace, label text; open the other instance of browser 
with the page which overwrites the XML. Note the former, the first time it fetches 
data from the database and the subsequent request will be from cache till your 
expiration time of 45 seconds is reached or anyone overwrites or changes the 
"Master.xml" file. Also give a look on Timespan parameter since you have a concept of 
Sliding expiration that can also be implemented. Keep refreshing the first page and 
you will see that trace indicates the cached page retrieval. Click the overwrite XML 
button on the latter page that would overwrite the XML and again refresh the former 
page to note that the data is retrieved from database. Though in this example I have 
not shown any direct relation between the cached data and the dependency file (like 
get values from dependency file and merge with cached object etc) in terms of 
integrated usage, this could very easily be designed and implemented. Dependency 
caching is a powerful technique that .NET supports and should be utilized wherever 
applicable.  
DBScripts.sql *************  CREATE DATABASE [Users]   GO  use [Users] GO  CREATE 
TABLE [dbo].[tblLocations] ( [LocationId] [int] IDENTITY (1, 1) NOT NULL , [Name] 
[varchar] (60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , [Description] [varchar] 
(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL  ) ON [PRIMARY] GO  CREATE TABLE 
[dbo].[tblQualifications] ( [QualificationId] [int] IDENTITY (1, 1) NOT NULL , [Name] 
[varchar] (60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , [Description] [varchar] 
(100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL  ) ON [PRIMARY] GO  CREATE TABLE 
[dbo].[tblUsers] ( [UserId] [int] IDENTITY (1, 1) NOT NULL , [FirstName] [varchar] 
(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , [LastName] [varchar] (60) COLLATE 
SQL_Latin1_General_CP1_CI_AS NOT NULL , [QualificationId] [int] NULL , [LocationId] 
[int] NULL  ) ON [PRIMARY] GO  ALTER TABLE [dbo].[tblLocations] ADD  CONSTRAINT 
[PK_tblLocations] PRIMARY KEY  CLUSTERED  ( [LocationId] )  ON [PRIMARY]  GO  ALTER 
TABLE [dbo].[tblQualifications] ADD  CONSTRAINT [PK_tblQualification] PRIMARY KEY  
CLUSTERED  ( [QualificationId] )  ON [PRIMARY]  GO  ALTER TABLE [dbo].[tblUsers] ADD  
CONSTRAINT [PK_tblUsers] PRIMARY KEY  CLUSTERED  ( [UserId] )  ON [PRIMARY]  GO  ALTER 
TABLE [dbo].[tblUsers] ADD  CONSTRAINT [FK_tblUsers_tblLocations] FOREIGN KEY  ( 
[LocationId] ) REFERENCES [dbo].[tblLocations] ( [LocationId] ), CONSTRAINT 
[FK_tblUsers_tblQualifications] FOREIGN KEY  ( [QualificationId] ) REFERENCES 
[dbo].[tblQualifications] ( [QualificationId] ) GO 

-----------------------------------------------------------

To stop getting this e-mail, or change how often it arrives, go to your E-mail 
Settings.
http://groups.msn.com/MumbaiUserGroup/_emailsettings.msnw

Need help? If you've forgotten your password, please go to Passport Member Services.
http://groups.msn.com/_passportredir.msnw?ppmprop=help

For other questions or feedback, go to our Contact Us page.
http://groups.msn.com/contact

If you do not want to receive future e-mail from this MSN group, or if you received 
this message by mistake, please click the "Remove" link below. On the pre-addressed 
e-mail message that opens, simply click "Send". Your e-mail address will be deleted 
from this group's mailing list.
mailto:[EMAIL PROTECTED]

Reply via email to