OLE DB作为通用API
在微软Windows操作系统中,OLE DB是进行数据访问最常用的API。OLE DB是针对OLE对象的规范。这些OLE对象有一系列标准接口。这些接口的标准化使得一个编程模型几乎可以访问所有类型的数据源。微软SQL Server数据挖掘有一个OLE DB提供程序。这个提供程序能将OLE DB编程模型翻译成数据挖掘所需要的内容。
关于 OLE DB的更多内容,请访问MSDN OLE DB页。
OLE DB可以被很多种编程语言直接使用。在本机(非托管)C++中,可以创建OLE DB对象,并且可以直接调用OLE DB的方法。ALT使用者模版(ALT Consumer Templates)也为OLE DB使用者应用程序提供了一系列有用的类。在Visual Basic或者VBA中,OLE DB提供程序可以在ADO(ActiveX Data Objects,ActiveX数据对象)中使用。在托管语言中,我们可以使用ADO.NET 库来调用OLE DB提供程序。
OLEDB编程模型以如下对象为中心。首先,数据源必须由服务器端初始化和控制。其次,在这个数据源上必须初始化一个通讯对话。OLE DB架构的第三个重要组成部分就是命令,它们将服务器请求打包。每个服务器请求都是对话的一部分。OLE DB架构的第四个组成部分是服务器响应。大多数数据挖掘任务可以被OLE DB命令所执行。例如,可以使用一个命令来传输DMX语句,也可以传输一个DDL语句来创建一个新的元数据。但是命令并不能传输一个发现元数据语句(Discovery)。所以针对此点,OLE DB定义了一个可以被对话执行的IDBSchemaRowset接口。这里我们需要注意的是,ADO和ADO.NET有一个封装了数据源和OLE DB对话的连接对象(Connection)。这两种标准的OLE DE对象(数据源和OLE DB对话)公开的功能在ADO和ADO.NET的连接对象中可用。
所有的OLE DB对象(数据源、对话、命令和响应)经常在COM组件中执行来调用OLE提供程序。
下面的图1给出了一个OLE DB解决方案的框架:
如图中所示,首先,各个客户端上安装的OLE DB提供程序使用OLE DB来连接服务器。Microsoft Analysis Services 2005的OLE DB提供程序是在安装SQL Server 2005的连接组件时安装的。
OLEDB连接经常通过连接字符串的方法来初始化。连接字符串包含一系列有分号分隔开的“名字-值”字符对,即属性。这些属性描述了OLE DB连接初始化时的各个参数。所有的OLE DB包(如ATL使用者模版、ADO、或者ADO.NET)都根据连接字符串来进行初始化。这里给出一个用来连接Microsoft Analysis Services 2005的OLE DB连接字符串的例子:
"Provider=MSOLAP; Data Source=localhost; "
第一个属性 Provider描述示例中指定的提供程序。
"MSOLAP" 是微软分析服务中OLE DB提供程序的名字。请注意这个名字是依赖版本的。如果一台机器上安装了多个分析服务OLE DB提供程序(如一个来自Analysis Services 2005,一个来自Analysis Services 2000),就需要使用更加准确的名字来区分版本:Analysis Services 2000使用“MSOLAP.2”,Analysis Services 2005使用“MSOLAP.3”。第二个属性“Data Source”表示要连接的数据源。它一般都是一个机器名,但是也可以是其它表达方式。例如,它可以是一个文件名,或者是一个网络URL,如我们将在下文“HTTP Pump”章所见到的一样。关于分析服务OLE DB提供程序属性的更多信息,你可以从SQL Server在线信息中得到。
在之前的代码中,可以将CommandText 属性改为一个DDL语句,比如Alter、Create或者Drop;或改为一个DMX语句,如CREATE MINING MODEL或者INSERT INTO,它可以实现绝大多数挖掘任务。唯一一个需要附加补充的是查询挖掘模型。DMX查询与一般的无响应信息语句不同,因为:
• 它返回一个表型结果。
• 表型结果可能包含多级的表(嵌套表)。
• DMX 支持参数。
我们可以从返回单级表的DMX查询开始看起,使用我们最开始使用的对象来对比(命令和连接):
43 Cmd.ActiveConnection = Conn
44 Cmd.CommandText = "SELECT NODE_CAPTION FROM DecisionTree1.CONTENT" _
45 &"where NODE_TYPE=2"
46
47 Dim rs As ADODB.Recordset
48 Set rs = Cmd.Execute()
49 rs.MoveFirst
50 While Not rs.EOF
51 Debug.Print rs.Fields(0).Value
52 Wend
53 rs.Close
如我们之前所提到的一样,DMX语句由CommandText属性来传输。与发现(Discovery)使用相同的方式来遍历Recordset。第44行用到的查询只返回一列,这里并不真正需要从recordset 字段来查找列;相反的,它应该由它的索引得到(第51行)第0字段的内容。也请注意第53行中对Recordset 的配置。当Recordset 是活跃的时候,命令对象不能执行之后的语句。
OLE DB规范也允许返回更加复杂的结果集,如表型列或者嵌套表。下面给出一个服务器响应是嵌套表的例子,我们将使用DMX语句来添加查询更复杂的第二列NODE_DISTRIBUTION。所以新的查询如下所示:
"SELECT NODE_CAPTION, NODE_DISTRIBUTION FROM DecisionTree1.CONTENT WHERE NODE_TYPE=2"
NODE_DISTRIBUTION 是一个典型的嵌套表例子。根据数据挖掘的OLE DB规范,模型中的NODE_DISTRIBUTION列包含当前行所在节点的属性值的分布。例如,在一棵预测头发颜色的决策树中,对每一个树节点,这一列都描述有多少实例是黑发,多少实例是金发,多少实例是灰发。
执行命令在新的一列中并不改变。实际上唯一需要改变的就是Recordset的遍历代码,需要进行适合表的新列的改变。在代码中可以很容易的从Recordset 作为字段值的属性返回一列的值。如果实例中的列是一个嵌套表,列值将产生一个新的Recordset,再遍历整个嵌套表。
所以,在51行以下应该执行如下的代码:
52 Debug.Assert( rs.Fields(1).Type = adChapter)
53 Dim nestedRS As ADODB.Recordset
54 Set nestedRS = rs.Fields(1)
55 nestedRS.MoveFirst
56 While Not nestedRS.EOF
57 Debug.Print nestedRS.Fields(0).Value
58 Wend
59 nestedRS.Close
第52行语句用来在将值写入嵌套Recordset前,确认列的类型是正确的。这行语句也可以用来判断制定的列是不是一个嵌套表。
应为拥有遍历嵌套表的能力,此时数据挖掘查询产生的任何返回值都可以在你的应用中被使用了。
DMX也支持查询中的参数。参数可以取代DMX查询中的任何值。例如,可以使用一个参数来代替上述查询语句中where子句里的NODE_TYPE 的值“2”。在数据挖掘应用中,也有少数参数非常有用的场景,比如生成一个单独的查询(关于单独查询的详细内容,请看“Adomd.NET”一节)。
想在DMX查询中将一个值变为一个参数,我们使用参数指示标志@来开始替换,使用“@唯一的参数名”。这样VBA代码片段中的第45行就可以变成:
45 &"where NODE_TYPE=@typeParam"
然后,在执行命令之前,我们应该插入这样的一段代码来确保能正确的使用新的参数。请注意,尽管实际数据可能与参数的值很不同,但是使用参数并不会改变服务器响应的格式。所以上述遍历Recordset 的代码可以并不改变。
46 Cmd.NamedParameters = True
47
48 Dim typeParameter As ADODB.Parameter
49 Set typeParameter = Cmd.CreateParameter()
50 typeParameter.Direction = adParamInput
51 typeParameter.Name = "typeParam"
52 typeParameter.Value = 2
53 typeParameter.Type = adInteger
54 typeParameter.Size = 4
55
56 Cmd.Parameters.Append typeParameter
在分析服务的OLE DB提供程序中使用参数时,如下的几步非常重要:
• 命令必须使NamedParameters可用(第46行)。分析服务的OLE DB提供程序只支持命名了的参数。
• 参数的名字必须符合查询中的相应参数,但是在这里不使用@前缀(第51行)。
• 可以只传输参数(第50行)。
• 参数的类型和大小必须声明(第53和54行)。
想对数据挖掘的OLE DB规则进行很好的理解,需要充分使用Microsoft Analysis Services 2005数据挖掘的特性。一旦设计好了数据挖掘查询,OLE DB就成为了一个可以执行它们、可以管理数据挖掘服务器的完整且具有通用性的API。关于在非托管C++或ADO.NET中C#使用OLE DB 的代码,请看本文附录2中的代码片段。