为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

数据库开发

2012-04-20 49页 pdf 1MB 22阅读

用户头像

is_356250

暂无简介

举报
数据库开发 数据库开发 林林在大学期间有过一段实习经历,在实习的过程中她不经意间发现自己工作的地方居然和一个著名 软件公司相距咫尺。很快她就知道该公司采用的是国际化的管理模式,效益非常好,是盛产“IT 精英”的 好地方,于是她便产生了加盟该软件公司的念头。不过打听之后林林却抽了一口冷气:公司用人非常苟刻, 尽管前来应聘的都是大学生中的佼佼者,但淘汰率仍高达 90%,更可气的是该公司基本不会给女性晋升管 理层的机会,所以直接应聘几乎没有可能。然而她没有放弃,她选择了另外一种方式——“曲线救国”。 ...
数据库开发
数据库开发 林林在大学期间有过一段实习经历,在实习的过程中她不经意间发现自己工作的地方居然和一个著名 软件公司相距咫尺。很快她就知道该公司采用的是国际化的管理模式,效益非常好,是盛产“IT 精英”的 好地方,于是她便产生了加盟该软件公司的念头。不过打听之后林林却抽了一口冷气:公司用人非常苟刻, 尽管前来应聘的都是大学生中的佼佼者,但淘汰率仍高达 90%,更可气的是该公司基本不会给女性晋升管 理层的机会,所以直接应聘几乎没有可能。然而她没有放弃,她选择了另外一种方式——“曲线救国”。 在工作之余,林林走遍了全市的大街小巷,搜集了所有同类产品的相关资料,对接触过该公司软件产 品的人群进行咨询。 上至政府高官、公司老板,下至学生、公司职员,她都悉心请教不厌其烦。两个月下来,林林瘦了一 圈,但她却整理了近百页的调查分析。在这些报告中,她提供了各种准确数据,分析了软件公司的业 务模式和不同人群的用户需求,以及同类软件产品市场的发展动态等,更重要的是,林林发现了该公司市 场覆盖的盲点和潜在的危机,而且附上了自己的建议,当然还有求职申请。 当这饱含林林心血的通过有效渠道送达公司总裁的案头后,该公司领导层当天即召开公司会 议,就林林提供的材料一一进行讨论。一周后,该公司总裁亲自驾车邀林林加盟。 后来林林的同事告诉她,当时公司就要不要她直接进入管理层进行了非常激烈的争论,因为软件行业 的特点该公司管理层不接纳女性似乎成了惯例。但最后总裁发话:“用事实说话,我看林小姐所做的诸位不 一定都能做到,那么你们能呆在这里开会她为什么不能?再说,这样的人才我们如果不加以重用,我们的 竞争对手可不会不要,那样将使我们面临更大的威胁!” 对于公司而言,也许一个普通的应届生并不是他们所需要的,他们需要的是能直接为公司创造价值的 “人才”。所以,在做任何事情之前,如果我们能做到“知己知彼”,充分了解对方的各种信息,明白企业到底需 要什么,从而作出相应的反应和对策,无疑是最好的。其实,做技术开发亦是如此! 5 200 .NET 深入体验与实战精要 数据库的应用在我们的生活和工作中已经无处不在,无论是一个小企业的 OA 系统, 还是中国移动的运营系统,似乎都离不开数据库的应用。对于大多数应用程序来说,不管它 们是 Windows 桌面应用程序,还是 Web 应用程序,存储和检索数据都是其核心功能。所以针 对数据库的开发已经成为软件开发的一种必备技能。如果说过去是“学好数理化,走遍天下 都不怕”,那么,对于今天的软件开发者而言就是“学好数据库,走到哪儿都不怵!”。 5.1 ADO.NET 与抽水的故事 ADO.NET 是微软新一代.NET 数据库的访问架构,ADO 是 ActiveX Data Objects 的缩写。 ADO.NET 是数据库应用程序和数据源之间沟通的桥梁,主要提供一个面向对象的数据访问 架构,用来开发数据库应用程序。 5.1.1 ADO.NET 的定义 ADO.NET 是为.NET 框架而创建的,它提供对 Microsoft SQL Server、Oracle 等数据源 及通过 OLE DB 和 XML 公开的数据源的一致访问。应用程序可以使用 ADO.NET 来连接到 这些数据源,并检索、操作和更新数据。ADO.NET 是对 Microsoft ActiveX Data Objects(ADO) 的一个跨时代的改进,是一种全新的数据访问方法,是一项新技术、新。它提供了平台 互用性和可伸缩的数据访问。由于传送的数据都是 XML 格式的,因此任何能够读取 XML 格式的应用程序都可以进行数据处理。事实上,接受数据的组件不一定要是 ADO .NET 组件, 它可以是一个基于 Microsoft Visual Studio 的解决方案,也可以是任何运行在其他平台上的应 用程序。 简单地讲,ADO.NET 是用于和数据源打交道的.NET 技术,是一组向 .NET 程序员公 开数据访问服务的类。ADO.NET 提供了一个统一的编程模式和一组公用的类来进行任何类 型的数据访问,而不管你用何种语言来开发代码。 ADO.NET 有两个重要组成部分:.NET 数据提供程序(.NET Data Provider)和数据集 (DataSet)。 1..NET 数据提供程序(.NET Data Provider) .NET 数据提供程序是一个类集,用于连接到数据库、执行命令和检索结果。可以直接 处理检索到的结果,或将其放入 DataSet 对象中。它可以被认为是数据库与应用程序的一个 接口件或中间件。由于现在使用的数据源有多种(SQL Server、OLEDB 、ODBC 、Oracle), 在编写应用程序的时候就要针对不同的数据源编写不同的接口代码,这很麻烦,效率也不高, 针对这一问题 Data Provider 向上(应用程序)提供了统一的编程模型,向下(数据源)提供 了多种数据源的接口,这样一来就可以使应用程序不需关心什么数据源,即对数据源进行了 屏蔽,其好处是无论什么样的数据源,对于应用程序来说都只需提供一种编程模式即可。 201 5 数据库开发 针对不同的数据源,目前在.NET 平台中包含如下.NET 数据提供程序。 z SQL Server .NET 数据提供程序:提供专门针对 SQL Server 7.0 版或更高版本的数据 访问。使用 System.Data.SqlClient 命名空间。 z OLEDB .NET 数据提供程序:适合于使用 OLE DB 公开的数据源。使用 System.Data.OleDb 命名空间。 z ODBC .NET 数据提供程序:针对一些老式的数据源的访问。 z Oracle .NET 数据提供程序:针对 Oracle 数据库的访问(需要 Oracle Client 的支持)。 z MySQL .NET 数据提供程序:针对 MySQL 的数据访问(需要 MySQL Connector/Net 的支持)。 z SQLite .NET 数据提供程序(非官方,由 sqlite.phxsoftware.com 提供)。 z PostgreSQL .NET 数据提供程序(非官方,由 pgfoundry.org/projects/npgsql 提供)。 备注: OLE DB 是一种技术标准,目的是提供一种统一的数据访问接口,这里所说的“数据”, 除了标准的关系型数据库中的数据之外,还包括邮件数据、Web 上的文本或图形、目录服 务(Directory Services),以及主机系统中的 IMS 和 VSAM 数据。OLE DB 标准的核心内 容就是要求对以上这些各种各样的数据存储提供一种相同的访问接口,使得数据的使用者 (应用程序)可以使用同样的方法访问各种格式的数据,而不用考虑数据的具体存储地点、 格式或类型。 使用 OLE DB 的方法可以通过新建一个后缀是 udl 的文本文件进行编辑,如图 5-1 所示。 图 5-1 OLE DB 设置  虽然 OLE DB .NET 数据提供程序可以访问任何数据源且比较通用,但专门针对特定数 据库类型设计的.NET 数据提供程序(如 SQL Server .NET 数据提供程序、Oracle .NET 数据 提供程序)具有相应的性能优化设计,相比之下 OLE DB .NET 数据提供程序的访问速度更 慢。所以,建议能尽量用特定的数据提供程序的就尽量用数据提供程序。 202 .NET 深入体验与实战精要 .NET 数据提供程序有以下几个核心对象。 z Connection 对象:用于连接数据源。 z Command 对象:对数据源执行命令。 z DataReader 对象:在只读和只写的连接模式下从数据源读取数据。 z DataAdapter 对象:从数据源读取数据并使用所读取的数据填充数据集对象。 所有.NET 数据提供程序都实现了这几个对象各自的版本,附加了它们各自的前缀。 2.数据集(DataSet) DataSet 专门为独立于任何数据源的数据访问而设计。因此,它可以用于多种不同的数 据源,用于 XML 数据,或用于管理应用程序本地的数据。DataSet 包含一个或多个 DataTable 对象的集合,这些对象由数据行和数据列,以及有关 DataTable 对象中数据的主键、外键、 约束和关系信息组成。 我们可以看一下 ADO.NET 的多数据库连通性的特点,如图 5-2 所示。 OleDbConnection OleDbDataAdapterOleDbCommand OleDbDataReader DataSet SqlConnection SqlDataAdapter SqlCommand SqlDataReader XM L SQL ServerAccess 图 5-2 ADO.NET 的多数据库连通性 多个类型数据库,上层共享单一 DataSet 对象,实现单应用程序下多数据库底层支持。 本章不再使用大量篇幅来阐述 ADO.NET 的原理细节,而从实际项目应用的角度言简意 赅地说明 ADO.NET 的使用方法和常见问题。 5.1.2 趣味理解 ADO.NET 对象模型 为了更好地理解 ADO.NET 的架构模型的各个组成部分,我们可以对 ADO.NET 中的相 关对象进行图示理解,如图 5-3 所示的是 ADO.NET 中数据库对象的关系图。 203 5 数据库开发 图 5-3 ADO.NET 对象模型 我们可以用趣味形象化的方式理解 ADO.NET 对象模型的各个部分,如图 5-4 所示,可 以看出这些对象所处的地位和对象间的逻辑关系。 图 5-4 ADO.NET 趣味理解图 趣味理解 对比 ADO.NET 的数据库对象的关系图,我们可以用对比的方法来形象地理 解每个对象的作用,如图 5-4 所示。 z 数据库好比水源,存储了大量的数据。 z Connection 好比伸入水中的进水笼头,保持与水的接触,只有它与水进 行了“连接”,其他对象才可以抽到水。 z Command 则像抽水机,为抽水提供动力和执行方法,通过“水龙头”, 然后把水返给上面的“水管”。 z DataAdapter、DataReader 就像输水管,担任着水的传输任务,并起着桥 梁的作用。二者是有不同的,后面章节中将详细介绍。 z DataSet 则是一个大水库,把抽上来的水按一定关系的池子进行存放。 即使撤掉“抽水装置”(断开连接,离线状态),也可以保持“水”的 存在。这也正是 ADO.NET 的核心。 z DataTable 则像水库中的每个独立的水池子,分别存放不同种类的水。 一个大水库由一个或多个这样的水池子组成。 204 .NET 深入体验与实战精要 5.1.3 进水笼头——建立 Connection Connection 表示与数据源之间的连接。可根据 Connection 对象的各种不同属性来指定数 据源的类型、位置及其他属性,可用它来与数据库建立连接或断开连接。其他对象如 DataAdapter 和 Command 对象通过它与数据库通信。根据.NET Framework 数据提供程序的 不同,也有几种不同的 Connection,如针对 SQL Server 的 SqlConnection、针对 Oracle 的 OracleConnection、针对 MySQL 的 MySqlConnection、针对 OLEDB 的 OleDbConnection 等。 (本节代码示例位置:光盘\code\ch05\01) 1.用 SqlConnection 连接 SQL Server (1)加入命名空间: using System.Data.SqlClient; (2)连接数据库: string conString = "data source=127.0.0.1;Database=codematic;user id=sa;passwo rd="; SqlConnection myConnection = new SqlConnection(conString); myConnection.Open(); 2.用 OracleConnection 连接 Oracle 首先添加 OracleClient 的引用,如图 5-5 所示。 图 5-5 添加 OracleClient 的引用 (1)加入命名空间: using System.Data.OracleClient; (2)连接数据库: string conString = "Data Source=codematic;User ID=codeuser;Password=user123"; 205 5 数据库开发 OracleConnection myConnection = new OracleConnection(conString); myConnection.Open(); 3.用 MySqlConnection 连接 MySQL 在.NET 中连接 MySQL 数据库有两种方法:MySQL Connector/ODBC 和 MySQL Connector/NET,ODBC 连接器是符合 ODBC 标准的交互平台,是.NET 访问 MySQL 数据库 的最好的选择。 首先,我们下载安装 MySql-connector-net-5.1.5.Data.msi 这个组件。如果是默认安装, 则可以在 C:\Program Files\MySQL\MySQL Connector Net 5.1.5\Binaries\.NET 2.0(这里安装的 是 MySQL Connector/Net 5.1.5,老的 1.1 版本是:C:\Program Files\MySQL\MySQL Connector Net 1.0.4\bin\.NET 1.1\)中找到 MySql.Data.dll,将该文件复制到项目的 bin 目录下。 然后在项目引用中添加 MySql.Data.dll 的引用,如图 5-6 所示。 图 5-6 添加 MySql.Data.dll 的引用 实现代码如下。 (1)加入命名空间: using MySql.Data.MySqlClient; (2)连接数据库: string conString = "server=127.0.0.1;database=mysql;user id=root;password=123"; MySqlConnection myConnection = new MySqlConnection(conString); myConnection.Open(); 4.用 OleDbConnection 连接各种数据源 由于数据源不同,相应的连接字符串也会不同。 (1)加入命名空间: using System.Data.OleDb; (2)连接 SQL Server: 206 .NET 深入体验与实战精要 string conString = " Provider=SQLOLEDB.1;Persist Security Info=False; User ID=sa;Database=Codematic;Data Source=COMPUTER"; OleDbConnection myConnection = new OleDbConnection(conString); myConnection.Open(); (3)连接 Access(可通过建立.udl 文件来获得字符串): string conString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source =C:\\Database1.mdb;Persist Security Info=False"; (4)连接 Oracle(也可通过 OracleConnection 连接): string conString = "Provider=MSDAORA.1;User ID=user; Password=123; Data Source=db;Persist Security Info=False"; 从以上几个对象实例对比来看,几个.NET 数据提供程序组件模型的基本编程模式相同, 只是组件对象的前缀有所区别,正是这种统一编程模型,让我们在做不同类型数据库开发时, 变得非常简单。 5.1.4 抽水机——Command Command 对象封装了与用户想要完成的动作相关的数据库命令。在一般情况下这些命 令就是 SQL 语句。 1.构造 SqlCommand (1)初始化 SqlCommand 类的新实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString); SqlCommand myCommand = new SqlCommand(); myCommand.Connection = myConnection; myCommand.CommandText = "update P_Product set Name='电脑1' where Id=52"; myConnection.Open(); int rows = myCommand.ExecuteNonQuery(); myConnection.Close(); (2)初始化具有查询文本的 SqlCommand 类的新实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString ); string strSql = "update P_Product set Name='电脑2' where Id=52"; SqlCommand myCommand = new SqlCommand(strSql); myCommand.Connection = myConnection; myConnection.Open(); int rows = myCommand.ExecuteNonQuery(); myConnection.Close(); 207 5 数据库开发 (3)初始化具有查询文本和 SqlConnection 的 SqlCommand 类实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString ); string strSql = "update P_Product set Name='电脑3' where Id=52"; SqlCommand myCommand = new SqlCommand(strSql, myConnection); myConnection.Open(); int rows = myCommand.ExecuteNonQuery(); myConnection.Close(); (4)初始化具有查询文本、SqlConnection 和 Transaction 的 SqlCommand 类实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString ); string strSql = "update P_Product set Name='电脑4' where Id=52"; string strSql2 = "update P_Product set Name='数码4' where Id=53"; myConnection.Open(); SqlTransaction myTrans = myConnection.BeginTransaction(); SqlCommand myCommand = new SqlCommand(strSql, myConnection, myTrans); try { int rows = myCommand.ExecuteNonQuery(); myCommand.CommandText = strSql2; rows = myCommand.ExecuteNonQuery(); myTrans.Commit(); myConnection.Close(); } catch { myTrans.Rollback(); } 2.建立 SqlCommand 与 SqlConnection 的关联 myCommand.Connection = myConnection; //或者 SqlCommand myCommand = myConnection.CreateCommand; 3.设置 SqlCommand 的查询文本 myCommand.CommandText = "SELECT * FROM P_Product "; //或者第2种构造: SqlCommand myCommand = new SqlCommand(strSql); 4.执行命令 SqlCommand 方法如表 5-1 所示。 208 .NET 深入体验与实战精要 表 5-1 SqlCommand 方法 方 法 说 明 ExecuteReader 返回一行或多行。多用于 SELECT 查询数据 ExecuteNonQue ry 对 Connection 执行 SQL 语句,并返回受影响的行数(int),多用于 INSERT、 UPDATE、DELETE、CREATE 等操作 ExecuteScalar 返回单个值。返回结果集中第一行的第一列。忽略额外的列或行 ExecuteXmlRea der 将 CommandText 发送到 Connection 并生成一个 XmlReader 对象 例如: string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString); SqlCommand cmd = myConnection.CreateCommand(); cmd.CommandText = "SELECT * FROM P_Product"; myConnection.Open(); SqlDataReader dr = cmd.ExecuteReader(); //SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); while (dr.Read())//循环读取数据 { Response.Write(dr.GetInt32(0).ToString() + ", " + dr.GetString(1) + "
"); } dr.Close(); myConnection.Close(); string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString); string strSql = "select count(*) from P_Product"; SqlCommand myCommand = new SqlCommand(strSql, myConnection); myConnection.Open(); int count = (int)myCommand.ExecuteScalar(); myConnection.Close(); Response.Write(count); 很多数据库支持将多条命令合并或批处理成一条单一命令执行。例如,SQL Server 使你 可以用分号“;”分隔命令。将多条命令合并成单一命令,能减少到服务器的行程数,并提 高应用程序的性能。例如,可以将所有预定的删除在应用程序中本地存储起来,然后再发出 一条批处理命令调用,从数据源删除它们。 虽然这样做确实能提高性能,但是当对 DataSet 中的数据更新进行管理时,可能会增加 应用程序的复杂性。要保持简单,需要在 DataSet 中为每个 DataTable 创建一个 DataAdapter。 注 意 使用 SqlCommand 执行存储过程的快速提示:如果调用存储过程,则需将 SqlCommand 的 CommandType 属性指定为 StoredProcedure。这样在将该命令显 式标识为存储过程时,就不需要在执行之前分析命令了。 209 5 数据库开发 5.1.5 输水管——DataAdapter DataAdapter 提供连接 DataSet 对象和数据源的桥梁。DataAdapter 使用 Command 对象在 数据源中执行 SQL 命令,以便将数据加载到 DataSet 中,并使 DataSet 中数据的更改与数据 源保持一致。 趣味理解 DataAdapter 就像一根输水管,通过发动机,把水从水源输送到水库里进行 保存。 1.创建 SqlDataAdapter (1)初始化 SqlDataAdapter 类的新实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString); SqlCommand cmd = myConnection.CreateCommand(); cmd.CommandText = "SELECT * FROM P_Product"; DataSet ds = new DataSet(); myConnection.Open(); SqlDataAdapter adapter = new SqlDataAdapter(); adapter.SelectCommand = cmd; adapter.Fill(ds, "ds"); myConnection.Close(); (2)使用指定的 SqlCommand 初始化 SqlDataAdapter 类的新实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString); DataSet ds = new DataSet(); SqlCommand cmd = myConnection.CreateCommand(); cmd.CommandText = "SELECT * FROM P_Product"; myConnection.Open(); SqlDataAdapter adapter = new SqlDataAdapter(cmd); adapter.Fill(ds, "ds"); myConnection.Close(); (3)使用 selectcommand 字符串 和 SqlConnection 对象初始化 SqlDataAdapter 类的新 实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; string strSQL = "SELECT * FROM P_Product"; SqlConnection myConnection = new SqlConnection(conString); DataSet ds = new DataSet(); myConnection.Open(); SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection); 210 .NET 深入体验与实战精要 adapter.Fill(ds, "ds"); myConnection.Close(); (4)使用 selectcommand 字符串和一个连接字符串初始化 SqlDataAdapter 类的新实例。 string conString = "data source=127.0.0.1;Database=codematic;user id=sa; password="; string strSQL = "SELECT * FROM P_Product"; DataSet ds = new DataSet(); SqlDataAdapter adapter = new SqlDataAdapter(strSQL, conString); adapter.Fill(ds, "ds"); 2.DataAdapter 和 SqlConnection、SqlCommand 建立关联 方式 1:DataAdapter 在构造参数时建立。 方式 2:通过 SelectCommand 属性建立。 SqlDataAdapter adapter = new SqlDataAdapter(); adapter.SelectCommand = new SqlCommand(strSQL, myConnection); 5.1.6 输水管——DataReader 通过执行 ExecuteReader 方法可以返回一个 DataReader 对象。DataReader 以只进、只读 方式返回数据,从而提高应用程序的性能。这样可以节省 DataSet 所使用的内存,并省去创 建 DataSet 并填充其内容所需的处理。 趣味理解 DataReader 也是一种水管,和 DataAdapter 不同的是,DataReader 不把水输 送到水库里面,而是单向地直接把水送到需要水的用户那里或田地里,所以要比 在水库中转一下更快。 (1)遍历 DataReader 结果集。 SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { Response.Write(dr.GetInt32(0).ToString()+ ", "+ dr.GetString(1) + "
"); } dr.Close(); (2)使用序数索引器。 SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { Response.Write(dr[0].ToString() + ", " + dr[1].ToString() + "
"); } dr.Close(); (3)使用列名索引器。 SqlDataReader dr = cmd.ExecuteReader(); 211 5 数据库开发 while (dr.Read()) { Response.Write(dr["ProductId"].ToString()+", "+dr["Name"].ToString()); } dr.Close(); (4)使用类型访问器。 public char GetChar(int i); 获取指定列的单个字符串形式的值 public DateTime GetDateTime(int i); 获取指定列的 DateTime 对象形式的值 public short GetInt16(int i); 获取指定列的 16 位有符号整数形式的值 public string GetString(int i); 获取指定列的字符串形式的值 (5)得到 DataReader 的列信息。 dr.FieldCount 获取当前行中的列数 dr.GetFieldType(序号) 获取是对象的数据类型的 Type dr.GetDataTypeName(序号) 获取源数据类型的名称 dr.GetName(序号) 获取指定列的名称 dr.GetOrdinal(序号) 在给定列名称的情况下获取列序号 (6)得到数据表的信息。 DataTable dt=dr.GetSchemaTable(); (7)操作多个结果集。 SqlDataReader dr = cmd.ExecuteReader(); do { while (dr.Read()) { Response.Write(dr.GetInt32(0).ToString()+", "+dr.GetString(1)); } } while(myReader.NextResult());//使数据读取器前进到下一个结果集 dr.Close(); 下面是一些使用 DataReader 获得最佳性能的技巧。 z 在使用带参数的 Command 前,必须关闭 DataReader。 z 完成读数据之后一定要关闭 DataReader。如果使用 Connection 只返回 DataReader, 那么关闭 DataReader 之后立刻关闭它。另外一个显式关闭 Connection 的方法是将 CommandBehavior.CloseConnection 传递给 ExecuteReader 方法,以确保关闭 DataReader 时相应的连接也被关闭。如果从一个方法返回 DataReader,而且不能控 制 DataReader 的相关连接的关闭,则这样做特别有用。 z 不能在层之间远程访问DataReader。DataReader是为已连接好的数据访问而设计的。 z 当访问列数据时,使用类型化访问器,例如 GetString、GetInt32 等。这使你不用将 GetValue 返回的 Object 强制转换成特定类型。 z 一个单一连接每次只能打开一个 DataReader。如果想在相同的数据存储区上同时打 212 .NET 深入体验与实战精要 开两个 DataReader,则必须显式创建两个连接,每个 DataReader 一个。这是 ADO.NET 为池化连接的使用提供更多控制的一种方法。 z 在默认情况下,DataReader 每次 Read 时都要将整行加载到内存。这允许在当前行 内 随 机 访 问 列 。 如 果 不 需 要 这 种 随 机 访 问 , 为 了 提 高 性 能 , 则 将 CommandBehavior.SequentialAccess 传递给 ExecuteReader 调用。这将 DataReader 的默认行为更改为仅在请求时将数据加载到内存。注意,CommandBehavior. SequentialAccess 要求顺序访问返回的列。也就是说,一旦读过返回的列,就不能 再读它的值了。 z 如果已经读取了来自 DataReader 的数据,但仍然有大量挂起的未读结果,则在关 闭 DataReader 之前先要取消 Command。因为取消 Command 可使服务器放弃这些 结果,从而释放服务器的资源。 5.1.7 随用随关,释放资源 对于 C#程序员来说,确保始终关闭 Connection 和 DataReader 对象的一个方便的方法就 是使用 using 语句。using 语句在离开自己的作用范围时,会自动调用被“使用”的对象的 Dispose。例如: string connectionString = "data source=127.0.0.1;Database=codematic; user id=sa;password="; using (SqlConnection myConnection = new SqlConnection(connectionString)) { SqlCommand cmd = myConnection.CreateCommand(); cmd.CommandText = "SELECT * FROM P_Product"; myConnection.Open(); using (SqlDataReader dr = cmd.ExecuteReader()) { while (dr.Read()) { Response.Write(dr.GetInt32(0).ToString()+","+dr.GetString(1)+"
"); } } } 5.1.8 水库管理——DataSet DataSet是ADO.NET中最核心的成员之一,是各种基于.NET平台程序语言(如VB.NET、 C#.NET、C++.NET)的数据库应用程序开发最常接触的类,这是因为 DataSet 在 ADO.NET 实现从数据库中抽取数据的作用。数据抽取后,DataSet 就是数据的存放地,它是各种数据 源(SQL Server 、OLE DB 等)的数据在计算机内存的缓存,所以有时说 DataSet 可以看成 是一个数据容器(又称数据集)。在客户端通过对 DataSet 的数据集读取、更新等操作,从而 实现对数据源的同等操作。 213 5 数据库开发 DataSet 的最大优点是离线(断开)和连接。DataSet 既可以以离线方式,也可以以实时 连接方式来操作数据库中的数据。这样的好处是大大减少了服务器端数据库的连接线程,从 而大大地减少了服务器端的运行压力。所以,在数据量不大的情况下,使用 DataSet 是最好 的选择。 DataSet 的基本工作过程:应用程序一般并不直接对数据库进行操作(直接在程序中调 用存储过程等除外),而是先完成和数据库的连接,接着通过数据适配器(DataAdapter)把 数据库中的数据填入 DataSet 对象,然后客户端再通过读取 DataSet 来获得需要的数据,同 样,在更新数据库中的数据时,也是首先更新 DataSet,然后再通过 DataSet 和数据适配器将 更新的数据同步地解释入数据库中。 下面列出了 DataSet 的一些常用操作。 1.创建 DataSet 对象 初始化 DataSet 类的新实例。 public DataSet(); 用给定名称初始化 DataSet 类的新实例。 public DataSet(string); 2.用 DataAdapter 填充 DataSet DataSet ds = new DataSet(); adapter.Fill(ds); adapter.Fill(ds, "表名"); //用一个表去填充DataSet. 3.合并两个 DataSet string conString="data source=127.0.0.1;database=codematic;user id=sa; password="; SqlConnection myConnection = new SqlConnection(conString); myConnection.Open(); string strSQL = "SELECT * FROM P_Product"; DataSet ds1 = new DataSet(); SqlDataAdapter adapter1 = new SqlDataAdapter(strSQL, myConnection); adapter1.Fill(ds1, "Product"); strSQL = "SELECT * FROM P_Category"; DataSet ds2 = new DataSet(); SqlDataAdapter adapter2 = new SqlDataAdapter(strSQL, myConnection); adapter2.Fill(ds2, "Category"); myConnection.Close(); //ds1就是合并后的DataSet ds1.Merge(ds2, true, MissingSchemaAction.AddWithKey); 214 .NET 深入体验与实战精要 GridView1.DataSource = ds1.Tables["Product"]; GridView1.DataBind(); GridView2.DataSource = ds1.Tables["Category"]; GridView2.DataBind(); 5.1.9 水池子——DataTable 每一个 DataSet 都是一个或多个 DataTable 对象的集合(DataTable 相当于数据库中的 表),这些对象由数据行(DataRow)、数据列(DataColumn)、字段名(Column Name)、数 据格(Item),以及约束(Constraint)和有关 DataTable 对象中数据的关系(Relations)与数 据显示排序(DataView)信息组成。 DataView 用来在观察数据时提供排序和过滤的功能。DataColumn 用来对表中的数据值 进行一定的规限。比如哪一列数据的默认值是什么、哪一列数据值的范围是什么、哪个是主 键、数据值是否是只读等。 由于一个 DataSet 可能存在多张表,这些表可能存在关联关系,因此用 parentRelations 和 childRelations 来表述。ParentRelations 表是父表,childRelations 是子表,子表是对父表的 引用,这样就使得一个表中的某行与另一个表中的某一行甚至整个表相关联。 1.DataTableCollection 类 表示 DataSet 的表的集合。 DataTableCollection dtc = ds.Tables; DataTable customerTable = dtc["Product"]; 2.DataTable 进行动态的筛选和排序 调用 DataTable.Select()方法,获取 DataRow 对象的数组。 (1)获取所有行。 DataRow[] rows = dt.Select(); (2)按主键顺序(如没有主键,则按照添加顺序)获取符合筛选条件的行。 DataRow[] rows = dt.Select("ID>52"); (3)获取符合筛选条件的行,并按指定的排序条件排序。 DataRow[] rows = dt.Select("ID>52","ID DESC"); (4)获取符合筛选条件和指定状态的行,并按指定的排序条件排序。 string strExpr = "ID>52"; string strSort = "ID DESC"; DataRow[] foundRows = dt.Select(strExpr, strSort, DataViewRowState.OriginalRows); 215 5 数据库开发 3.DataTable 进行数据统计 我们在使用 SQL Server 时,可以轻松地对数据进行 Sum、Aver、Count 等操作以获得统 计结果,那么,在已经把数据检索出来的 DataSet(DataTable)中如何进行统计呢?特别是 通过第三方接口 Web Service 获得了 DataSet,这个时候,没有办法去执行 Select 语句来获取 这些统计,怎么办呢? 办法总比问题多,其实在 DataTable 中也是可以进行数据统计的。 下面就通过几个简单的示例,介绍一下如何无须通过逐条进行计算就可以轻松地获 得 DataTable 中的记录统计结果。这里调用的是功能强大的 DataTable 的函数 Compute。 (1)函数说明: public object Compute(string strExpression,string strFilter); z strExpression:要计算的表达式字符串,基本上类似于 Sql Server 中的统计表达式。 z strFilter:统计的过滤字符串,只有满足这个过滤条件的记录才会被统计。 (2)调用示例。 假设一个产品销售表 P_Sell,描述商场中各销售人员的销售记录,如表 5-2 所示。 表 5-2 产品销售表 序号 列名 数据类型 长度 主键 允许空 说明 1 ID int 4 √ 流水号 2 Name varchar 50 √ 姓名 3 Sex smallint 2 √ 性别:0 为女,1 为男 4 Birthday datetime 8
/
本文档为【数据库开发】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
热门搜索

历史搜索

    清空历史搜索