对数据库操作,就是处理各种数据事务,或者在你的网页上把数据按照一定的组织形式显示出来。
.NET中ADO.NET就提供了这样的功能。不过ADO.NET也够复杂的,所以很多人用了半天,还是一头雾水。
1、ADO的结构
ADO中使一系列的类,按功能,大致可分为连接用、执行命令用、填充数据用三类。另外还有些支持事务处理的类。
诸如SqlConnection,OleDBConnection,ODBCConnection等连接器,分别表示连接SQL Server, OleDB兼容驱动数据连接器,和ODBC兼容数据连接器。他们的作用就是用来和数据源连接。SQL Server也提供了OleDB和ODBC兼容的数据库驱动,所以使用OleDBConnection和ODBCConnection也可以连接到SQL Server,但ODBCConnection要在ODBC数据连接池中作设置。况且后两者性能都不是最好的,所以Microsoft又开发了SqlConnection,专门针对Sql的连接。
诸如SqlCommand,OleDBCommand,ODBCCommand等类,是执行SQL命令使用。分别对应上述不同的连接器。Command可以执行的命令根据数据库能够支持而决定,一般来说,我们最常使用它的SELECT来检索数据。
诸如SqlDataReader, OledbDataReader等,这些阅读器是通过执行Command的ExecuteReader方法创建出来的。阅读器算是ADO中最轻量级的数据检索类了,但是它只是ADO的一个小角落,Reader提供的功能少之又少,只能读取数据不能写数据,每次读一行,使用DataReader.Read命令读,使用DataReader.GetValue(int Index)获取所读到单前行中索引为Index的列的值,况且,DataReader还必须和数据库保持连接,单这一点来说,DataReader付出的连接成本是相当高的,所以DataReader不是任何时候都适用,但是它很简单,所以很多教材中都以它来说明数据库连接的例子,大多数初学者也宁愿使用DataReader。
诸如SqlDataAdapter, OledbDataAdapter等,我们都叫这一类对象叫作DataAdapter(数据适配器)。这个理解理解起来比较困难一些,但是既然叫做适配器,不妨做个比喻:例如计算机中的网卡(专业名称叫网络适配器),他的作用就是将网络上传来的属于这台计算机的数据收下来,并处理后提交给计算机,计算机将要发送的数据给网卡,网卡负责将其打包封装,然后放在网络上,不难看出,网卡充当了数据传递沟通处理转换的桥梁。DataAdapter也是一样的,DataAdapter本质上也是靠SQL命令来实现数据桥梁,桥梁的一端是数据库Database,另外一端是DataSet,关于DataSet,稍后会描述。要想从数据库取得数据填充DataSet,需要使用Select命令,这个命令是DataAdapter.SelectCommand属性保存的Command命令对象执行的,要想从DataSet将数据更新到数据库,需要联合使用DELETE,UPDATE和INSERT命令,这些命令也是分别由DataAdapter.DeleteCommand,DataAdapter.UpdateCommand,DataAdapter.InsertCommand属性所指定的Command对象执行的。DataAdapter提供Fill方法填充数据,用Update方法更新数据。
DataSet,这是ADO.NET的核心,也是最复杂的类了,DataSet可以理解为“内存中的数据库”,所以DataSet至少是一个数据表的容器,他还可以定义约束,而且还可以读入XSD建立一个“类型化”的DataSet,这些超出了本文讨论的范围了,留给以后的文章去。
如果创建无类型的DataSet,这是比较简单的,使用DataSet ds = new DataSet();即可。无类型的DataSet里面什么都没有,接下来我们就可以用DataAdapter将数据填充到DataSet中,填充后的DataSet结构取决于DataAdapter中的SelectCommand的命令内容。
如下这样,定义了一个创建和设置了一个完整的DataAdapter,虽然代码量有点大,不过很容易就能看懂:
"alling, UserCity, UserEduLevel, UserGender, UserIDCard, UserIncoming, UserInfID," & _
" UserJob, UserMobilePhone, UserNextGet, UserPoint, UserPostAddress, UserPostCode" & _
", UserProvince, UserRealName, UserTel FROM UserInfo WHERE (UserInfID = 0)"
Me.OleDbSelectCommand1.Connection = Me.connMain
'
'OleDbInsertCommand1
'
Me.OleDbInsertCommand1.CommandText = "INSERT INTO UserInfo(BoundUserID, CanLogin, DefaultPostMode, InfCreateDateTime, U" & _
"serBorn, UserCalling, UserCity, UserEduLevel, UserGender, UserIDCard, UserIncomi" & _
"ng, UserJob, UserMobilePhone, UserNextGet, UserPoint, UserPostAddress, UserPostC" & _
"ode, UserProvince, UserRealName, UserTel) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " & _
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
Me.OleDbInsertCommand1.Connection = Me.connMain
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("BoundUserID", System.Data.OleDb.OleDbType.Integer, 0, "BoundUserID"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("CanLogin", System.Data.OleDb.OleDbType.VarWChar, 10, "CanLogin"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("DefaultPostMode", System.Data.OleDb.OleDbType.VarWChar, 50, "DefaultPostMode"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("InfCreateDateTime", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "InfCreateDateTime"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserBorn", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "UserBorn"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserCalling", System.Data.OleDb.OleDbType.VarWChar, 50, "UserCalling"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserCity", System.Data.OleDb.OleDbType.VarWChar, 50, "UserCity"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserEduLevel", System.Data.OleDb.OleDbType.VarWChar, 50, "UserEduLevel"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserGender", System.Data.OleDb.OleDbType.VarWChar, 50, "UserGender"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserIDCard", System.Data.OleDb.OleDbType.VarWChar, 50, "UserIDCard"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserIncoming", System.Data.OleDb.OleDbType.VarWChar, 50, "UserIncoming"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserJob", System.Data.OleDb.OleDbType.VarWChar, 50, "UserJob"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserMobilePhone", System.Data.OleDb.OleDbType.VarWChar, 50, "UserMobilePhone"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserNextGet", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "UserNextGet"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserPoint", System.Data.OleDb.OleDbType.Integer, 0, "UserPoint"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserPostAddress", System.Data.OleDb.OleDbType.VarWChar, 50, "UserPostAddress"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserPostCode", System.Data.OleDb.OleDbType.VarWChar, 50, "UserPostCode"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserProvince", System.Data.OleDb.OleDbType.Integer, 0, "UserProvince"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserRealName", System.Data.OleDb.OleDbType.VarWChar, 50, "UserRealName"))
Me.OleDbInsertCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserTel", System.Data.OleDb.OleDbType.VarWChar, 50, "UserTel"))
'
'OleDbUpdateCommand1
'
Me.OleDbUpdateCommand1.CommandText = "UPDATE UserInfo SET BoundUserID = ?, CanLogin = ?, DefaultPostMode = ?, InfCreate" & _
"DateTime = ?, UserBorn = ?, UserCalling = ?, UserCity = ?, UserEduLevel = ?, Use" & _
"rGender = ?, UserIDCard = ?, UserIncoming = ?, UserJob = ?, UserMobilePhone = ?," & _
" UserNextGet = ?, UserPoint = ?, UserPostAddress = ?, UserPostCode = ?, UserProv" & _
"ince = ?, UserRealName = ?, UserTel = ? WHERE (UserInfID = ?)"
Me.OleDbUpdateCommand1.Connection = Me.connMain
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("BoundUserID", System.Data.OleDb.OleDbType.Integer, 0, "BoundUserID"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("CanLogin", System.Data.OleDb.OleDbType.VarWChar, 10, "CanLogin"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("DefaultPostMode", System.Data.OleDb.OleDbType.VarWChar, 50, "DefaultPostMode"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("InfCreateDateTime", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "InfCreateDateTime"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserBorn", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "UserBorn"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserCalling", System.Data.OleDb.OleDbType.VarWChar, 50, "UserCalling"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserCity", System.Data.OleDb.OleDbType.VarWChar, 50, "UserCity"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserEduLevel", System.Data.OleDb.OleDbType.VarWChar, 50, "UserEduLevel"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserGender", System.Data.OleDb.OleDbType.VarWChar, 50, "UserGender"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserIDCard", System.Data.OleDb.OleDbType.VarWChar, 50, "UserIDCard"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserIncoming", System.Data.OleDb.OleDbType.VarWChar, 50, "UserIncoming"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserJob", System.Data.OleDb.OleDbType.VarWChar, 50, "UserJob"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserMobilePhone", System.Data.OleDb.OleDbType.VarWChar, 50, "UserMobilePhone"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserNextGet", System.Data.OleDb.OleDbType.DBTimeStamp, 0, "UserNextGet"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserPoint", System.Data.OleDb.OleDbType.Integer, 0, "UserPoint"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserPostAddress", System.Data.OleDb.OleDbType.VarWChar, 50, "UserPostAddress"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserPostCode", System.Data.OleDb.OleDbType.VarWChar, 50, "UserPostCode"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserProvince", System.Data.OleDb.OleDbType.Integer, 0, "UserProvince"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserRealName", System.Data.OleDb.OleDbType.VarWChar, 50, "UserRealName"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("UserTel", System.Data.OleDb.OleDbType.VarWChar, 50, "UserTel"))
Me.OleDbUpdateCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_UserInfID", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "UserInfID", System.Data.DataRowVersion.Original, Nothing))
'
'OleDbDeleteCommand1
'
Me.OleDbDeleteCommand1.CommandText = "DELETE FROM UserInfo WHERE (UserInfID = ?)"
Me.OleDbDeleteCommand1.Connection = Me.connMain
Me.OleDbDeleteCommand1.Parameters.Add(New System.Data.OleDb.OleDbParameter("Original_UserInfID", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "UserInfID", System.Data.DataRowVersion.Original, Nothing))
这里面着重设置了SelectCommand,UpdateCommand,InsertCommand,DeleteCommand的SQL语句。其中SQL语句使用了参数形式,所以看起来比较复杂。
DataSet本身表示一个内存中的数据库,因此他是一系列表DataTable对象的集合,这些DataTable表对象又可理解为行DataRow对象的集合,而每个DataRow的Item集合表示该行的列集合,通过对Item检索得到指定的数据。当然DataSet配合显示数据的专门控件,可以达到强大的效果。
2、关于数据显示控件Repeater,DataList,DataGrid
他们都可以显示数据,功能顺次逐渐强大,但是灵活性却逐渐降低,什么时候用什么控件关键看你用在什么场合。Repeater很简单,仅仅是根据数据源有多少条目而重复定义在其模板中的代码,而DataList和DataGrid是从TableList派生来的,所以他们会产生一系列Table,tr,td等标记,某些场合并不适用(比如遵循Web2.0规范中,对表格的使用作出限制)。DataGrid和DataList都可以编辑数据,DataGrid在DataList的基础上又增加了分页功能。这也是人们用得最多的功能。
Repeater,DataList,DataGrid很容易使用,只需首先为DataSet填充了数据,指定Repeater,DataList,DataGrid的数据源指向这些DataSet,然后接下来分别调用他们的DataBind()方法将数据加载。在项模板中,使用类似<%# Container.DataItem("ColumnName")%>这样的绑定语句,加载的数据即可显示出来,DataGird为某些常见的数据类型提供了模板,使用起来还要方便些。当时我首先要强调的是他们各有各的功能定位,要根据你的适用场合来确定到底适用哪个控件最合适。
Repeater,DataList,DataGrid这三个显示数据的空间并不属于ADO的范畴,因为三个空间的DataSource不仅可以使用DataSet,还可以使用DataView,或者甚至是一个数组之类的。
关于ADO.NET实在是太大了,等我写到这里的时候,才发现定下的题目似乎很大了,就算是浅谈,也可能还要写很多。相信很多人都对ADO.NET有认识,认识不同罢,我所本文叙述的内容,在MSDN上都可找到,我把他们整理在一起了,不过不是非常全面。这篇文章的一个目的是希望有些初学者不要走入ADO的误区,不要怕困难,直面DataSet,深入了解它,只有掌握了DataSet的用法,ADO也就差不多拿下了。
错误在所难免,欢迎批评指正!