架构部分
架构部分是必需的。 如前面的示例所示,ADO 写出有关每列的详细元数据,从而尽可能保留数据值的语义来进行更新。 但 ADO 只需列名及其所属的行集即可在 XML 中进行加载。 以下是最小的架构示例:
<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly">
<s:AttributeType name="ShipperID"/>
<s:AttributeType name="CompanyName"/>
<s:AttributeType name="Phone"/>
<s:Extends type="rs:rowbase"/>
</s:ElementType>
</s:Schema>
<rs:data>
...
</rs:data>
</xml>
在前面的示例中,ADO 将数据视为长度可变的字符串,因为架构中不包含类型信息。
为列名创建别名
rs:name 属性支持为列名创建别名,以便易记名称可以出现在行集公开的列信息中,且可以在数据部分中使用较短的名称。 例如,可以修改之前的架构,将 ShipperID 映射到 s1,将 CompanyName 映射到 s2,将 Phone 映射到 s3,如下所示:
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:updatable="true">
<s:AttributeType name="s1" rs:name="ShipperID" rs:number="1" ...>
...
</s:AttributeType>
<s:AttributeType name="s2" rs:name="CompanyName" rs:number="2" ...>
...
</s:AttributeType>
<s:AttributeType name="s3" rs:name="Phone" rs:number="3" ...>
...
</s:AttributeType>
...
</s:ElementType>
</s:Schema>
然后,在数据部分,行将使用 name 属性(而不是 rs:name)来引用此列:
"<row s1="1" s2="Speedy Express" s3="(503) 555-9831"/>
只要列名不是 XML 中的有效属性或标记名,就需要为列名创建别名。 例如,“LastName”必须具有别名,因为具有嵌入空格的名称是无效属性。 XML 分析程序将无法正确处理以下行,因此必须为其他没有嵌入空格的名称创建别名。
<row last name="Jones"/>
无论对 name 属性使用什么值,在 XML 文档的架构和数据部分中引用列的每个位置都必须一致使用该值。 以下示例显示了对 s1 的一致使用:
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly">
<s:attribute type="s1"/>
<s:attribute type="CompanyName"/>
<s:attribute type="s3"/>
<s:extends type="rs:rowbase"/>
</s:ElementType>
<s:AttributeType name="s1" rs:name="ShipperID" rs:number="1"
rs:maydefer="true" rs:writeunknown="true">
<s:datatype dt:type="i4" dt:maxLength="4" rs:precision="10"
rs:fixedlength="true" rs:maybenull="true"/>
</s:AttributeType>
</s:Schema>
<rs:data>
<z:row s1="1" CompanyName="Speedy Express" s3="(503) 555-9831"/>
</rs:data>
同样,由于在之前的示例中没有为 CompanyName
定义别名,因此必须在整个文档中一致使用 CompanyName
。
数据类型
可以使用 dt:type 属性将数据类型应用于列。 有关支持的 XML 类型的完整可靠的指南,请参阅 W3C XML-Data 规范的“数据类型”部分。 可以通过两种方式指定数据类型:直接在列定义本身上指定 dt:type 属性或将 s:datatype 构造用作列定义的嵌套元素。 例如,
<s:AttributeType name="Phone" >
<s:datatype dt:type="string"/>
</s:AttributeType>
等效于
<s:AttributeType name="Phone" dt:type="string"/>
如果在行定义中完全省略 dt:type 属性,默认情况下,列的类型将是长度可变的字符串。
如果拥有的类型信息不仅仅是类型名(例如 dt:maxLength),那么使用 s:datatype 子元素会更易读取。 然而,这只是一个约定,而不是要求。
以下示例进一步显示如何在架构中提供类型信息。
<!-- 1. String with no max length -->
<s:AttributeType name="title_id"/>
<!-or -->
<s:AttributeType name="title_id" dt:type="string"/>
<!-- 2. Fixed length string with max length of 6 -->
<s:AttributeType name="title_id">
<s:datatype dt:type="string" dt:maxLength="6" rs:fixedlength="true" />
</s:AttributeType>
<!-- 3. Variable length string with max length of 6 -->
<s:AttributeType name="title_id">
<s:datatype dt:type="string" dt:maxLength="6" />
</s:AttributeType>
<!-- 4. Integer -->
<s:AttributeType name="title_id" dt:type="int"/>
第二个示例对 rs:fixe32dlength 属性进行了细微使用。 将 rs:fixedlength 属性设置为 true 的列意味着数据必须具有架构中定义的长度。 在此情况下,title_id 的有效值为“123456”,“123”也是如此。但“123”是无效的,因为它的长度是 3,而不是 6。 有关 fixedlength 属性的更完整说明,请参阅 OLE DB 程序员指南。
处理 Null
Null 值由 rs:maybenull 属性处理。 如果将此属性设置为 true,列的内容可以包含 Null 值。 此外,如果在一行数据中没有找到列,从行集中读回数据的用户将从 IRowset::GetData() 中获取 Null 状态。 考虑 Shippers 表中的以下列定义。
<s:AttributeType name="ShipperID">
<s:datatype dt:type="int" dt:maxLength="4"/>
</s:AttributeType>
<s:AttributeType name="CompanyName">
<s:datatype dt:type="string" dt:maxLength="40" rs:maybenull="true"/>
</s:AttributeType>
定义支持 CompanyName
为 Null,但 ShipperID
不能包含 Null 值。 如果数据部分包含以下行,暂留提供程序会将 CompanyName
列的数据状态设置为 OLE DB 状态常量 DBSTATUS_S_ISNULL:
<z:row ShipperID="1"/>
如果行完全为空,如下所示,暂留提供程序将为 ShipperID
返回 OLE DB 状态 DBSTATUS_E_UNAVAILABLE,为 CompanyName 返回 DBSTATUS_S_ISNULL。
<z:row/>
请注意,长度为零的字符串与 Null 不同。
<z:row ShipperID="1" CompanyName=""/>
暂留提供程序将为前一行的两列返回 OLE DB 状态 DBSTATUS_S_OK。 在这种情况下,CompanyName
仅为 ""(长度为零的字符串)。
有关可在 OLE DB 的 XML 文档架构中可用的 OLE DB 构造的详细信息,请参阅“urn:schemas-microsoft-com:rowset”的定义和 OLE DB 程序员指南。