Overview of Application Management


Application state management enables information to be shared between multiple users of the same Web application. In classic ASP, you manage application state using an HttpApplicationState handler, which is encapsulated by the ASP Application object. This object is still available in ASP.NET, although it has additional members and gives you new ways to enumerate through a collection of HttpApplicationState variables . The Application object is easy to work with, in terms of configuration and coding, and this makes it a tempting option. Unfortunately, the Application object is also problematic because it does a poor job of synchronizing changes from multiple users. Only one user at a time (technically, one thread at a time) should be allowed to modify an Application object variable. This is a big issue in the .NET environment, which supports free-threaded objects. To ensure single-thread updates, the Application object provides Lock() and UnLock() methods that prevent other users from simultaneously updating the object. The Lock() method actually locks the entire Application object, even though the user may be updating just one of several available object variables. This feature can cause concurrency problems if several users attempt to lock the object at the same time. Ultimately, concurrency problems lead to scalability problems as users are forced to wait to commit their changes. Worse yet, concurrency lockups could cause one or more users to deadlock and experience instability with their sessions. As a result, Application state is only appropriate for values that are read often but are updated infrequently.

ASP.NET provides a new and superior alternative to the Application object in the form of a Cache engine, which provides better control over data storage and retrieval. The Cache engine provides a more sophisticated API than the Application object as well as better concurrency handling. The following sections demonstrate the different options that ASP.NET provides for managing application state.

Permanent vs. Transient Application State

You need to store two kinds of information at the application level:

  • Permanent information: This applies globally across an application and changes rarely. Examples include connection string information or configuration setting values referenced throughout the application.

  • Transient information: This information is still global in scope, but it changes with some frequency; examples include counters, such as a Web site visitor counter. Users must all modify the same copy of this value to keep a running count.

Although you could store both kinds of information in an Application object, ASP.NET provides better alternatives.

Understanding Permanent Application State

You can store permanent information in the Web.config file and reference it programmatically at runtime. At the simplest level, you can assign custom information to a new key within the <appSettings> node:

 <appSettings>     <add key="ConnectionString" value="server=;uid=sa;pwd=ap1;database=dev;" />     <add key="SysAdminEmailAddress" value="sysadmin@yourcompany.com" /> </appSettings> 

You can then reference these keys from any code-behind file using the ConfigurationSettings object, which is a member of the System.Configuration namespace:

 Dim strConn As String strConn = ConfigurationSettings.AppSettings("ConnectionString") 

The <appSettings> element is useful, but it is restricted to storing name -value pairs. The Web.config file also allows you to define a custom configuration section, which can have a more complex structure. For example, you could define a section that tracks parent (myMenuGroup) and child (myMenuItem) menu options:

 <configSections>          <!-- Declares a section group called myMenuGroup -->          <sectionGroup name="myMenuGroup">                   <!-- Declares a section name called myMenuItem -->                   <section name="myMenuItem"                       type="System.Configuration.DictionarySectionHandler, System"/>          </sectionGroup> </configSections> 

You could then implement the sections as follows :

 <myMenuGroup>          <myMenuItem>                   <add key="Login" value="login.aspx"/>                   <add key="Logout" value="logout.aspx"/>          </myMenuItem> </myMenuGroup> 

You must define and implement custom configuration settings inside Web.config . Once you do this, you can reference the settings from any code-behind file in the project using the GetConfig() method of the ConfigurationSettings object:

 Dim dctMenuItems As IDictionary Dim enmKeys As IDictionaryEnumerator dctMenuItems = ConfigurationSettings.GetConfig("myMenuGroup/myMenuItem") enmKeys = dctMenuItems.GetEnumerator() While enmKeys.MoveNext     If enmKeys.Value.GetType.ToString = "System.String" Then         Response.Write(enmKeys.Key & "= " & enmKeys.Value & "<BR>")     End If End While 

The Web.config file is an excellent choice for persisting permanent application information that must be referenced by, but never altered by, the application. Clearly, the Web.config file is only capable of storing a limited range of data types, so it is most suitable for storing configuration values. An added advantage is that the application automatically picks up changes to this file without requiring a restart. (ASP.NET automatically restarts when it detects a change event.) This makes it easy to change application settings on the fly or to deploy multiple versions of the same Web.config file to different environments, such as staging and production.

Caution

The Web.config file is a text file and should therefore not be used for storing sensitive information. IIS will not allow the Web.config file to be accessed by an outside browser, but you should still be cautious with the type of information you store in this file.

