$null строки в Powershell и переиспользование сессий в Analysis Services
В Analysis Services различаются понятия соединения (connection) и сессии (session, в русских BOL - сеанс). Между ними существует отношение многие-ко-многим, в частности, несколько соединений могут шарить одну сессию. Сессия поддерживает контекст состояния: текущий каталог, вычисления и т.д. По умолчанию, каждое новое соединение открывает новую сессию, и по его закрытию она закрывается. Можно закрыть соединение без закрытия сессии, если вызвать перегруженый метод Close соединения AdomdConnection с параметром false. Осиротевшую сессию, т.е.не имеющую связанных с ней открытых соединений, SSAS прибирает после IdleOrphanSessionTimeout. Время жизни неактивной сессии определяется MaxIdleSessionTimeout. Эти и другие конфигурационные настройки сервера Analysis Services можно видеть, если кликнуть по нему правой кнопкой в Object Explorere SSMS, выбрать в контекстном меню пункт Properties и отметить галку Show Advanced (All) Properties. Рис.1 Указанные настройки хранятся в файле C:\Program Files\Microsoft SQL Server\MSAS10_50.MSSQLSERVER\OLAP\Config\msmdsrv.ini. Еще во времена 2005-го Энтони Манн и Эдвард Меломед написали статью «SQL Server 2005 Analysis Services (SSAS) Server Properties», в которой толково объясняется, что означает каждая настройка и на что она влияет. Замечательный документ. Я рекомендую всем его распечатать и пришпилить куда-нибудь на видное место. Более подробно прочитать про различия сессий и соединений можно в BOL – см. Установление соединений в ADOMD.NET и Работа с соединениями и сеансами в ADOMD.NET. С точки зрения производительности бывает выгодно повторно использовать сессии, экономя на пересоздании контекста. В этом случае мы сохраняем в приложении идентификатор сессии (свойство соединения SessionID), a закрывая AdomdConnection, говорим серверу оставить сессию - сnn.Close(false). Перед открытием нового соединения ему присваивается сохраненный идентификатор прежней сессии и, если та еще не проэкспайрилась, оно будет использовать ее контекст. Все просто. Я попытался воспроизвести пример, описанный в книжке Тео Лачева «Applied Microsoft Analysis Services 2005» (п.17.4.3 Managing Connections and Sessions, стр.574), на PowerShell.
Скрипт 1 Смысл скрипта понятен: сначала пытаемся открыть соединение с прежним SessionID, оставшимся от каких-то предыдущих действий. Если таковой истек, сбрасываем $cnn.SessionID обратно в Null и снова пытаемся открыть соединение. Тогда при открытии для него будет автоматически создана новая сессия, и в $cnn.SessionID появится ее идентификатор. К сожалению, этот скрипт не работает из-за одной неприятной особенности PowerShell. При присвоении $null в $cnn.SessionID он конвертируется в пустую строку, т.к. св-во SessionID имеет тип строки. ADOMD.NET обучено заводить новую сессию только в случае, когда свойство SessionID у соединения равно строго Null, т.е. нулевой указатель на область памяти, где хранится содержание строки. Если же там лежит какая-то строка, пусть даже пустая, т.е. указатель непустой, но указывает на пустую область памти, ADOMD.NET воспринимает это как сигнал того, что мы хотим открыть соединение в контексте некоторой сессии. Сессии с SessionID в виде пустой строки она не находит, поэтому соединение не открывает, и цикл будет длиться бесконечно . Когда в переменную сохраняется некоторое значение, хотелось бы быть уверенным, что оно там в целости и неизменности сохранится, и в своем первозданном виде его можно оттуда достать по мере надобности. PowerShell является уникальным языком в этом плане. Можно положить одно, а достать совсем другое:
Скрипт 2 Вопрос: не знает ли кто, как запретить Powershell’у творить такое непотребство? Мне не нужно, чтобы $null конвертировался в пустую строку. Нужно, чтобы $null оставался $null, как это принято во всех нормальных человеческих языцех. В прошлом посте я полагал, что самый занятный язык – это диалект SQL, поддерживаемый Analysis Services. На самом деле, то были цветочки. Самый занятный язык – это PowerShell. Нарекания на такое поведение существуют с незапамятных времен - https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=307821&SiteID=99, http://www.vistax64.com/powershell/160947-string-null-eq-null-eq.html, http://www.techtalkz.com/microsoft-windows-powershell/150495-gotcha-null-string-not-null.html . Возможно, его с тех пор уже поправили. Если вы в курсе таких исправлений, подскажите, и вам воздастся. Пока что воркэраунды, которые удалось найти, достаточно монструозны. Проще переписать Скрипт 1 как
Скрипт 3 Автор: Алексей Шуленин |