Введение в SQL Server Analysis Services для разработчика. ADOMD.NET.
Существуют средства доступа, берущие на себя накладные расходы, но, как и в любой программной модели, за это приходится платить снижением гибкости и полноты контроля. Наиболее популярным таким средством является ADOMD.NET – аналог ADO.NET для многомерных данных. Библиотека ADOMD.NET ставится в составе SQL Server, либо ее можно скачать и установить отдельно. Она раздается в составе SQL Server Feature Pack. Для SQL Server 2008 R2 ее на данный момент можно взять здесь (СТР3 – ноябрь 2009). Для просто SQL Server 2008 ее на данный момент можно взять здесь (октябрь 2009). Найдите в перечне фич Microsoft ADOMD.NET и скачайте. Для SQL Server 2005 тоже где-то есть.
Рассмотрим в качестве примера отправку XMLA-запроса с помощью ADOMD.NET.
Создайте новое консольное приложение. Предварительно в проект требуется добавить ссылку на C:\Program Files\Microsoft.NET\ADOMD.NET\100\Microsoft.AnalysisServices.AdomdClient.dll:
Рис.1
Разрешите использование типов в пространстве имен Microsoft.AnalysisServices.AdomdClient:
Рис.2
Запустите на выполнение код:
using System;
using Microsoft.AnalysisServices.AdomdClient;
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
string xmla = @"<Statement>SELECT Measures.MEMBERS ON COLUMNS FROM [Adventure Works]</Statement>";
AdomdConnection cnn = new AdomdConnection("Data Source=http://192.168.0.29/msolap/msmdpump.dll; User ID=192.168.0.29\\Administrator; Password=AbraCada<br>a");
cnn.Open();
AdomdCommand cmd = new AdomdCommand(xmla, cnn);
cmd.Properties.Add("Catalog", "Adventure Works DW 2008R2");
cmd.Properties.Add("Format", "Multidimensional");
cmd.Properties.Add("AxisFormat", "TupleFormat");
CellSet res = cmd.ExecuteCellSet();
cnn.Close();
Debug.WriteLine("");
foreach (Cell c in res.Cells) Debug.Write(String.Format("{0} ; ", c.FormattedValue));
Debug.WriteLine("\n");
}
}
Скрипт 1
Для счастливчиков, успевших установить Visual Studio 2010 Release Candidate, - получите ошибку The type or namespace name 'AnalysisServices' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?). И это невзирая на то, что IntelliSence только что его прекрасно видел. Зайдите в свойства проекта и исправьте Target framework c .NET Framework 4 Client Profile, который VS по умолчанию ставит для консольных приложений и Win-форм, на полный .NET Framework 4:
Рис.3
Об отличиях можно прочитать здесь.
Снова запустите приложение на выполнение. Теперь оно выполнится нормально
Рис.4
и мы можем продолжить наш разговор про ADO.NET. Во-первых, ADOMD.NET предоставляет модель доступа, инвариантную по отношению к протоколу. В случае, когда в качестве Data Source выступает ISAPI dll (с префиксом http://), ADOMD.NET шлет SOAP-запрос по HTTP. Мы могли бы написать в качестве Data Source просто имя OLAP-сервера:
AdomdConnection cnn = new AdomdConnection("Data Source=192.168.0.29;");
cnn.Open();
Скрипт 2
В этом случае SOAP-запрос автоматически отправлялся бы по ТСР. Понятно, что когда на пути нет IISа, осуществляющего промежуточную аутентификацию, MS AS будет аутентифицировать по Windows credentials и указывать User ID; Password не требуется.
Во-вторых, обратите внимание на урезанный вид XMLA-запроса в Скрипте 1 по сравнению со Скриптом 1 из предыдущего поста. От него остался только элемент Statement:
<Statement>SELECT Measures.MEMBERS ON COLUMNS FROM [Adventure Works]</Statement>
Скрипт 3
Если попытаться запихать запрос в ADOMD.NET в его первоначальном полном варианте (см. Скрипт 1 из поста MDX и XMLA):
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body>
<Execute xmlns='urn:schemas-microsoft-com:xml-analysis'>
<Command>
<Statement>SELECT Measures.MEMBERS ON COLUMNS FROM [Adventure Works]</Statement>
</Command>
<Properties>
...
</soap:Envelope>
Скрипт 4
произойдет ошибка The soap:Envelope element at line 7, column 85 (namespace http://schemas.xmlsoap.org/soap/envelope/) cannot appear under Envelope/Body/Execute/Command, из которой следует, что ADOMD.NET за нас заворачивает текст команды в SOAP-конверт. Следовательно, в качестве текста AdomdCommand потребляется InnerXml элемента Command XMLA-запроса. Что мы и видели на примере окна MDX-запроса в SSMS. См., напр., Рис.3 в посте XMLA DDL. Тот пример на команду резервного копирования можно выполнить из ADOMD.NET следующим образом:
cnn.Open();
AdomdCommand cmd = new AdomdCommand(
@"<Backup xmlns='http://schemas.microsoft.com/analysisservices/2003/engine'>
<Object>
<DatabaseID> Adventure Works DW 2008R2</DatabaseID>
</Object>
<File>Adventure Works DW.abf</File>
<AllowOverwrite>true</AllowOverwrite>
</Backup>",
cnn);
cmd.Execute();
cnn.Close();
Скрипт 5
Т.е. Inner XML из элемента Command, как и говорилось выше.
В случае MDX Query в SSMS для DML-запросов можно опускать не только скобки в виде элемента Command, но и вообще ограничиться Inner XML из элемента Statement. Так, от нашего первоначального SOAP XMLA-запросa (Скрипт 1 из поста MDX и XMLA) в результате остается только
Рис.5
а в Скрипте 1, соответственно -
string xmla = "SELECT Measures.MEMBERS ON COLUMNS FROM [Adventure Works]";
...
Скрипт 6
Невозможность послать через ADOMD.NET полноценный XMLA-запрос, а только его подмножество в виде элемента Command вызывает некоторый дискомфорт. Внутри элемента Execute наряду с Command идут также Properties и Parameters (http://msdn.microsoft.com/en-us/library/ms186691.aspx). Если AdomdCommand оперирует только с внутренностью элемента Command, как передать ей свойства и параметры? Далее, как быть с методом Discover, про который еще толком не говорилось, только упоминалось, что он есть наравне с Execute? Он ведь вообще не имеет элемента Command. Там различие начинается на более высоком уровне. Что в этом случае выполнять в ADOMD.NET? Смотрите следующую серию.
Алексей Шуленин