Professional ASP.NET 1.1 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Professional ASP.NET 1.1 [Electronic resources] - نسخه متنی

Alex Homeret

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Application State Management


State management is the persistence of objects or values throughout the lifetime of a web application or for the duration of a user's interaction with the application. ASP.NET provides four ways to manage state for your application (we will cover each in more detail later in the chapter):



User state (session):User state is controlled through the

Session object.

Session allows us to maintain data for a limited duration of time (the configurable default is 20 minutes), for a particular user and isolate that data from other users. For example, we could use

Session state to track the ad banners we have shown a particular user. If the user doesn't interact with the site within the configurable

Session time limit, their data expires and is deleted.



Application state:Application state is controlled through the

Application object.

Application allows us to maintain data for a given ASP.NET application. Settings made in

Application are accessible to all resources (ASP.NET page, web services, and so on) within our web application. For example, if we wanted to retrieve some expensive records out of a database and share it throughout our application, storing the data using

Application state would be very useful.



Transient application state (cache):Transient Application state is controlled through the

Cache object.

Cache is similar in functionality to

Application , in that it is accessible (shared memory) for the entire web application.

H owever, it adds some functionality not available to

Application , in the form of dependencies, callbacks, and expiration. For example, when our ASP.NET application started we might populate an object used by all ASP.NET pages from an XML file. We could store this object in the

Cache and also create a dependency for that item on the XML file the data originated from. If the XML file changed, ASP.NET will detect the file change and notify the

Cache to invalidate the entry. Caching is a very powerful feature of ASP. NET. The differences between

Application and

Cache are summarized later in the chapter.



Static variables:In addition to using the

Application or

Cache sytate, we can also use one of the object-oriented facilities of ASP.NET – static variables. When we can declare a static variable, only one copy of the variable is created no matter how many instances of the class are created. The static variable is accessible throughout our application and in some cases is more efficient than

Application . This is an advanced option and is discussed at the end of the chapter.



The use of

Application and

Session (and now

Cache ) in ASP.NET is identical to the use of

Application and

Session in ASP. You can simply use a string key and set a value:


' Set an Application value

Application("SomeValue") = "my value"

' Read an Application value

Dim someString As String

someString = Application("SomeValue")


These familiar semantics are carried forward and used for the

Cache , too:


' Set a Cache value

Cache("SomeValue") = "my value"


' Read a Cache value

Dim someString As String

someString = Cache("SomeValue")


Let's take a closer look at

Session ,

Application , and

Cache and how they relate to building web applications.


Session – Managing User State


Classic ASP's familiar

Session object is new and improved for ASP.NET. The major caveats for

Session use in classic ASP are:



Web farm challenges:

Session data is stored in memory on the server it is created on. In a web farm scenario, where there are multiple web servers, a problem could arise if a user was redirected to a server other than the server upon which they stored their

Session state. Normally, this can be handled by an IP routing solution where the IP address of the client is used to route that client to a particular server. However, some ISPs use farms of reverse proxies, where the client request may come through a different IP on each request. When a user is redirected to a server other than the server that contains their

Session data, poorly designed applications can break.



Supporting clients that don't accept HTTP cookies:Since the Web is inherently a stateless environment, to use

Session state the client and web server need to share a key that the client can present to identify its

Session data on subsequent requests. Classic ASP shared this key with the client through an HTTP cookie. While this scenario worked well for clients that accept HTTP cookies, it broke for the one percent of users that rejected HTTP cookies.



Both of these issues have been addressed in ASP.NET's

Session state, which supports several new features:



Web farm support:ASP.NET

Session now supports storing the

Session data in-process (in the same memory that ASP.NET uses), out-of-process using Windows NT Service (in separate memory from ASP.NET), and in SQL Server (persistent storage). Both the Windows Service and SQL Server solutions support a web farm scenario where all the web servers can be configured to share a common

Session store. So, as users get routed to different servers, each server is able to access that user's

Session data. To the developer using

Session , this is completely transparent and does not require any changes in the application code. Rather, we must configure ASP.NET to support one of these out-of-process options. We will discuss configuring

Session next chapter.



Cookieless mode:Although somewhat supported in ASP through the use of an ISAPI filter (available as part of the IIS 4.0 SDK), ASP.NET makes cookieless support for

Session a first class feature. However, by default,

Session still uses HTTP cookies. When cookieless mode is enabled (details in the next chapter), ASP.NET will munge the URL that it sends back to the client with a

Session ID, rather than storing the