Some developers refuse to store SQL connection string information in the Web.config file. We, on the other hand, store SQL login credentials as long as they reference an account that has highly restricted access to the database.

Chapter 2, "Introducing ASP.NET Applications," discusses the Web.config file in great detail.

Understanding Transient Application State

ASP.NET provides two main classes for managing transient application state:

  • HttpApplicationState

  • Cache

Let's discuss each of these in turn .

Configuring and Using the HttpApplicationState Class

The HttpApplicationState class is instanced once for every ASP.NET application, and it provides shared application state for all requests . This class is conveniently exposed by the Page object's Application property. From here on, we refer to the HttpApplicationState class as the Application object , which represents a single instance of the class. Think of the Application object as a collection container that enables you to manage a collection of globally scoped variables. Like the Session object, the Application object provides a straightforward API that is easy to code against. Table 4-4 summarizes useful Application object members.

Table 4-4: HttpApplicationState Class Members

MEMBER

DESCRIPTION

Add()

This method adds a new item to application state. Its syntax is Add(name As String, value As Object) .

Lock()

This method locks access to a specific application state variable.

Unlock()

This method unlocks access to a specific application state variable.

Set()

This method sets the value of a specific application variable. Its syntax is Set(name As String, value As Object) .

Contents

This read-only property gets a reference to the collection of Application variables that were added through code using the Application object's API.

StaticObjects

This read-only property gets a reference to the collection of Application objects that were added in Global.asax using the <object> tag.

RemoveAll()

This method removes the entire collection of Application variables.

Remove()

This method removes a specific Application variable from the collection. Its syntax is Remove(name As String) .

RemoveAll()

This method removes the entire collection of Application variables.

The Application object is programmatically accessible via the Application property of the Page object. Unlike the Session object, the Application object does not require any settings in the Web.config file. You can add application-level variables to the collection in two ways:

  • Programmatically using the Application object's API

  • Using the <object> tag in Global.asax

For example, you can assign a String object programmatically:

 Dim objStr As System.String Page.Application.Add("myStr", objStr) 

Alternatively, you can instance the String object at the application level in Global.asax :

 <%@ Application Codebehind="Global.asax.vb" Inherits="Apress1.Global" %> <object runat="server" id="myStr" class="System.String" scope="application" /> 

Now that you have instanced the String object, you can set and retrieve its value from any page within the application. For example, on Page1.aspx , you can set the value:

 ' Set the string Dim MyString1 As String = "My global string value." Page.Application.Set("myStr", MyString1) 

Then on Page2.aspx , you can retrieve the value:

 ' Retrieve the string Dim MyString2 As String = Page.Application.Item("myStr") Response.Write("MyString2 = " & MyString2.ToString()) 

Observant readers will notice that we assigned MyString1 to the Application object without locking the object first. Had we been more careful, we would have used the available locking methods:

 ' Alternative set Dim MyString2 As String = "My global string value2." Page.Application.Lock() Page.Application.Set("myStr", MyString2) Page.Application.UnLock() 

The moral of the story is that the Application object allows you to set values without requiring the safety check of the Lock() and UnLock() methods. Without this check, you risk a collision with another user who is updating the Application object at the same time. On the other hand, if you keep the Application locked for too long, you risk a deadlock with another user.

In summary, the advantages of the Application object are that Application objects are easy to code with and easy to configure.

The disadvantages of the Application object are as follows:

  • You cannot share Application objects across multiple Web servers. Stored values are only available to the application thread that instanced them.

  • Application objects are not durable. They reside in memory and will be lost if the dedicated process crashes or is restarted.

  • Application objects greatly impact scalability because they are multi-threaded and run a high risk of causing deadlocks and concurrency issues when multiple users attempt updates at the same time.

  • Application objects use memory resources, which can potentially have a significant impact on the Web application's performance and scalability ”particularly if the Application object stores significantly sized objects, such as a populated DataSet.

  • Application objects do not optimize resource usage, for example, by expiring underused items. Application items remain in memory all the time, whether they are heavily used or not.

Let's now take a look at another alternative for managing transient application state: the Cache class.

Configuring and Using the Cache Class

ASP.NET supports application data caching, which allows expensive resources to be stored in memory for fast retrieval. Chapter 5, "Caching ASP.NET Applications," discusses caching in full detail, so this section serves as a quick introduction to the feature. We present just enough detail to demonstrate how caching is a good alternative to the Application object for managing transient application state.

