What is session state?

A session is defined as the period of time that a unique user interacts with a Web application. Session state is a collection of objects, tied to a session are stored on a server.

Why use SQL?

Once you start running multiple web servers for the same web site, the default asp.net session state, InProc, is no longer useful, as you cannot guarantee that each page request goes to the same server. It becomes necessary to have a central state store that every web server accesses.

SQL Server offers you centralized storage of a session state in a Web farm. It also offers the transactional capabilities that provide reliability to most relational database systems. You can use SQL Server to save a session. This process is not as efficient as InProc and StateServer mode, because you must store the information in a different process or on a different server. However, this option may be more efficient than using the aspnet_state service, depending on the actual workload and the database configuration. Once you start saving session state to a SQL database it will also persist through web server restarts and reboots.

For reliability you should consider storing session state for a web farm on a SQL cluster.

Creating the database

  • Start Query Analyzer, connected to the server you want to use for state storage.
  • Open and execute InstallSqlState.sql script file. By default, InstallSqlState.sql is located in one of the following folders; system drive\ Windows\ Microsoft.NET\ Framework\version\
  • If you are using trusted connections to connect to your server, you must change ownership of the state database to sa after creation. In Query Analyzer run use ASPState
    exec sp_changedbowner 'sa','true'
  • If you are using SQL authentication create a user and password for session state to use. At a minimum this user should havepermissions to execute the stored procedures in the ASPState database. You will have to manually set these, or if you're feeling dangerous, give the state user dbo rights to ASPState.

Configuring ASP.Net

To switch ASP.Net to use SQL you must update the <sessionState> element of your application's Web.config file as follows;

  • Set the mode attribute of the <sessionState> element to SQLServer.
  • Set the sqlConnectionString attribute to specify the connection string to your SQL Server

For example

<sessionState
mode="SQLServer"
sqlConnectionString="data source=server;user id=uid;password=pwd"
cookieless="false" timeout="20" />

If you specify integrated security/trusted connections in the database connection string (ie. "trusted_connection=true", or "integrated security=sspi"), you cannot use impersonation in asp.net, as your database connection will then run the context of the impersonated user, which will not have rights to the state database. You can, of course grant connections to that user context. KB 326606 has more details.

If you are configuring session state to be stored on a cluster you must manually override the .net machine keys on each server. KB 323262 has more details.

Configuring SQL2000 SP3

So, you have created the database, you've created the user, given it rights to all the stored procedures in the ASPState database, you've up to date with patches, Windows, IIS SQL, and you connect to your web site...

SELECT permission denied on object 'ASPStateTempApplications', database 'tempdb', owner 'dbo'.
INSERT permission denied on object 'ASPStateTempApplications', database 'tempdb', owner 'dbo'.
SELECT permission denied on object 'ASPStateTempApplications', database 'tempdb', owner 'dbo'.

SP3 for SQL 2000 adds a new security feature, disabled by default, cross-database ownership chaining (see KB 810474 for details). When this feature is disabled, ASP.Net session state stops working.

To reconfigure SQL 2000 SP3 for ASP.net session state you must run

use master
go
EXEC sp_configure 'Cross DB Ownership Chaining', '0';
RECONFIGURE
GO

Now restart your SQL server, then run

use master
go
EXEC sp_dboption 'ASPState', 'db chaining', 'true'
go

Timeouts under heavy load

If your web servers are under heavy load it may be useful to increase the time out for session state access. You can add the stateNetworkTimeout attribute to the sessionState settings in web.config and machine.config


<sessionState stateNetworkTimeout="15" />

If a Web server or a state server is under stress and cannot complete session accesses on time, event ID 1072 and event ID 1076 may be logged in the event log.

Caveats when using SQL session state

Using SQL is slower than using InProc session state. When storing basic data types (string, int, etc), ASP.Net can take 10%-25% longer to store their values. Complex types take even longer. Of course because you are connecting to a separate server it does use bandwidth on your network.

When using SQL Server mode, objects stored in session state are serialised and deserialised when a request is processed. So any objects which do not support serialisation cannot be stored in session state. In ASP.Net v1.0 a bug means that attempting to store a non-serialisable object does not throw an error, and so will probably pass unnoticed.

For session state to be maintained across different web servers in a web farm (the main reason for moving session state to SQL), the Application Path of the website (For example \LM\W3SVC\2) in the IIS Metabase should be identical in for all the web servers in the web farm. Microsoft's KB 325056 details this problem.

If you wish to persist session state through SQL server reboots you must follow the instructions in KB 311209 to move the session state tables from tempdb to the ASPState database.

Other resources

Peter Bromberg's Session State FAQ
KB 317604 HOW TO: Configure SQL Server to Store ASP.NET Session State