Session ID in an HTTP cookie. When the client makes a request using the munged URL containing the

Session ID, ASP.NET is able to extract it and map the request to the appropriate

Session data.



We will cover how to configure both of these options in the next chapter, when we discuss ASP.NET configuration. From our perspective as developers coding and using

Session , these features are completely transparent.

Session is dedicated data storage for each user within an ASP.NET application. It is implemented as a

Hashtable and stores data based on key/value pair combinations.

Setting Session Value


In ASP.NET, the use of

Session follows the same pattern as in classic ASP. To set a

Session value in Visual Basic .NET, simply state:


Session("[String key]") = Object


The C# equivalent is:


Session["[String key]"] = Object;


You can provide

Session with a key that identifies the item we are storing. This

Session stores items of type

Object . Since all types in .NET inherit from

Object , this allows you to store anything in

Session . However, objects that contain live references, such as a

DataReader containing an open connection to a database, should not be stored in

Session .

For example, to store the string

Hello World using a key of

SimpleSession , write the following code in Visual Basic .NET:


Session("SimpleSession") = "Hello World"


And in C#:


Session["SimpleSession"] = "Hello World";


Underneath the covers, the CLR knows that the type

String originated from the type

Object , and is able to store that value correctly in memory.

Retrieving Session Value


Since

Session is available throughout your web application, you can set values in

global.asax code and access a

Session value from ASP.NET pages.

For example, to retrieve your

Hello World value from

Session , you only need to provide

Session with your key for it to return the value. This is the Visual Basic .NET code:


Dim sessionValue As String

sessionValue = Session("SimpleSession")


And in C#:


string sessionValue;

sessionValue = Session["SimpleSession"];


For types other than

String , the semantics of accessing the value stored in

Session are a bit more explicit. Because

Session stores its data as an

Object type, giving it the flexibility to store any .NET item, when you wish to retrieve data (other than type

String ) you have to cast the return value to the correct type.

For example, if you stored a custom class you defined called

PurchaseOrder in

Session , here is how you would need to retrieve it in Visual Basic .NET:





Important

For a class instance to be stored in out-of-process

Session state, the class must be marked with the

[Serializable] attribute.



Dim po As PurchaseOrder

po = CType(Session("po"), PurchaseOrder)


And in C#:


PurchaseOrder po;

po = (PurchaseOrder) Session["po"];


In both examples, the

Object returned is cast by the key

po to type

PurchaseOrder .

The

Session API provides additional properties that you can use in code to determine what mode

Session is in:



IsCookieless :Returns

True or

False indicating whether or not

Session is using cookieless mode to maintain the

Session ID. By default, this is

False , meaning that

Session is using cookies.



IsReadOnly :Returns

True or

False indicating whether or not

Session is in read-only mode. Read-only mode is an optimization that does not allow ASP.NET to update

Session data. This can be particularly useful for out of process modes on pages that only read

Session state and don't need write access. When a

Session is read-only, a lock does not have to be maintained and the round-trip back to an out-of-process

Session store for an update can be skipped. By default, this value is

False , and

Session is read/write. We will discuss how to enable

ReadOnly for

Session in the next chapter.



Mode :Returns the value of an enumeration,

SessionStateMode , (found in

System.Web.SessionState ) that indicates the storage mode that

Session is configured for. Values include

InProc ,

Off ,

SQLServer , and

StateServer .



ASP.NET session state is quite different from ASP session state. The new capability of session state that is not bound to the ASP.NET process means that developers can begin to use session state in server farm environments without worrying about whether the client is coming through a proxy server. With the cookieless state functionality, it is even easier to use session state and guarantee that all clients can take advantage of the session state feature. In the next chapter, you will learn how to configure

Session to support a read-only mode as well the other 'mode' options (in-process, Windows Service, and SQL Server).

Configuring and using Session State is covered in more depth in Chapter 13.


Application – Managing Application State


Unlike

Session , which is basically dedicated storage for each user,

Application is shared application storage. This shared storage is quite useful, especially if there are resources that all users share, such as an XML representation of a site's shopping catalog. Similar to

Session ,

Application state is simply a

Hashtable that stores key/value pair combinations.

Unlike

Session , however,

Application does not support the concept of storing data separate from the ASP.NET process. Instead,

Application stores its data in process with ASP.NET. If the ASP.NET process is recycled (covered in the next chapter)

Application data is lost. The trade-off is that storing the data in-process is faster than going to another process, or possibly across the network, to retrieve data.

