Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Существуют средства доступа, берущие на себя накладные расходы, но, как и в любой программной модели, за это приходится платить снижением гибкости и полноты контроля. Наиболее популярным таким средством является 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? Смотрите следующую серию.
Алексей Шуленин