`
bcyy
  • 浏览: 1942855 次
文章分类
社区版块
存档分类
最新评论

ADO.NET中的数据关系

 
阅读更多
传统的ADO与ADO.NET最大的区别在于以ADO.NET存储的RowSets有真正的相互关系。例如,一个DataSet存储包含客户信息的Customers表和客户订单的Orders表,在ADO.NET中,这些表之间可以具有联系,并且重新创建了在关系数据库中的联系。对ADO.NET来说,一旦你再次得到这两个行集合的数据(换句话说,有父子关系的表的数据),并且使他们之间具有联系,你就可以通过给定的Parent来访问所有Rows,同时显示任何一个表(any one DataTable in a grid),或者修改表对象的几行数据,并将修改批量更新到数据库。DataRelation对象最为ADO.NET应用的一部分,能实现这些功能。
本栏,我将探讨通过ADO.NET在多层次结构中(相对单一的RowSet(通过INNER JOIN))呈现数据上正反两方面的意见。我会解释DataRelation对象如何提高应用程序的性能,并讨论实现他们应该做些什么 。我会通过一些Demo来做说明,这些Demo创建了通过DataRelation对象产生联系的一系列DataTale对象,就能访问Parent和Children RowSets,并及联更新整个DataSet。
为什么使用DataRelation
在我转入任何代码事例之前,理解数据关系带来了什么和在你运用它之前需要考虑些什么是很重要的。关键因素包括是否运用数据关系,如何使用他们来带来数据冗余(how to use them involve the issue of data redundancy.),应用程序需要如何显示数据,应用程序需要如何管理数据更改。开始我会挑几点并演示如何实现关系。
在2002年2月的MSDN Magazine 的Data Point栏目中,我演示了如何去扩展应用程序,这样就避免了使用ADO.NET DataRelation对象到处对多级数据层次结构进行修改的麻烦。在那个栏目中我所演示的样例是一个在WebForm中使用DataGrid控件来显示存储数据的标准应用。(DataGrid控件对使用关系数据表DataTable对象是理想的,因为它内置了对这些关系的支持。)本栏我会将重点放在DataRelation对象上并解释使用它们相对于使用传统的SQL连接(join)语句的优缺点。
本栏的例子中,我将涉及到Northwind数据库的customer-to-orders-to-order具体的层次结构。在考虑是使用单一的包含连接(join)的数据表还是使用一系列的有关系的数据表时,这里有一些关键考虑的事项要记住。管理数据的两个基本功能是显示数据和管理数据修改(both to the database and within the data structure itself)。
如果你想简单的显示数据,并不要求任何数据的更改,那么选择就主要取决于你想显示单个表格还是多个。如果数据只用来显示单个表格,那么使用连接存储数据最适合。只是因ADO.NET能存储多个有关联的数据表,并不是意味开发者必须每次都使用他们。就象使用Phillips的螺丝起子拧不一定象使用普通的螺丝起子拧一样有效,关联数据表可能在特定情况下不是最有效的方案。如果你的目的只是显示数据的话,使用一系列的表格优于使用单一的表格来显示,并存储到关联的表中,这样更适合。(and you would prefer to display the data in a series of grids rather than in a single grid,storing the data in releated DataTable objects is more appropriate.)
仅显示数据这种情况是普遍的,那么要求显示和数据更改的应用就不同了。对这类应用来说,拥有显示数据的合适工具和管理数据更改的能力是至关重要的,这里就是ADO.NET真正灵活的地方。通过将客户,订单和订单详细信息存储到三个分开的彼此关联的表中,你就可以轻松的在表格中显示它们,并管理每个表的任何数据更改。关联行集rowset的DataRelation对象会在通过GetChanges方法将数据更改保存到底层数据库之前会被过滤掉,这样就只有更改的数据被保存到了数据源。
连接查询和分割查询
使用DataTable和DataRelation对象关联的行集RowSet也可以帮助消除的冗余数据,这些数据对单一的连接行集来说是本身固有的。例如,连接cutomers,orders,order details表为单一的行集,这对每个订单和订单详情行来说就复制了指定的客户数据(例如,客户的名字及公司名称)。例如,假如一个客户有5个订单,没个订单有5个订单详情,那么这个客户数据会有25行数据信息。对于使用SQL的开发者来说这太可怕了,然而使用层次数据结构如XML和ADO.NET关系数据表对象是消除这些冗余数据的好方法。
最普遍的行类型来源于连接查询。例如,查询客户及其他们的订单,使用SQL语法会放回一个单一的行集。这个行集为每条客户订单都复制客户信息,因此产生了数据冗余。再加入订单详情到这个连接查询的话,将产生更多的数据冗余。(Figure 1)
Joining Customers, Orders, and Order Details
SELECTc.CustomerID,
c.CompanyName,
c.ContactName,
o.OrderID,
o.OrderDate,
od.ProductID,
p.ProductName,
od.UnitPrice,
od.Quantity
FROMCustomersc
INNERJOINOrdersoONc.CustomerID=o.CustomerID
INNERJOIN[OrderDetails]odONo.OrderID=od.OrderID
INNERJOINProductspONod.ProductID=p.ProductID
更新一个来源于多个表的行集是非常麻烦的,如果你想更新parent数据。例如,如果你想更新customer-to-orders-to-order details行集的customer数据的话,由于冗余数据,你必须重新查询数据库确保行集中的所有行都被更新。使用ADO.NET中的DataRelation对象时,这个行集会被插入基行集并相互关联起来,使合成后的DataSet跟实际结构更接近。通过将查询插入相互关联的三个数据表的关系结构中,消除冗余数据。更新数据变的更容易,现实客户及其订单也更自然。
使用关联数据表另一个优点是在更新数据库时能增加灵活性。当数据被分别放在customers,orders,order details数据表中并通过DataRelation对象相互关联起来时,每个数据表的数据都能对其中的数据使用指定的命令来更新数据到数据库。例如,包含customer行集的数据表能将修改了的数据保存到数据库,使用根据Northwind数据库的customers表而定的SqlCommand对象。这个SqlCommand对象可能涉及SQL语句或存储过程,它与用于更新数据表更改到数据源的SqlDataAdapter对象联合使用。本栏的后面窝会演示如何使用这些对象并使用SQL Server 2000 Northwind数据库提供的样例代码将更改存入层次结构中。(make modifications to a hierarchical structure)
数据修整
在XML程序员迷恋于层次数据结构的年代里,ADO.NET就已经将它在实现基于Microsoft.NET的应用中变的很简单了。在搜索每个应用中实现层次数据结构中,以前的ADO版本已经有个称为数据修整(Data Shaping)的技术了。当数据修整表示层次结构时,还存在一些很严重的缺点一致没有得到认可(it alse has some drawbacks significant enough that it hasn’t caught on in the mainstream),而且,为使用数据修整你必须学习SHAPE语法。
当数据修整要求专用的数据提供程序和语法的时候,ADO.NET中的层次数据结构就能用标准的我们都熟悉并喜爱的SQL提供程序和SQL语法来创建了。数据修整和其他传统ADO的XML特征都被添加到左右,使得XML变得很受欢迎,并被使用,然而,ADO本身并没有构建XML,因此它有个根本性的缺点,这个缺点在ADO.NET中必须予以解决。而传统的ADO的XML特点,诸如数据形成和存储XML是很有用的,ADO.NET中的XML特点是迄今最全面的。我从来没有听过一个单身人士说,他们曾去想念数据整形语法。
定义数据关系
如何使用DataRelation定义层次rowset呢?让我们来看看,DataSet包含了客户,及其它们的订单,和他们的订单详情的能使用DataRelation对象将他们关连起来三个独立的数据表。使用DataSet包含通过DataRelation对象连接在一起的数据表,可以级联更新,浏览parent纪录,送不同的数据源连接数据,甚至不用在数据库中就可以整合数据。第一步,创建存储三个独立的源于三个独立查询的RowSetDataSet对象(Figure 2)
Creating a DataSet
//Createtheconnection
stringsCn
="DataSource=(local);InitialCatalog=northwind;
UserID=sa;Password=yourpassword";
SqlConnectionoCn
=newSqlConnection(sCn);
DataSetoDs
=newDataSet();
//—FillthecustomerDataTable
stringsSqlCustomer
="SELECTCustomerID,CompanyName,ContactName
FROMCustomers";
SqlDataAdapteroDaCustomer
=newSqlDataAdapter(sSqlCustomer,oCn);
oDaCustomer.Fill(oDs,"Customer");

//—FilltheorderDataTable
stringsSqlOrder
="SELECTCustomerID,OrderID,OrderDateFROMOrders";
SqlDataAdapteroDaOrder
=newSqlDataAdapter(sSqlOrder,oCn);
oDaOrder.Fill(oDs,"
Order");
//—FilltheorderdetailDataTable
stringsSqlOrderDetail
="SELECTod.OrderID,od.ProductID,
p.ProductName,"
+
"od.UnitPrice,od.Quantity
FROM[OrderDetails]od"+
"
INNERJOINProductspONod.ProductID=p.ProductID";
SqlDataAdapteroDaOrderDetail
=newSqlDataAdapter(sSqlOrderDetail,
oCn);
oDaOrderDetail.Fill(oDs,"OrderDetail");
Figure 2中的Code创建一个包含所有客户的DataTable,和包含所有订单的第二个DataTable和包含所有订单详情的第三个DataTableDataSet。在这一点上,code定义了DataSet包含了三个RowSet,但是关系还没确定。为关联DataTable,我使用两个DataRelation对象:一个用来关联客户和他们的订单,另一个用来关联订单和他们的详情。Figure 3显示了如何为这些情况创建DataRelation对象,在Figure 2种构建code样例。
Creating DataRelation Objects
//CreatetheDataRelationand
//—relatethecustomerstotheirorders
DataRelationoDr_Customer2Order
=newDataRelation("Customer2Order",
oDs.Tables
["Customer"].Columns["CustomerID"],
oDs.Tables
["Order"].Columns["CustomerID"]);
oDs.Relations.
Add(oDr_Customer2Order);

//CreatetheDataRelationand
//—relatetheorderstotheirorderdetails
DataRelationoDr_Order2OrderDetail
=new
DataRelation("Order2OrderDetail",
oDs.Tables
["Order"].Columns["OrderID"],
oDs.Tables
["OrderDetail"].Columns["OrderID"]);
oDs.Relations.
Add(oDr_Order2OrderDetail);
通过创建DataRelation对象,并添加到DataSet的Relations集合中,三个DataTable对象的RowSet通过定义的字段相互关联起来。象大多数ADO.NET对象一样,DataRelation对象有多个不同的构造函数。我使用接受关系名,父表的列和子表的列的构造函数。假如定义关系的多个列,可以传给一个父表列的集合和子表列的集合。另一种选择是使用相同的三个参数中的第一个参数,我在Figure 3中使用过,然后传入第四个参数表示约束是否被自动创建(传入一个布尔值)。但是立刻会有更多的约束。
DataSet一旦被三个RowSet和关联DataTable对象的关系填充时,DataSet就可以轻松的使用DataGrid显示在Web页面上,只要象下面一样设置一下DataSource属性:
dataGrid1.DataSource=oDs;
DataGrid很聪明,他可以判断有多个需要显示数据表,并且它应该允许RowSet按DataRelation对象规定的规则被操纵。
约束和级联
就像数据库,DataSet对象中的外键约束帮助约束数据完整性。当我创建在Figure 3种创建Customer2OrderDataRelation时,自动创建了父表主键(customer.customerid)的唯一性约束和子表外键(order.customerid)约束。外键约束会在DataSet呈现到WEB页面的DataGrid时自动起作用(be in effect)。因此,如果你试图修改子纪录的外键值为一个父表主键中不存在的值时,会产生一个违背完整性约束的错误。为演示这个,你应该通过设置DataSet的EnforceConstraints属性为false来取消约束,以使他们不会被强制。除为证明起见,我不推荐这样做,因为这将让你的用户违反数据和应用的完整性。
通过外键支持级联更新和删除是SQL Server 2000的新特征。例如,如果你开启了SQL Server 2000中的这些功能并且你删除父表中的一行,相关联的子表的行也会被删除。ADO.NET有类似的功能,这些功能可以通过ForeignKeyConstraint对象的DeleteRule和UpdateRule属性来控制。默认的,这些规则用于对关联数据进行级联修改。因此如果你改变了客户表的CustomerID的值,那么订单表中的CustomerID也会随着更新。然而,通过设置属性为Rule的枚举值来改变它们,Rule枚举值有Cascade(默认的),None,SetDefault,或者SetNull。
为创建自己的外键约束,你可以定义ForeignKeyConstraint对象。这可以让你灵活的定义列和约束规则,然后运用约束。下面的代码片断演示了怎样建立一个ForeignKeyConstraint和并和DataRelation联合:
ForeignKeyConstraintoFKey;
oFKey
=newForeignKeyConstraint("CustomerForeignkey",
oDs.Tables[
"Customer"].Columns["CustomerID"],
oDs.Tables[
"Order"].Columns["CustomerID"]);
oFKey.DeleteRule
=Rule.Cascade;
oFKey.UpdateRule
=Rule.Cascade;
oDs.Tables[
"Customer"].Constraints.Add(oFKey);
oDs.EnforceConstraints
=true;
父与子
当你有一个DataRelatin对象,他的重要之处是知道如何向上和向下浏览父和子的RowSet。例如,你想要循环遍历特定客户的订单,你要取出这些订单,由于DataRelation已经被你确定了。Figure 4演示了如何取出所有子表的行并遍历他们。
Looping Through Child Rows
//—Retrievethechildrowsforthefirstcustomer
DataRow[]oRows=
oDs.Tables[
"Customer"].Rows[0].GetChildRows(oDr_Customer2Order);
stringsMsg="Theordersforthefirstcustomerare: ";
//—Loopthroughthechildrowsforthefirstcustomer
for(inti=0;i<oRows.Length;i++)
...{
//—Grabthevaluesforeachchildrowofthefirstcustomer
DataRowoRow=oRows[i];
sMsg
+=" "+oRow["CustomerID"].ToString()+
""+oRow["OrderID"].ToString()+
""+oRow["OrderDate"].ToString()+" ";
}

//—Displaythevaluesofthechildrows
MessageBox.Show(sMsg);
Figure 4还显示了如何取出第一个客户的所有儿子并遍历他们。但你想找到父表行或某数据表的行。(But what if you want to find the parent row or rows of a DataTable?)如果有可能多于一行,你可以使用GetParentRows方法。然而,对于我的例子来说,每个订单只有一个父行,因此我使用GetParentRow方法。这个代码显示如何通过Order DataTable的第一行的引用取得父表Customer DataTable的值:
DataRowoRow=
oDs.Tables[
"Order"].Rows[0].GetParentRow(oDr_Customer2Order);
MessageBox.Show(oRow[
"CompanyName"].ToString());
结论
另一个值得注意的特征是ADO.NET如何使自己的XML这样容易。ADO.NET把XML作为他的基础,因此你可以通过ADO.NET将DataSet转化到XML。使用DataSet的WriteXml,WriteXmlSchema,GetXml,和GetXmlSchema方法,你可以取得放在(represent)背后DataSet结构下的XML。在本栏的例子中使用GetXml方法会产生一个包含XML的字符串。GetXmlSchema方法取得数据的模式而GetXml方法取得数据和模式:
MessageBox.Show(oDs.GetXml());
你也可以使用ReadXml和ReadXmlSchema方法从一个XML字符串或文件创建DataSet。例如,你可以使用WriteXml方法保存一个包括结构和数据的DataSet为XML文件,然后,你可以使用ReadXml方法从相同的XML文件创建DataSet。记住ADO.NET关系的关键点是,首先你该确定你是否需要,关系是非常适合应用在需要层叠表示的数据。然而,如果你的情况,包括以单表格格式显示数据,一系列相关RowSet可能不能为单一的连接RowSet带来什么好处。在以后的栏目中,我会在ADO.NETSQL Serverexpression-based栏目进一步介绍DataRelation对象,如何执行批量更新,通过SqlCommandBuilder来找捷径,并发行和一致性的考虑。
分享到:
评论

相关推荐

    学生管理系统+ADO.NET+SQL2005

    接着,ADO.NET的DataSet和DataTable对象扮演了数据容器的角色,它们可以加载从SQL Server查询到的数据,同时提供了在内存中操作数据的能力。在添加、修改或删除学生信息时,可以通过DataTable对象直接操作,然后使用...

    数据访问技术系列课程(2):ADO.NET 连接方式进行数据访问

    3. **数据适配器(DataAdapter)**:`SqlDataAdapter`是ADO.NET中的关键组件,它充当了数据库与数据集(DataSet)之间的桥梁。数据适配器可以从数据库填充数据集,也可以将数据集中的更改同步回数据库,实现数据的...

    一个ADO.NET数据库操作实例

    `ADO.NET与数据控件综合实例.pptx`可能是一个演示文稿,详细介绍了如何在Windows Forms或ASP.NET应用中使用ADO.NET数据控件,如`GridView`、`DataGrid`和`DataSet`等。这些控件允许开发者将数据库中的数据绑定到用户...

    ADO.NET 全面解析ADO.NET

    ADO.NET是Microsoft开发的一种用于访问关系数据库的数据访问技术,它为.NET Framework应用程序提供了一套全面的数据访问组件。本文将深入探讨ADO.NET的核心概念、对象模型和数据操作。 首先,我们来看ADO.NET的设计...

    ADO.NET 4从入门到精通

    在《ADO.NET 4从入门到精通》的五大部分内容中,分别重点介绍了ADO.NET系统的不同侧面。具体包括基本概念、在分别采用内外数据源时如何使用这一技术、实体框架、linq和其他一些主题。本章主要面向ADO.NET技术的初学者...

    ADO.NET 4从入门到精通源代码

    - **DataSet**: ADO.NET的核心组件,它是一个离线数据集合,可以包含多个DataTable,支持数据的增删改查操作。 - **DataTable**: 表示数据库中的表,包含行(DataRow)和列(DataColumn)。 - **Connection对象**...

    ado.net面试题

    7. **XML集成**:ADO.NET 与XML紧密结合,可以轻松地在XML和关系数据之间转换,增强了数据的可移植性和互操作性。 8. **管理提供者**:针对不同数据库系统,ADO.NET 有不同的管理提供者,如SQL Server 的`SqlClient...

    ADO.NET sql、LINQ to sql、ADO.NET Entity Framework(EF)数据库连接性能比较

    ADO.NET SQL是最原始的.NET数据访问接口,它提供了对SQL Server的直接、低级的访问。开发者可以直接编写SQL语句,执行存储过程,并通过DataSets、DataTables等对象处理结果。这种方式灵活性高,但需要编写大量的SQL...

    ADO.NET核心技术(我看过最好的ADO。NET书)

    1. **对象模型**:ADO.NET对象模型包括.NET数据提供程序、联机对象、脱机对象、元数据以及强类型`DataSet`对象等。 2. **数据访问**:ADO.NET库包含了一系列类,可以与各种数据源连接、提交查询并处理结果。 3. **...

    ADO.NET本质论.rar

    1. ADO.NET架构:介绍ADO.NET的组件和它们之间的关系,以及如何协同工作以实现数据访问。 2. 数据连接管理:详细讲解如何创建和管理数据库连接,包括连接字符串的构建、连接池的概念及使用。 3. 数据操作:涵盖如何...

    ADO.NET本质论.pdf

    2.3.2 使用ado.net数据提供程序编写泛型数据访问代码 2.3.3 数据提供程序模型中的游标 2.4 断开模式和dataset 2.5 .net中的xml api 2.5.1 流式xml 2.5.2 xml架构 2.5.3 xmldocument,xpath和...

    ADO.net数据访问存储

    3. **DataAdapter 对象**:DataAdapter 是 ADO.NET 中的数据桥梁,它负责在数据库和数据集(DataSet)之间传输数据。当需要填充数据集时,可以使用 DataAdapter 的 Fill 方法;当需要将数据集中的更改保存回数据库时...

    PPT ADO.NET课件

    ADO.NET是微软.NET框架中用于访问数据库的核心组件,它提供了一组全面的接口和服务,使得开发者可以高效地处理数据。本课件将深入探讨ADO.NET的相关知识点,包括但不限于以下内容: 1. 数据访问架构:ADO.NET采用...

    ADO.NET数据库访问技术案例教程

    ADO.NET是微软.NET框架下的一种数据访问技术,用于与各种关系型数据库进行交互。它提供了一组组件和服务,使得开发者可以高效、灵活地存取和处理数据。在本"ADO.NET数据库访问技术案例教程"中,我们将深入探讨ADO...

    ADO.NET官方参考文档2021-09.pdf

    ADO.NET 是 .NET Framework 中用于访问关系数据库的关键组件,它提供了与各种数据源(如 SQL Server、Oracle 等)交互的灵活性。在2021-09版的官方参考文档中,主要关注了DataSet、DataTable、DataView这三个核心类...

    ado.net简介(flash)

    ADO.NET是微软.NET框架中的一个核心组件,用于访问和操作各种数据源,如关系数据库、XML文档、甚至其他数据提供程序。它为开发者提供了一种高效、灵活且可靠的手段来处理数据,支持离线操作和数据缓存,使得应用程序...

    ADO.NET_DataSet(数据集

    ADO.NET中的DataSet是.NET Framework中一个非常重要的组件,它提供了一种在应用程序中存储和处理数据的方式,即使在没有与数据库连接的情况下也能进行数据操作。DataSet可以被看作是一个轻量级的数据库,它在内存中...

    ado[1].net中文手册 学习 ado.net的重要资料

    ADO.NET 是微软.NET框架中用于访问和管理数据的核心组件,它提供了一种高效、灵活的方式来与各种数据源交互,包括关系数据库、XML文件、Web服务等。此中文手册是学习ADO.NET的重要参考资料,涵盖了从基础概念到高级...

    ADO.NET中一些重要的概念

    - DataSet是断开式的,可以在内存中持久化数据,支持多表和数据关系,但读取速度相对较慢。 4. **ADO.NET与传统ADO的区别**: - ADO.NET使用DataSet代替了Records,支持多表数据和关系。 - ADO.NET的数据可以以...

    ADO.NET技术内幕

    数据集是ADO.NET中的一个内存缓存,它可以存储来自多个数据源的数据,并提供了关系型数据的表示。数据集中包含了DataTable对象,用于存储表格数据,以及DataRelation对象,用于定义表间的关系。 3. **数据适配器...

Global site tag (gtag.js) - Google Analytics