The syntax used for setting and accessing values with

Application is identical to that of

Session , with one exception.

Since

Application is accessible in a multi-user environment, updates to

Application values should be synchronized. This simply means that whenever

Application data is being updated, you should prevent other users or applications from updating the data simultaneously. Luckily,

Application provides you with this capability through a simple set of locking methods. Note these are the same locking methods

Lock and

UnLock supported in ASP.

Reading and Writing Application Data


We read and write data in

Application in a similar manner to

Session using key/value pairs, such as the following in Visual Basic .NET:


Application("HitCounter") = 10


Or in C#:


Application["HitCounter"] = 10;


Similarly, if you wish to read the value back simply use your key, like this in Visual Basic .NET:


Dim HitCount As Integer

HitCount = Application("HitCounter")


Or in C#:


int HitCount = Application["HitCounter"];


However, to update

HitCounter you must synchronize access using the

Lock and

UnLock methods of

Application . Otherwise, the potential exists for two requests to attempt to update

HitCounter simultaneously, causing a potential deadlock or update failure.

Although this is an illustrative example, when you Lock, you are effectively blocking other applications that may be attempting to update the

HitCounter value, causing them to serialize – that is, perform operations one after another. We definitely don't want to Lock/UnLock on each request, as this would negatively affect performance. If the data stored in Application must be updated frequently, it is probably not a good candidate for Application state, unless recreating the data is more costly than the time spent serializing the updates.

Let's look at an illustrative example using

Application.Lock and

Application.UnLock , first in Visual Basic .NET:


Public Sub Application_OnStart()

Application("HitCount") = 0

End Sub


Public Sub Application_OnBeginRequest()

Application.Lock()

Application("HitCounter") = Application("HitCounter") + 1

Application.UnLock()

End Sub


And now in C#:


public void Application_OnStart() {

Application["HitCounter"] = 0;

}


public void Application_OnBeginRequest(){

Application.Lock();

int tmpInt = (int)Application["HitCounter"];

Application["HitCounter"] = tmpInt + 1;

Application.UnLock();

}


In the preceding code, we call

Application.Lock to ensure that while we update

HitCounter , some other thread cannot update the value simultaneously.





Note

When the ASP.NET process is stopped or recycled,

Application state is lost. However, when the process is recycled, the

Application_OnEnd event (discussed later) is raised and values can be persisted to a database or file.


Since ASP.NET is a multi-threaded system,

Application memory can be accessed by multiple processes simultaneously. To use

Application and set values, you must either:



Know that the object stored in

Application is doing its own thread management (not shown).

Or



Perform our own synchronization using

Application.Lock and

Application.UnLock .



Calling

Lock instructs ASP.NET to block any other threads from modifying this resource until

UnLock is called, giving your code exclusive access. However, if you don't explicitly call

UnLock , ASP.NET will call it when the application completes the request, the request times out, or an unhandled error occurs. Although this is done for us, you should always aim to write code that explicitly calls

UnLock .

Storing Objects in Application


Classic ASP VB objects could not be hosted in

Application state due to the default threading model these components supported (Apartment Model threading). In effect, accessing an instance of a VB component stored in

Application would cause ASP to serialize (execute one request after another) access to that component. .NET components are free threaded by default and don't have this thread affinity problem. Therefore, there are no performance penalties for storing a Visual Basic .NET object in

Application and accessing it across multiple requests.

Next, let's look at a new object,

Cache , used to store transient application data.


Cache – Managing Transient State


Many developers use

Application as a cache for frequently used resources, for example, reading an XML file that represents a product catalog and storing the object representing that XML file in

Application memory.

However, what happens when this XML file representing the product catalog changes? In most cases, developers who use

Application to manage this data simply force the web application to restart, thus forcing

Application to get refreshed.

The design goal of the

Cache was to give developers the benefits of

Application , but with additional features that went above and beyond those provided by

Application , such as the ability to evict an item from the

Cache when a file changes, it is then your responsibility through code to add the item back to the

Cache if you desire.

Cache Overview


Cache is an instance of the

Cache class found in the namespace

System.Web.Caching . In addition to being a simple key/value pair

Hashtable like

Application , the

Cache also supports:



Dependency-based expiration:Dependencies can be other

Cache keys, files, or a timestamp. When one of the dependencies changes or expires (timestamp), the

Cache item is invalidated and removed from the

Cache .



Lock management:Unlike

Application , the

Cache class does its own internal lock management. Therefore, while

Application required us to explicitly

Lock and