The Cache class provides optimized storage for persisting objects in memory. Unlike the Application object, cached items remain available only for as long as they are needed. You can assign cached items with expiration policies. The Cache class provides much more control over cached items compared to the Application object. These advantages include the following:

  • Customized expiration : You can assign cache items individual expiration policies that indicate when they should expire and be removed from the cache. The Cache class supports three expiration modes, including absolute, sliding, and dependency expiration:

    • Absolute mode specifies an exact date and time for expiring the item.

    • Sliding mode specifies a time interval for expiring the item, based on the last time that the item was accessed.

    • Dependency mode links an item's expiration to a fixed resource, such as a file. The item automatically expires and refreshes whenever the dependency changes.

  • Memory management : The Cache class automatically removes underused items from the cache. In addition, items will be systematically evicted from the cache when server resources become low.

  • Concurrency management : The Cache class automatically manages concurrent updates to the same item, without requiring that the user place a lock on the item.

Durability is the key difference between items stored in the cache vs. those stored in an Application object. Cache items are not guaranteed to persist in memory, although you can ensure they will by setting specific expiration policies. As server resources become low, the Cache class will evict items based on their relative priority. Heavily used items have high priority and will typically be evicted last. You can set items with specific priorities to influence their eviction order. But, ultimately, all items are subject to eviction if server resources become tight enough. The Application object, on the other hand, will continue to hold its references, regardless of the impact on server resources.

Like the Application object, the Cache class allows you to add items implicitly, using basic key-value pairs:

 Dim sqlDS As DataSet Page.Cache("MyDS") = sqlDS 

The Cache class also provides explicit Add() and Insert() methods for adding cache items with advanced settings, such as expiration policies and priorities. The Insert() method is overloaded, so it provides the most flexibility for adding items. For example, this is how you add an item using a 30-minute sliding expiration:

 Dim sqlDV As DataView Page.Cache.Insert("MyDV", sqlDV, Nothing, Cache.NoAbsoluteExpiration, _     New TimeSpan(0, 0, 30)) 

You can retrieve items from the cache implicitly:

 Dim sqlDV As DataView sqlDV = Page.Cache("MyDV") ' Returns Nothing reference if item has been evicted 

Or, explicitly using the Get() method:

 Dim sqlDV As DataView sqlDV = Page.Cache.Get("MyDV") ' Returns Nothing reference if item has been evicted 

Finally, you can explicitly remove items from the cache using the Remove() method:

 Dim MyDS As DataSet MyDS = Page.Cache.Remove("MyDS") ' Evaluates to True 

Because cache items may expire, or be evicted, any code that uses them must have the ability to re-create the object in the event that it cannot be pulled from the cache. Consider the following code, which uses the GenerateDataSet() method to create a populated DataSet object:

 If Not IsNothing(Page.Cache.Item("MyDS")) Then      sqlDS = Page.Cache.Get("MyDS") Else      sqlDS = GenerateDataSet() ' Regenerate the DataSet      Page.Cache.Insert("MyDS", sqlDS, Nothing, "12/31/2020", _          Cache.NoSlidingExpiration) End If 

In this example, the code attempts to retrieve the DataSet from the cache. If it cannot be found, then it must be regenerated and added to the cache again. This example illustrates an important point: The Cache class is best suited for storing objects that have page-level scope and that can be re-created if needed. The Cache is global to an application, so it may technically be used for storing "application-level" objects. But in practice, you would not want every page to have to check for, and re-create, the Application object item. However, this is not an issue for page-level objects.

The Cache class is a superior alternative to the Application object for all purposes except when you need to store a truly global object reference ”that is, a reference that may be accessed from any page within an application and that must be counted on to be there. The Application object is not as efficient as the Cache class, but it does offer more convenience when you want to guarantee that an item will always be available. The Application object does not persist items in the event that the application crashes, but then, neither does the Cache class.

In summary, the advantages of the Cache class are as follows:

  • The Cache class optimizes memory management by using expiration policies and by automatically removing underused items.

  • The Cache provides automatic concurrency management.

  • The Cache class is easy to code with and easy to configure.

The disadvantages of the Cache class are as follows:

  • Cache items are not guaranteed to be persistent in the cache. This requires contingency coding in code blocks that use cached object references.

  • You cannot share cached objects across multiple Web servers. Object references are only available to the application thread that instanced them.

This concludes our discussion on application state management. Next, we discuss the Global.asax file and show how it helps you design optimal ASP.NET applications.




Performance Tuning and Optimizing ASP. NET Applications
Performance Tuning and Optimizing ASP.NET Applications
ISBN: 1590590724
EAN: 2147483647
Year: 2005
Pages: 91

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