与其他 Microsoft .NET Framework 数据访问接口一样,ADOMD.NET 也用作应用程序与数据源之间的桥梁。
但 ADOMD.NET 与其他 .NET Framework 数据访问接口的不同之处在于 ADOMD.NET 处理的是分析数据。
为了处理分析数据,ADOMD.NET 支持的功能与其他 .NET Framework 数据访问接口所支持的功能差异很大。
ADOMD.NET 不仅可检索数据,还可检索元数据并更改分析数据存储区的结构:
检索元数据
应用程序可使用架构行集或对象模型,进一步了解通过元数据检索从数据源检索的数据。如可用的关键绩效指标 (KPI) 的类型、多维数据集中的维度和挖掘模型所需的参数等信息都可以发现。对于“动态”应用程序而言,元数据最为重要,这些应用程序需要用户输入以确定要检索的数据的类型、深度和范围。此类应用程序的例子有查询分析器、Microsoft Excel 以及其他查询工具。对于执行一组预定义操作的“静态”应用程序而言,元数据的重要性就要低一些。
检索数据
数据检索是对存储在数据源中的信息的实际检索。数据检索在知晓数据源结构的“静态”应用程序中是主要功能。数据检索也是“动态”应用程序的最终结果。一天中给定时间的 KPI 值、每个商店上一小时内的的自行车销售量以及影响雇员的年度业绩的因素,这些数据都是可以检索的。检索数据对于任何查询应用程序都是至关重要的。
更改分析数据的结构
ADOMD.NET 还可用于实际更改分析数据存储区的结构。虽然这通常是通过分析管理对象 (AMO) 对象模型进行的,但您也可以使用 ADOMD.NET 来发送 Analysis Services 脚本语言 (ASSL) 命令,从而创建、更改或删除服务器中的对象。
检索元数据、检索数据和更改数据结构均发生在典型 ADOMD.NET 应用程序的工作流中的特定点。
典型处理流程
传统的 ADOMD.NET 应用程序在处理分析数据时,通常遵循相同的工作流:
首先,使用 AdomdConnection 对象与数据库建立连接。打开连接时,AdomdConnection 对象会公开所连接到的服务器的元数据。在动态应用程序中,其中的某些信息通常会显示给用户,以便用户做出选择,如查询哪个多维数据集。应用程序可多次重用此步中创建的连接,以降低开销。
连接建立后,动态应用程序即可从服务器查询更多特定元数据。对于静态应用程序,由于程序员事先知道应用程序要查询哪些对象,因此不需要检索这些元数据。应用程序和用户可以在下一步骤中使用检索到的元数据。
接下来,应用程序对服务器运行一条命令。执行这一命令的目的既可以是检索其他元数据或检索数据,也可以是修改数据库结构。对于这些任务中的任何一个,应用程序都可以使用先前确定的查询,也可以使用新检索的元数据创建其他查询。
命令发送到服务器后,服务器即开始向客户端返回元数据或数据。使用 CellSet 对象、AdomdDataReader 对象或 System.XmlReader 对象可查看此信息。
为了说明这种传统工作流,下面的示例包含了一个方法,该方法先打开一个与数据库的连接,再对一个已知多维数据集执行一条命令,然后检索结果并将其放入一个单元集。随后,该单元集返回一个以制表符分隔的包含列标题、行标题和单元数据的字符串。
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->string ReturnCommandUsingCellSet()
{
//Create a new string builder to store the results
System.Text.StringBuilder result = new System.Text.StringBuilder();
//Connect to the local server
using (AdomdConnection conn = new AdomdConnection("Data Source=localhost;"))
{
conn.Open();
//Create a command, using this connection
AdomdCommand cmd = conn.CreateCommand();
cmd.CommandText = @"
WITH MEMBER [Measures].[FreightCostPerOrder] AS [Measures].[Reseller Freight Cost]/[Measures].[Reseller Order Quantity],
FORMAT_STRING = 'Currency'
SELECT
[Geography].[Geography].[Country].&[United States].Children ON ROWS,
[Date].[Calendar].[Calendar Year] ON COLUMNS
FROM [Adventure Works]
WHERE [Measures].[FreightCostPerOrder]";
//Execute the query, returning a cellset
CellSet cs = cmd.ExecuteCellSet();
//Output the column captions from the first axis
//Note that this procedure assumes a single member exists per column.
result.Append("\t");
TupleCollection tuplesOnColumns = cs.Axes[0].Set.Tuples;
foreach (Tuple column in tuplesOnColumns)
{
result.Append(column.Members[0].Caption + "\t");
}
result.AppendLine();
//Output the row captions from the second axis and cell data
//Note that this procedure assumes a two-dimensional cellset
TupleCollection tuplesOnRows = cs.Axes[1].Set.Tuples;
for (int row = 0; row < tuplesOnRows.Count; row++)
{
result.Append(tuplesOnRows[row].Members[0].Caption + "\t");
for (int col = 0; col < tuplesOnColumns.Count; col++)
{
result.Append(cs.Cells[col, row].FormattedValue + "\t");
}
result.AppendLine();
}
conn.Close();
return result.ToString();
} // using connection
}