UnLock when updating

Application ,

Cache doesn't require this. Keep in mind that we do still need to manage concurrency for objects stored in the

Cache just as we do with objects stored in

Application .



Resource management:When the

Cache detects memory pressure, a least recently used algorithm walks the

Cache and automatically evicts items used less frequently. Therefore, before we request an item, we always need to check if the item exists.



Callbacks:The

Cache supports allows us to run code when items are removed from the

Cache .



The

Cache supports two methods of inserting items:



Implicit:We are familiar with this syntax from working with

Session or

Application using the key/value pairs.

In Visual Basic .NET:


Dim productDataSet As New DataSet()

' Populate DataSet

Cache("products") = productDataSet


And in C#:


DataSet productDataSet = new DataSet();

// Populate DataSet

Cache["products"] = productDataSet;




Explicit:Using the

Insert method, it allows us to set up special relationships such as dependencies. In VB.NET, the code to do this is.


Dim productDataSet As New DataSet()

' Populate DataSet

Cache.Insert("products", productDataSet, Nothing)


In C#:


DataSet productDataSet = new DataSet();

// Populate DataSet

Cache.Insert("products", productDataSet, null)




The

Cache also supports an

Add method. The

Add method behaves similar to

Insert , with the exception that it will only add them item to the

Cache if it does not already exist – whereas the

Insert method will always add the item into the

Cache , even if it already exists.

When using the

Cache , you will mostly use the explicit

Insert . Let's look at some examples.

Dependency-Based Expiration


Dependency-based expiration is very powerful. It allows you to create a relationship between an item in the

Cache and either a file, another

Cache key, or a defined point in time. For example, if your site used XML and XSL transforms to control aspects of content, you could load the XML into an

XmlDocument class and store the value within the

Cache . You could also establish a relationship between the cached

XmlDocument and the file that it is reading, using the file-based dependency feature of the

Cache . Let's build this sample.

This is the XML file:


<?xml version="1.0"?>

<books>

<book>

<name>Professional ASP.NET 2nd Edition</name>

<isbn>1861007035</isbn>

<publisher>Wrox Press</publisher>

<authors>

<author name="David Sussman"/>

<author name="Brian Francis"/>

<author name="Alex Homer"/>

<author name="Karli Watson"/>

<author name="Rich Anderson"/>

<author name="Rob Howard"/>

</authors>

<description>

ASP.NET is a unified web development

platform that provides the services necessary

for developers to build enterprise-class web

applications.

</description>

</book>

</books>


The file is saved as

1861007035.xml , which is the ISBN for the book Professional ASP.NET 1.0 Special Edition. You also have an XSL transform for this file, called

book.xsl :


<xsl:stylesheet

version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html"/>

<xsl:template match="/">

<html>

<head>

<title><xsl:value-of select="books/book/name"/></title>

</head>

<style>

body { font-family: Arial; font-size: 18; color:white; }

li { list-style: square outside; }

</style>

<body bgcolor="black">

<xsl:apply-templates/>

</body>

</html>

</xsl:template>

<xsl:template match="name">

<h1><font color="red"><xsl:value-of select="."/></font></h1>

</xsl:template>

<xsl:template match="description">

<h6><xsl:value-of select="."/></h6>

</xsl:template>

<xsl:template match="isbn">

<font size="1">ISBN: <xsl:value-of select="."/></font><br/>

</xsl:template>

<xsl:template match="publisher">

<font size="1">Publisher: <xsl:value-of select="."/></font><br/>

</xsl:template>

</xsl:stylesheet>


The following code snippet is the ASP.NET page (

SingleFilevb.aspx ) that uses the

Cache and creates a file dependency on the XML file only – in this particular example we are not caching the XSL file:


<%@ Import Namespace="System.Xml" %>

<%@ Import Namespace="System.Xml.Xsl" %>


<Script runat="server">

Public Sub Page_Load(sender As Object, e As EventArgs)

Dim dom As XmlDocument

Dim xsl As New XslTransform()


' Do we have the Wrox Pro ASP.NET 2nd Ed book in the Cache?

If (IsNothing(Cache("1861007035.xml"))) Then

CacheStatus.Text = "Item not present, updating the Cache..."

UpdateCache("1861007035.xml")

Else

CacheStatus.Text = "Retrieving from Cache"

End If


' Load the transform

xsl.Load(Server.MapPath("book.xsl"))


dom = CType(Cache("1861007035.xml"), XmlDocument)


BookDisplay.Document = dom

