Recipe 7.2. Maintaining Information Needed by All Users of an Application


Problem

You want to make certain data available to all users of an application.

Solution

Place the code needed to find and load the data in the Application_Start method of global.asax and store it in the Application object:

In the global.asax file, use the .NET language of your choice to:

  1. Create an event handler for the Application_Start event.

  2. Load the application data and store it in the Application object.

The code we've written to demonstrate this solution is shown in Examples 7-1, 7-2, 7-3, 7-4, 7-5, 7-6 through 7-7. Examples 7-1 and 7-2 show the VB and C# global.asax files; this code reads data from a database and places it in the Application object. Examples 7-3 and 7-4 show the VB and C# classes for constants used throughout the application to access the data in the Application object. Figure 7-1 shows a simple form we've created to view the application state data. Example 7-5 shows the .aspx file that produces the form. Examples 7-6 and 7-7 show the companion VB and C# code-behind files that demonstrate how to access the application state data.

Figure 7-1. A view of some sample application state data


Discussion

The purpose of the Application object is to store information once that can be simultaneously shared with all users of the application without having to access it repeatedly from a database or some other data store. One example is when you want to store and share the number of times an application has been hit by all the users of the application. Another example is when you want to store and share some common reference information, as illustrated in Figure 7-1. Using the Application object provides the ideal means to accomplish these tasks. The Application object is similar to the Session object (discussed in the next recipe), except that it stores global information as opposed to information about an individual session. The Application object is a property of the Page object that provides the ability to store almost any data and offer access to it throughout the application by all users. Storing commonly used global data in memory can improve the application's performance.

The Cache object can also be used to store data used throughout an application. See Chapter 16 for examples of using the Cache object.


The code we've written to illustrate this recipe provides an example of loading information from a database and storing it in the Application object so it can be accessed by any page of an application without having to retrieve the data from the database each time the data is needed.

Data that you want to make available throughout the application should be initialized when the application starts. The Application_Start event handler in the global.asax file class is the best place to do this because the Application_Start event is raised the first time the application is accessed.

In our example, the Application_Start event handler reads the titles of the chapters of this book from a database into a DataTable and stores the table of chapter data in the Application object.

