Partager via


Введение в SQL Server Analysis Services для разработчика. Discover из ADOMD.NET.

Содержание предыдущей серии.

 

Средствами ADOMD.NET XMLA-запросы с методом Discover выполнять немного хитрее, чем Execute. Если ничтоже сумняшеся забабахать запрос из поста Метод Discover\Скрипт 1 в в AdomdCommand по аналогии, например, со Скриптом 2 поста про MDX-запросы, произойдет ошибка

 

class Program

{

    static void Main(string[] args)

    {

        AdomdConnection cnn = new AdomdConnection("Data Source=localhost");

        cnn.Open();

        AdomdCommand cmd = new AdomdCommand(@"

           <Discover xmlns='urn:schemas-microsoft-com:xml-analysis'>

             <RequestType>DBSCHEMA_CATALOGS</RequestType>

             <Restrictions />

             <Properties />

           </Discover>", cnn);

        cmd.Execute();

        cnn.Close();

    }

}

Скрипт 1

 

image

Рис.1

Это происходит потому, что, как уже неоднократно отмечалось выше, AdomdCommand воспринимает только InnerXml элемента <Command> XMLA-запроса, т.е. она может выполнять только запросы метода Execute. Ну вот так устроена ADOMD.NET.

Для выполнения Discover-запросов в ADOMD.NET существет метод GetSchemaDataSet(), который выполняется непосредственно над соединением AdomdConnection. Первым параметром в нем является строка с названием риквест тайпа или его гуидом. Гуиды риквест тайпов можно видеть при помощи Скрипта 4 поста Метод Discover. Кроме того, добрые люди, писавшие ADOMD.NET, предусмотрели enum (перечислимый тип) AdomdSchemaGuid, который избавляет от необходимости обременять свою память или заниматься копи-пастом гуидов. Скажем, вместо строки "DBSCHEMA_CATALOGS" можно написать AdomdSchemaGuid.Catalogs и т.д. (см., к примеру, Рис.3).

 

AdomdConnection cnn = new AdomdConnection("Data Source=localhost");

cnn.Open();

 

DataSet ds = cnn.GetSchemaDataSet("DBSCHEMA_CATALOGS", null); //Вторым параметром идут Restrictions

 

cnn.Close();

 

DataTable dt = ds.Tables[0];

Debug.WriteLine("");

foreach (DataColumn c in dt.Columns) { Debug.Write(c.ColumnName); Debug.Write("; "); }

foreach (DataRow r in dt.Rows)

{

       Debug.WriteLine("");

    for (int i = 0; i < r.Table.Columns.Count; i++)

    {

       Debug.Write(r[i]); Debug.Write("; ");

    }

}

Debug.WriteLine("\n");

 

Скрипт 2

 

image

Рис.2

 

Как говорилось в посте Метод Discover, результатом Discover-запроса является реляционное множество записей (rowset). Его колонками являются те элементы, которые можно видеть в XSD-описании элемента <row> в результатах запроса Скрипт 1 поста Метод Discover:

 

<xsd:complexType name="row">

        <xsd:sequence>

          <xsd:element sql:field="CATALOG_NAME" name="CATALOG_NAME" type="xsd:string" minOccurs="0" />

          <xsd:element sql:field="DESCRIPTION" name="DESCRIPTION" type="xsd:string" minOccurs="0" />

          <xsd:element sql:field="ROLES" name="ROLES" type="xsd:string" minOccurs="0" />

          <xsd:element sql:field="DATE_MODIFIED" name="DATE_MODIFIED" type="xsd:dateTime" minOccurs="0" />

        </xsd:sequence>

      </xsd:complexType>

Скрипт 3

 

Эти результаты можно видеть на Рис.1 поста Метод Discover повыше обведенного фрагмента. Это шапка. Значения Analysis Services берет из недр директории, где лежат данные. Что-нибудь типа %ProgramFiles%\Microsoft SQL Server\MSAS10_50.MSSQLSERVER\OLAP\Data, в зависимости от того, куда происходила установка.

Дополнительными элементами канонического Discover-запроса в XMLA выступают Restrictions и Properties. В аналогичной ситуации Execute-запроса для передачи элементов запроса Parameters и Properties у AdomdCommand существовали свойства-коллекции Parameters и Properties – см., напр., Скрипт 2 поста Параметризованные MDX-запросы. В случае Discover-запроса для передачи Restrictions предназначен второй параметр метода GetSchemaDataSet типа object[] или AdomdRestrictionCollection, а Properties, похоже, не передаются никак. То есть выполнить запрос Скрипта 5 из предыдущего поста нам еще удастся, например, вот так:

 

DataSet ds = cnn.GetSchemaDataSet(AdomdSchemaGuid.SchemaRowsets, new string[] { "MDSCHEMA_DIMENSIONS" });

Скрипт 4

 

или так:

 

AdomdRestrictionCollection restrictions = new AdomdRestrictionCollection();

restrictions.Add("SchemaName", "MDSCHEMA_DIMENSIONS");

DataSet ds = cnn.GetSchemaDataSet("DISCOVER_SCHEMA_ROWSETS", restrictions);

Скрипт 5

 

А вот, допустим, как ему подсунуть

 

<Properties>

    <PropertyList>

      <Catalog>Adventure Works DW 2008R2</Catalog>

    </PropertyList>

</Properties>

 

из Скрипта 2 (тоже предыдущего поста), я уже не знаю. Ну нет нигде для GetSchemaDataSet коллекции Properties. Видимо, просматривая список Properties (Скрипт 3 поста Метод Discover), эти добрые люди решили, что в плане Properties XMLA избыточен, хватит одних Restrictions. Я не поленился заглянуть в профайлер и обнаружил, что когда идет запрос через GetSchemaDataSet, судя по всему, всегда подставляется стандартный набор свойств:

 

<PropertyList xmlns="urn:schemas-microsoft-com:xml-analysis">

  <LocaleIdentifier>1033</LocaleIdentifier>

  <Content>SchemaData</Content>

  <Format>Tabular</Format>

</PropertyList>

 

где LocaleIdentifier определяется текущими установками, а база данных (Catalog), которая здесь явно не указана, по-видимому, берется из свойств соединения AdomdConnection.

 

...

AdomdConnection cnn = new AdomdConnection("Data Source=localhost;Initial Catalog=Adventure Works DW 2008R2");

cnn.Open();

 

DataSet ds = cnn.GetSchemaDataSet(AdomdSchemaGuid.Dimensions, null);

 

cnn.Close();

...

Скрипт 5

 

image

Рис.3

 

Кроме того, как мы помним, всегда остается способ в обход ADOMD заслать Analysis Services напрямую XMLA в чистом виде, т.е. SOAP-запрос по типу Скрипта 1 поста Доступ по SOAP.

 

Переход на следующую серию.

 

Алексей Шуленин