BookDisplay.Transform = xsl


End Sub


Public Sub UpdateCache(strItem As String)


Dim strPath As String

Dim dom As New XmlDocument()


' Determine the file path of the file to monitor

strPath = Server.MapPath(strItem)


' Load the file into an Xml Dom

dom.Load(strPath)


' Create a CacheDependency on the file

Dim dependency as New CacheDependency(strPath)


' Cache the XML document

Cache.Insert(strItem, dom, dependency)

End Sub

</Script>

Status: <asp:label id="CacheStatus" runat=server/>

<br>

<asp:xml id="BookDisplay" runat=server/>


The interesting code appears in the

UpdateCache subroutine, which is called if the

Cache key

1861007035.xml is not present. We first map the path to the XML file, which is in the same directory, and load that XML file into an

XmlDocument class. Then, we create a new

CacheDependency class passing in the path to the XML file. Finally, we use the Cache's

Insert method and create a new

Cache entry using the name of the file (

1861007035.xml ), the

XmlDocument instance,

dom , and the

CacheDependency class instance,

dependency .

On requesting this page for the first time, you would see the screen shown in Figure 12-9:


Figure 12-9:

On subsequent requests you would see the Status: Retrieving from Cache message.

If you open the

1861007035.xml file and modify the name from

Professional ASP.NET 1.0 Special Edition to

Pro ASP.NET 1.0 , the file change notification would be enforced and the

XmlDocument storing the XML from the file would be removed from the

Cache . Requesting the ASP.NET page would bring up the screen shown in Figure 12-10:


Figure 12-10:

What if instead of monitoring a file, you wanted to remove an entry (or series of entries) from the

Cache when another item in the

Cache changed? This option is supported through a key-based dependency.

The syntax for supporting key-based dependencies is very similar to that used in file-based dependencies. For example, you can easily change the preceding code to support a key-based dependency by modifying only a couple of lines.

If you cached multiple XML documents for each Wrox book on .NET, you could set up a dependency relationship where the

Cache entries for the books could be invalidated (and reloaded) whenever a master key, for example

booksDependencyKey , changed.

The following code example, called

KeyBasedvb.aspx , creates such a relationship:


<%@ Import Namespace="System.Xml" %>


<Script runat="server">


Public Sub Create(sender As Object, e As EventArgs)

' Create the Cache entry for the dependency relationship

' the value of the key doesn't matter

Cache("booksDependencyKey") = "Book Dependency"


' Create a string array with the key names for the

' dependencies to be created upon

Dim dependencyKey(0) As String


dependencyKey(0) = "booksDependencyKey"


' Create a CacheDependency on this key

Dim dependency as New CacheDependency(nothing, dependencyKey)


' Cache the XML document

Cache.Insert("1861007035.xml", Load("1861007035.xml"), dependency)


Status()

End Sub


Private Function Load(xmlFile As String) As XmlDocument

Dim dom As New XmlDocument()

dom.Load(Server.MapPath(xmlFile))

Return dom

End Function


Public Sub Invalidate(sender As Object, e As EventArgs)

Cache.Remove("booksDependencyKey")

Status()

End Sub


Public Sub Status()

If (IsNothing(Cache("1861007035.xml"))) Then

lblStatus1.Text = "No value..."

Else

lblStatus1.Text = "Cache entry exists..."

End If

End Sub


</Script>

<form runat=server>

<input type="submit" OnServerClick="Create"

value="Create Cache Entries" runat="server" />

<input type="submit" OnServerClick="Invalidate"

value="Invalidate Key" runat="server" />

</form>

Status for cache key: 1861007035.xml: <b><asp:label id="lblStatus1"

runat=server/></b>


When you run this code, you need to press the Create Cache Entries button to create the

Cache entry for the XML file, as well as the dependency relationship. You can then press Invalidate Key, which raises the

Invalidate event. Within this event, we explicitly remove the cache key

booksDependencyKey . This enforces the dependency and also removes the

Cache entry for your XML document.

Finally, in addition to file and key-based dependencies, you can also create dependencies on time values. Consider an example where Wrox were to store all of its book titles in a single table in the database, and you knew that this data was only updated once a week. You could cache a

DataSet that represents this data with an explicit expiration of 60 minutes. This will save you going to the database for every request, but in case an update occurs, you can still guarantee that the data will be fresh within the following hour.

Here's the code from

TimeBasedvb.aspx that does this:


<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.SqlClient" %>


<script runat=server>

Private DSN As String