Data stored in the Application object can be accessed from any page of an application. When you access the data, you must cast it to the correct type because all data is stored in the Application object as Objects; without properly casting the data, your code will not compile. Our example retrieves the data and binds it to a Repeater control in the Page_Load method in Examples 7-6 (VB) and 7-7 (C#). (Data binding is described in Chapter 2.)

To avoid "hardcoding" names of variables placed in the Application object, we recommend you define public constants in a class that is accessible throughout your application, such as appconstants in Examples 7-3 (VB) and 7-4 (C#). In ASP.NET 1.x, these constants could be placed in the Global.asax.vb (or Global.asax.cs) class. With the changes in ASP.NET 2.0 to use partial classes, these constants must be placed in another class to provide application-wide access.

On another note, any object placed in the Application object must be free-threaded; otherwise, deadlocks, race conditions, and access violations can occur. Any object created from the classes in the Common Language Runtime is free-threaded and can be safely stored in the Application object. VB6 objects are apartment-threaded and should not be placed in the Application object.


You can update data stored in the Application object whenever your application requires it. ASP.NET is multithreaded, so many threads can access the variables within the scope of an application at the same time. Changing the variables' values in an uncontrolled fashion can cause data concurrency issues. To prevent contention between threads, the Application object must be able to block access to itself while changes are being made. You can do this by calling the Lock method of the Application object, making your changes, and calling the Unlock method, as shown here:

 

Application.Lock() Application.Add(APP_CHAPTER_DATA, _ ds.Tables(CHAPTER_TABLE)) Application.UnLock()

Application.Lock(); Application.Add(APP_CHAPTER_DATA, ds.Tables[CHAPTER_TABLE]); Application.UnLock();

Your application should always minimize the time the Application object is locked because all other threads are held off until the lock is released. To avoid permanent locks, ASP.NET automatically performs the unlock operation when a request is completed, a request times out, or an unhandled exception occurs and causes the request to fail.


Whenever you use the Application object in an application, consider the following points:

  • The Application object is not shared across servers in a web farm. Each server maintains its own copy of the Application object. If the values stored in the application are different on each of the servers in the web farm, your application may operate differently depending on which server was accessed.

  • Any data stored in the Application object is cleared when the application restarts. If any of that data needs to be persisted, you can place code in the Application_End event handler of global.asax to store the data in a database or the like. Be careful in relying on the Application_End event handler to persist any important data. It is not called if the application stops abnormally, such as in a power failure or an application crash.

See Also

Chapter 16 for information on using the Cache object

Example 7-1. Maintaining application state (global.asaxVB)

 <%@ Application Language="VB" %> <%@ Import Namespace="System.Configuration.ConfigurationManager" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <%@ Import Namespace="ASPNetCookbook.VBExamples" %> <script RunAt="server"> '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the application start ''' event. It is responsible for initializing application variables. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) Dim dbConn As OleDbConnection = Nothing Dim da As OleDbDataAdapter = Nothing Dim dTable As DataTable = Nothing Dim strConnection As String Dim cmdText As String Try 'get the connection string from web.config and open a connection 'to the database strConnection = _ ConnectionStrings("dbConnectionString").ConnectionString dbConn = New OleDbConnection(strConnection) dbConn.Open() 'build the query string and get the data from the database cmdText = "SELECT ChapterNumber, Title, Description " & _   "FROM Chapter " & _   "ORDER BY ChapterNumber" 'fill the dataset with the chapter data da = New OleDbDataAdapter(cmdText, dbConn) dTable = New datatable da.Fill(dtable) 'store the table containing the chapter data in the Application object Application.Add(appconstants.APP_CHAPTER_DATA, _ dtable) Finally If (Not IsNothing(dbConn)) Then dbConn.Close() End If End Try End Sub </script> 

Example 7-2. Maintaining application state (global.asaxC#)

 <%@ Application Language="C#" %> <%@ Import Namespace="System.Configuration" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.OleDb" %> <%@ Import Namespace="ASPNetCookbook.CSExamples" %> <script RunAt="server"> ///*********************************************************************** /// <summary> /// This routine provides the event handler for the application start /// event. It is responsible for initializing application variables. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> void Application_Start(Object sender, EventArgs e) { OleDbConnection dbConn = null; OleDbDataAdapter da = null; DataTable dTable = null; String strConnection = null; String cmdText = null; try { // get the connection string from web.config and open a connection // to the database strConnection = ConfigurationManager. ConnectionStrings["dbConnectionString"].ConnectionString; dbConn = new OleDbConnection(strConnection); dbConn.Open(); // build the query string and get the data from the database cmdText = "SELECT ChapterNumber, Title, Description " +   "FROM Chapter " +   "ORDER BY ChapterNumber"; // fill the dataset with the chapter data da = new OleDbDataAdapter(cmdText, dbConn); dTable = new DataTable(); da.Fill(dTable); // store the table containing the chapter data in the Application object Application.Add(appconstants.APP_CHAPTER_DATA, dTable);  } // try finally { // cleanup if (dbConn != null) { dbConn.Close(); } } // finally } // Application_Start </script> 

Example 7-3. Application constants (.vb)

 Option Explicit On Option Strict On Imports System.Drawing Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class constants that are used throughout the application ''' </summary> Public Class appconstants 'the following constant used to define the name of the variable used to 'store the chapter data in the application object Public Const APP_CHAPTER_DATA As String = "ChapterData" End Class 'appconstants End Namespace 

Example 7-4. Application constants (.cs)

 using System; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class constants that are used throughout the application /// </summary> public class appconstants { // the following constant used to define the name of the variable used to // store the chapter data in the application object public const String APP_CHAPTER_DATA = "ChapterData"; } // appconstants } 

Example 7-5. Using application state data (.aspx)

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master" AutoEventWireup="false" CodeFile="CH07ApplicationStateVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH07ApplicationStateVB" Title="Application State" %> <asp:Content  runat="server" ContentPlaceHolder> <div align="center" > Maintaining Application State (VB) </div> <table width="40%" border="0" align="center" cellpadding="0" cellspacing="0"> <thead> <tr> <th colspan="2"    >ASP.NET Cookbook Chapters</th> </tr> </thead> <tr> <td><img src="/books/1/505/1/html/2/images/spacer.gif" height="10" border="0" alt=""/></td> </tr> <asp:Repeater  runat="server"> <ItemTemplate> <tr > <td align="center" width="15%"> <%#Eval("ChapterNumber")%></td> <td width="85%"> <%#Eval("Title")%></td> </tr> <tr> <td bgcolor="#FFFFFF" colspan="2"> <img src="/books/1/505/1/html/2/images/spacer.gif" border="0" height="2" alt=""/></td> </tr> </ItemTemplate> </asp:Repeater> </table> </asp:Content> 

Example 7-6. Using application state data code-behind (.vb)

 Option Explicit On Option Strict On Imports System.Data Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the code behind for ''' CH07ApplicationStateVB.aspx ''' </summary> Partial Class CH07ApplicationStateVB Inherits System.Web.UI.Page '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the page load event. It ''' is responsible for initializing the controls on the page. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Private Sub Page_Load(ByVal sender As Object, _   ByVal e As System.EventArgs) Handles Me.Load Dim chapterData As DataTable If (Not Page.IsPostBack()) Then 'get the chapter data stored in the application object chapterData = CType(Application.Item(appconstants.APP_CHAPTER_DATA), _ DataTable) 'bind it to the repeater to display the chapter data repMenuItems.DataSource = chapterData repMenuItems.DataBind() End If End Sub 'Page_Load End Class 'CH07ApplicationStateVB End Namespace 

Example 7-7. Using application state data code-behind (.cs)

 using System; using System.Data; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class provides the code behind for /// CH07ApplicationStateCS.aspx /// </summary> public partial class CH07ApplicationStateCS : System.Web.UI.Page { ///*********************************************************************** /// <summary> /// This routine provides the event handler for the page load event. /// It is responsible for initializing the controls on the page. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void Page_Load(object sender, EventArgs e) { DataTable chapterData = null; if (!Page.IsPostBack) { // get the chapter data stored in the application object chapterData = (DataTable)(Application[appconstants.APP_CHAPTER_DATA]); // bind it to the repeater to display the chapter data repMenuItems.DataSource = chapterData; repMenuItems.DataBind(); } } // Page_Load } // CH07ApplicationStateCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2003
Pages: 202

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net