Помощь

Хранение сессий в базе данных Microsoft SQL Server

Настройка БД MSSQL для хранения сессий

Для того, чтобы MSSQL мог хранить сессии необходимо в базе данных создать специальный набор таблиц и хранимых процедур. Во всех источниках говорится, что это можно сделать при помощи мастера, запускаемого из командной строки:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regsql.exe

Проблема заключается в том, что мастер не показывает ошибки, если они возникают при его выполнении. Утилита aspnet_regsql.exe позволяет сделать экспорт скрипта, который выполняется на сервере MSSQL. Это делается следующей командой:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regsql.exe -S uXXXXX.mssql.masterhost.ru -U uXXXXX_user -P PASSWORD -d uXXXXX_name -ssadd -sstype c -sqlexportonly C:\ssdb.sql

uXXXXX.mssql.masterhost.ru — адрес сервера MSSQL
uXXXXX_user — нужный MSSQL-логин
uXXXXX_db — имя нужной базы данных MSSQL
PASSWORD — соответствующий пароль доступа к базе данных

После выполнения команды создастся файл C:\ssdb.sql с кодом скрипта для настройки базы. Откроем этот файл в любом текстовом редакторе. База данных уже создана, поэтому из кода убираем следующую часть:

/* Create and populate the session state database */

IF DB_ID(N'uXXXXX') IS NULL BEGIN
    DECLARE @cmd nvarchar(500)
    SET @cmd = N'CREATE DATABASE [uXXXXX]'
    EXEC(@cmd)
END
GO

На хостинговом MSSQL-сервере отключен SQL Agent, поэтому невозможно создание заданий. Убираем части кода, касаемые создания заданий:

Убираем часть 1:

/* Drop the DeleteExpiredSessions_Job */

DECLARE @jobname nvarchar(200)
SET @jobname = N' uXXXXX' + '_Job_DeleteExpiredSessions'

-- Delete the [local] job
-- We expected to get an error if the job doesn't exist.
PRINT 'If the job does not exist, an error from msdb.dbo.sp_delete_job is
expected.'

EXECUTE msdb.dbo.sp_delete_job @job_name = @jobname
GO

Убираем часть 2:

/* Create the job to delete expired sessions */

-- Add job category
-- We expect an error if the category already exists.
PRINT 'If the category already exists, an error from msdb.dbo.sp_add_category is expected.'
EXECUTE msdb.dbo.sp_add_category @name = N'[Uncategorized (Local)]'
GO

BEGIN TRANSACTION
    DECLARE @JobID BINARY(16)
    DECLARE @ReturnCode int
    DECLARE @nameT nchar(200)
    SELECT @ReturnCode = 0

    -- Add the job
    SET @nameT = N'uXXXXX' + '_Job_DeleteExpiredSessions'
    EXECUTE @ReturnCode = msdb.dbo.sp_add_job
            @job_id = @JobID OUTPUT,
            @job_name = @nameT,
            @owner_login_name = NULL,
            @description = N'Deletes expired sessions from the session state database.',
            @category_name = N'[Uncategorized (Local)]',
            @enabled = 1,
            @notify_level_email = 0,
            @notify_level_page = 0,
            @notify_level_netsend = 0,
            @notify_level_eventlog = 0,
            @delete_level= 0

    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

    -- Add the job steps
    SET @nameT = N'uXXXXX' + '_JobStep_DeleteExpiredSessions'
    EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep
            @job_id = @JobID,
            @step_id = 1,
            @step_name = @nameT,
            @command = N'EXECUTE DeleteExpiredSessions',
            @database_name = N'uXXXXX',
            @server = N'',
            @subsystem = N'TSQL',
            @cmdexec_success_code = 0,
            @flags = 0,
            @retry_attempts = 0,
            @retry_interval = 1,
            @output_file_name = N'',
            @on_success_step_id = 0,
            @on_success_action = 1,
            @on_fail_step_id = 0,
            @on_fail_action = 2

    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

    EXECUTE @ReturnCode = msdb.dbo.sp_update_job @job_id = @JobID, @start_step_id = 1
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

    -- Add the job schedules
    SET @nameT = N'uXXXXX' + '_JobSchedule_DeleteExpiredSessions'
    EXECUTE @ReturnCode = msdb.dbo.sp_add_jobschedule
            @job_id = @JobID,
            @name = @nameT,
            @enabled = 1,
            @freq_type = 4,
            @active_start_date = 20001016,
            @active_start_time = 0,
            @freq_interval = 1,
            @freq_subday_type = 4,
            @freq_subday_interval = 1,
            @freq_relative_interval = 0,
            @freq_recurrence_factor = 0,
            @active_end_date = 99991231,
            @active_end_time = 235959

    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

    -- Add the Target Servers
    EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(local)'
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

    COMMIT TRANSACTION
    GOTO   EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO
/*************************************************************/

Остается решить, что делать со старыми сессиями. Их периодически необходимо удалять, иначе размер базы данных будет расти. Это можно сделать добавив следующий код либо в начало процедуры TempGetAppID, либо в код самого приложения:

Exec [dbo].[DeleteExpiredSessions]

По окончании редактирования файла достаточно выполнить его, например, подключившись к нужной базе данных с помощью Microsoft SQL Management Studio.

Настройка сайта для работы с БД MSSQL для хранения сессий

Для настройки сайта достаточно внести в файл конфигурации web.config в раздел <system.web> следующие строки:

<sessionState mode="SQLServer"
   allowCustomSqlDatabase="true"
   sqlConnectionString="Data Source=uXXXXX.mssql.masterhost.ru;
   Initial Catalog=uXXXXX_db;uid=uXXXXX_user;pwd=PASSWORD;"
   cookieless="false"
   timeout="20"
/>

uXXXXX.mssql.masterhost.ru — адрес сервера MSSQL
uXXXXX_user — нужный MSSQL-логин
uXXXXX_db — имя нужной базы данных MSSQL
PASSWORD — соответствующий пароль доступа к базе данных

Скачать пример готового web.config

Пример кода для проверки хранения сессий в БД MSSQL

Для проверки корректности хранения сессий в базе данных MSSQL можно использовать такой код:

<%@ Page Language="VB" %>
<Script runat=server>
  Sub Session_Add(sender As Object, e As EventArgs)
        Session("MySession") = text1.Value
        span1.InnerHtml = "Session data updated! <P> Your session contains: <font color=red>" + Session("MySession").ToString() + "</font>"
  End Sub

  Sub CheckSession(sender As Object, e As EventArgs)
        If Session("MySession") Is DBNull.Value Then
            span1.InnerHtml = "NOTHING, SESSION DATA LOST!"
        Else
            span1.InnerHtml = "Your session contains: <font color=red>" + Session("MySession").ToString() + "</font>"
        End If
  End Sub
</Script>

<form id="Form1" runat=server>
  <input id=text1 type=text runat=server>
  <input id="Submit1" type=submit runat=server
              OnServerClick="Session_Add" Value="Add to Session State">
  <input id="Submit2" type=submit runat=server
              OnServerClick="CheckSession" Value="View Session State">
</form>
<hr size=1>
<font size=6><span id=span1 runat=server/></font>

Код нужно сохранить в файле с расширением .aspx и загрузить файл на площадку в директорию сайта