Public Sub Page_Load(sender As Object, e As EventArgs)

Dim strCacheKey As String

Dim titlesDataSet As DataSet


strCacheKey = "Titles"


If (IsNothing(Cache(strCacheKey))) Then

lblStatus.Text = "Getting data from database..."

LoadTitles(strCacheKey)

Else

lblStatus.Text = "Getting data from Cache..."

End If


titlesDataSet = CType(Cache(strCacheKey), DataSet)

TitleList.DataSource = titlesDataSet

TitleList.DataBind()


End Sub


Public Sub LoadTitles(strCacheKey As String)

Dim connection As SqlConnection

Dim command As SqlDataAdapter

Dim sqlSelect As String

Dim strDsn As String

Dim dataset As New DataSet()


sqlSelect = "SELECT title, pub_id, price, notes, pubdate FROM titles"

strDsn = "server=localhost;uid=sa;pwd=;database=pubs"


connection = New SqlConnection(strDsn)

command = New SqlDataAdapter(sqlSelect, connection)


command.Fill(dataset, "Author-Titles")

Cache.Insert(strCacheKey, dataset, nothing, _

DateTime.Now.AddMinutes(60), TimeSpan.Zero)

End Sub

</script>

<font size=6>

<asp:label id="lblStatus" runat="server"/>

</font>

<P>

<ASP:DataGrid id="TitleList" HeaderStyle-BackColor="#aaaadd"

BackColor="#ccccff"

runat="server" />


In this example, we have some logic at the beginning that checks for an entry in the

Cache named

Titles . If the

Cache entry doesn't exist, we then call the subroutine

LoadTitles , which connects to a database, performs a select on the titles table, fills a

DataSet , and finally inserts the

DataSet into the

Cache . We are using the explicit

Insert method of the

Cache :

Cache.Insert(strCacheKey, dataset, nothing, _
DateTime.Now.AddMinutes(60), TimeSpan.Zero)

This adds a

Cache entry with the key

titles , the populated

dataset , and also instructs the cache to expire the item after 60 minutes.

Cache additionally supports a very useful callback capability. The callback allows you to run your code when an item is removed from the cache, giving you the opportunity to add it back.

We could make the following modification to the preceding code (highlighted), which would guarantee that our item is always served from the cache:

   ...

If (loadedFromCallback) Then

lblStatus.Text = lblStatus.Text + "loaded from callback"

loadedFromCallback = false

End If
sqlSelect = "SELECT title, pub_id, price, notes, pubdate FROM titles"
connection = New
SqlConnection("server=localhost;uid=sa;pwd=00password;database=pubs")
command = New SqlDataAdapter(sqlSelect, connection)
command.Fill(dataset, "Author-Titles")

' Create the a CacheItemRemovedCallback

Dim onRemove As New CacheItemRemovedCallback(AddressOf _

Me.RemovedCallback)

Cache.Insert(strCacheKey, dataset, nothing,

DateTime.Now.AddMinutes(60), TimeSpan.Zero, _

CacheItemPriority.High, onRemove)
End Sub

' This method represents the callback

Public Sub RemovedCallback(key As String, value As Object,

reason As CacheItemRemovedReason)

' Let's always re-add the item if removed

LoadTitles(key)

End Sub
</script>
<font size=6>
<asp:label id="lblStatus" runat="server"/>
</font>
<P>
<ASP:DataGrid id="TitleList" HeaderStyle-BackColor="#aaaadd" BackColor="#ccccff"
runat="server" />


Caching adds a lot of powerful new features to manage data that you ordinarily would have stored in

Application state. Dependencies allow you to set up relationships with items that can invalidate the cache, and callbacks allow you to execute your own code whenever an item is removed from the

Cache .

State management in ASP.NET should be very familiar to developers who have worked with ASP. Both

Session and

Application state remain identical in use and you now have the

Cache option. It is very important to understand state management and when to use the options provided by it. Here are some basic guidelines:



Session :Used to store data that should be available to the user on each request. Be efficient about what you store in

Session , since each

Session will get its own individual copy of the data. Remember that class instances stored in out-of-process session state must be attributed with the

[Serializable] attribute at the class level.



Application :Used to store data that needs to be available to the entire application. A good candidate for

Application is data that remains fairly static and must be available on each request. Remember to use the

Lock and

Unlock methods to control access to

Application when updating the data.



Cache :Used to store data that may be used on each request, or data where a dependency relationship needs to be established. In many cases,

Cache can be used in place of

Application .



/ 244