我学东西常常有一种乱七八糟的感觉,经济学、营销学、英语、计算机样样俱全,但无一精通。朋友也常常劝我找一样拿手的。但总是不得要领。我想自己可能不太适合做专业的人士吧。事实上,学习之于我来说,更像是一种兴趣,没有什么目的,就是学,不问别的。就像有人喜欢游戏,有人喜欢chat一样。微软的.net出现已经很久了,我也学了一段时间,书看了不少,总是隔三差五的,也不知道自己到底学到了点什么,会点什么?想想还是做个总结吧,先从ado.net说起。
查sdk可知,ado.net引自于system.data.ado(我这里采的是NETbeta1版,好像在beta2中已经改成systm.data.oledb了,这些东西都不重要,到时候可以查帮助,关键是思路)其与asp3.0内的ado相对应,在ado.net中,通过managed provider所提供的应用程序编程接口(API),可以轻松地访问各种数据源的数据,包括oledb所支持的和odbc支持的数据库。
在sdk中查找可以得到大量的信息(见图一),什么你english不好?那可是个麻烦事,抽个空我说说你,英语是不得不说的,那是工具,有它不感到多点什么?没它你可要吃点苦头了。如果今年11月中国加入WTO,那就更得懂点了。事实上,那些东西我也看不太懂,教你个窍门。前两个月看到清华一个博士生出的一套书,.net框架,一共四册。但我只看到过两本,一本是系统类分册的,一本是数据库类分册的。可以说是微软sdk的原文翻译,你可以借来翻翻,一本书过后,东西学到了,英文也不成问题了(至少是在.net类的词汇中)。是不是感到看我的文章受益非浅,一般!
(图一)
在ado.net的帮助中,你可以看到一些class、Delegates之类的东西,比如ADOCommand、adoconnection、adodatasetcommand等等(注意,这些在beta2中都变了,我说过主要是思路,改变的东西也不过是改几个字母罢了,就像如果我要用sql server,我只要把ado改成sql就行了,一个道理)这些我都会慢慢说到。这里打断一下,我写的东西不一定比别的什么人写的详细到或者是权威到什么地方去,国内大部分人都是看sdk来完成的。但是如果你仔细看我写的每一句废话,可能会给你减少走弯路的时间。至少我认为是这样。
不是开头的开头
有些故事没有开头,我写东西也没开头,对于这部分,我提到两个重要的概念,managed provider 和 dataset。
我说过managed provider是应用程序接口的参考。通过managed provider所提供的应用程序编程接口(API),可以轻松地访问各种数据源的数据。
(图二)
如上图所示(来自于微软的sdk),可见数据存取的基本结构。过去我们在使用asp时,通过ado的数据存取是基于连接的编程模型。连接断开,数据就不能再存取。在ADO.net中,datsetcommand扮演了极其重要的角色。它可以取回一个dataset,并维护一个数据和dataset之间的"桥",以便于数据的访问和修改、保存。Datasetcommand自动将数据的各种操作变换到数据源相关的合适的sql语句。四个command对象:selectcommand、insertcommand、updatecommand、deletecommand分别代替了数据库的查询、插入、更新、删除操作。而这一些都是断开的。
在学习microsoft.net的同时,你可以将dataset想像成一个关系型的数据库,如access建造的数据库。所不同的是它是建立在内存中的。有人不同意这种说法,但我看不出有什么区别,我就是这么认为,你怎么认为你自己看着办。Play by your own rules and you'll be happy.(照你自己的原则去做吧,这样你会活得很快乐。这是我昨天在学英语时记下的句型,to play by one's own rules照某人自己的原则行事。赖世雄老师主编的,very good!有空你去买一本,包你物超所值,我的英语不好,但那是个熟练的过程,每天学一点,不知不觉中自然成了高手)你看,学什么东西都是一个道理,持之以恒,没有不成功的。我们继续说dataset,它支持多表、表间关系、数据约束等,这些和关系数据库一般无二。比如说我建立一个dataset:sample,和一个用access建立的sample.mdb进行比较。我用连接对象connection、命令对象command与sample.mdb进行连接后,在内存中建立一个dataset对象sample。在sample建立和sample.mdb中一样的数据表,比如说customer(顾客表)、urine(尿样检查表)等。
那么内存中的dataset对象sample几乎和sample.mdb是一样的。
Access建立的数据库sample.mdb
内存中的dataset对象sample
customer
Customer
urine
Urine
gorgeous
Gorgeous
Dataset里的表是用datatable来表示的。Dataset可以包含许多datatable,这些datatable对象构成了表集合tablescollection对象。这些可以在sdk的system.data中查找到:
(图三)
那里说的很详细,如果英文不是很好的话,可以照我前面提到的方法,一举两得。
不是正文的正文:数据库的连接
让我们回忆一下asp中数据库的连接,(你可能看到我在写东西的时候,不时的提到一些可能你没学过的课程,这不重要,如果你学过的话,会理解的快一点;如果你没学过,也不影响你的学习。)一般是通过三个步骤完成:
将水管连接到水龙头上,即ado.connection;
根据指定的要求,打开水龙头,即执行sql,产生recordset。
把你掌握的水用在该用的地方。即对数据库的查、增、删、改。
有些时候我会想加上关闭数据链接这个步骤,但还是去掉了。因为我发现无论是在我国的一些高校,还是一些生活区,对于不是自己的东西,常常不知道珍惜。有些公用的水龙头,用完以后,从来不关。所以我想关闭水龙头这个步骤我还是不说了。说了你也记不住,直到发现自己的程序和别人少写了一行,却慢的惊人时,就会比谁都记得更清楚了。我有一次去北大吃饭,看到一个同学,把吃剩的半盘饭直接倒到水沟里,很容易把下水道堵住,自己却不当一回事。直到我用手把那饭抠出来,他才满脸通红,为什么自己不能注意一些呢?还有就是前几日看到报道说中国东北的一个市长被人家从飞机上赶下来,那时候我真的为中国人这三个字惭愧。书归正传,在ado.net中,有几点是改到的:
第一, 数据库链路是可以断开的,所做的变动都是在dataset进行操作。
第二, 引入的dataset内部采用的是xml标准,也就是说它与平台、语言无关。
第三, 在引用ado.net时,采用的是域名空间(namespace)。而不是对象引用。
因此相应的关系也就变成了:
1、 引用域名空间
2、 创建一个数据库链路(也就是在水龙头上接上水管)
3、 请求一个记录集合(也就是找到剩水的物体)
4、 把所得的记录集合暂存在指定的dataset内。(你把水存放在水盆里,而水盆又放在某一间屋子内。这样你取水的时候,可以这么指定姜志辉房间内的用红盆装的那个water)
5、 关闭数据库链路(也就是关闭水龙头)
6、 在dataset上进行所需要的操作。
而相对于上面这几步我以分解的形式来讲述,不要看到分解就头痛,你很幸运了,有我这种高手给你指路,少说节省半年的时间。(我靠,你dare掷我,兄弟几人,出来单挑)
引用域名空间
我想这个技术可能是来自java,当然我也是听说,后来为了求证一下,翻了一部分java以及jsp的书,差不多。事实上,很多microsoft的东东都是学习别人的,结果更上一层,我就喜欢它这种方式。不像国内许多程序员总说微软的东西都是在模仿中做出来的,一副不以为然的样子,好像他水平挺高,你倒也仿出来个看看啊!四大发明是中国发明的,可惜却在西方发挥的淋什么尽致。很多中国发明的,却被人家印上made in america的字样。醒醒吧!国人!脚踏实地的做人,在生活中学习一些别人的东西,是件好事情。Ok,远了,域名空间我很难给它个定义,倒不是写不出来,总是不贴切。你就看看我刚刚给你举的姜志辉屋内红色水盆的那个例子,想像一下。或许你也可以这么想,如果你的哪位同学是在北大上学,当然如果你like清华也可以。你找他的时候是这样的,找到北大,然后是光华管理学院,再然后是217室,然后是杨起荣。这就是域名空间。而microsoft是这样记录的。北大.光华管理学院.217.杨起荣。那个.大概是从属的意思,如果你用过微软的编程工具很容易明白。那么引用的时候呢,就像这样<%@ import namespace=" 北大.光华管理学院.217.杨起荣" %>。当然你还可以引入刘德华、关芝林(林是不是写错了)之类的。那么在ado.net中,引用应该是这样:
<%@ import namespace="system.data"%>
<%@ import namespace="system.data.ado"%>
如果你用的是sql server,可以这样用:
<%@ import namespace="system.data"%>
<%@ import namespace="system.data.sql"%>
事实上,这些都在beta2版中有所改动,不过不要紧,万变不离其衷,如果以后没有什么特殊情况,我不再加以说明。大家可能注意到了,在使用sql server时,所引用的域名空间不一样。采用的是system.data.sql,其实用system.data.ado也一样可以存取sql server。只是用system.data.sql更有效率,为什么呢?因为微软把它做出来一定有他的理由。否则的话,现在只能有两个傻瓜,一个是我,一个是微软。所以,不用考虑为什么,只是在使用sql server时尽量用system.data.sql就是了,因为微软是不是傻瓜我不知道。但是我绝对不是fool。
创建一个数据库链路(也就是在水龙头上接上水管)
下面是一个c#程序,创建一个函数,是以access为例:
public void CreateAdoConnection() {
ADOConnection myConnection = new ADOConnection();
myConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=NWIND_RW.MDB";
myConnection.ConnectionTimeout = 30;
myConnection.Open();
myConnection.IsolationLevel = IsolationLevel.ReadCommitted;
}
这个例子展示了如何连接到ms sql server上的pubs数据库:
string strconnstring;
strconnstring="provider="sqloledb;data source=(local);" & "initial catalog=pubs;user id=sa";
adoconnection objconn;
objconn=new adoconnection;
objconn.connectionstring=strconnstring;
objconn.open();
看到了吗,很简单,没有什么大不了的(no big deal,像是某句广告词)
基本思路如下,设置一个你要联接数据库的相应字符串,可以在控制面板里查到,或者是直接在sdk里得到。第二步设置一个adoconnection对象,将字符串指定给它,利用open方法打开即可。这是一定套路的。理解了就行,用的时候在sdk里一复制,改改相应的字符就行。或者如王国荣先生的方法,干脆做个函数,引用就行了。
请求一个记录集合(也就是找到剩水的物体)
下面是个例子,
//创建sql字符串
string strsql="select * from 姜志辉";
//创建对象adodatasetcommand和dataset
adodatasetcommand objcommand;
dataset objdataset=new dataset;
objcommand=new adodatasetcommand(strsql,objconn);
//填充数据到dataset
//并将数据集合命名为"靓子详情"
objcommand.filldataset(objdataset,"靓子详情");
解释一下,在这里是利用adodatasetcommand通过strsql字符串中的sql命令及objconn前面所提到的联接,建立一个dataset内的记录集合(请想像成数据表)"靓子详情",而它是dataset对象objdataset内的形如数据表式的记录集合。
而microsoft直接在sdk内给了你一个函数可用:
public DataSet SelectAccessRows(DataSet myDataSet,string myConnection,string mySelectQuery,string myTableName) {
ADOConnection myAccessConn = new ADOConnection(myConnection);
ADODataSetCommand myAccessDataSetCmd = new ADODataSetCommand();
myAccessDataSetCmd.SelectCommand = new ADOCommand(mySelectQuery,myConnection);
// fill myDataSet with data from myTableName
myAccessDataSetCmd.FillDataSet(myDataSet,myTableName);
return myDataSet;
}
可惜没有做vb的,这没关系,我会在这系列文章之后附送你一些半成品的函数,利于你编程。你只要稍加修改就行了。
关闭数据库链路
这很简单,objconn.close(); //关闭数据链路
objconn=nothing; //消除对象
over!
在dataset上进行所需要的操作
这是编程的关键部分,我决定做个正文来讲,先举个小例子看看:
myfirstdatagrid.datasource=objdataset.tables("靓子详情").defaultview;
myfirstdatagrid.databind();
完毕!收功!
一个小例子:test1.aspx(我包装于samples文件夹内)
本例用到了一个数据为文件test.mdb,一个config.web文件,一个test1.aspx。
test1.aspx文件的源代码如下:
<%@ page language="c#" %>
<%@ import namespace="System.Data" %>
<%@ import namespace="System.Data.ADO" %>
<html>
<head>
<script runat=server>
public void Page_Load(Object sender, EventArgs e) {
ADOConnection cn=new ADOConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;");
cn.Open();
message.Text="game over";
}
</script>
</head>
<body>
<asp:label id="message" runat="server"/>
</body>
</html>
执行结果如下:
(图4)
这里有一些周折,我本身是学VB出身的,所以有时候做出的东西会朝着那个方向去思考。有些小问题并不注意,结果使得调试这么一个小程序时费了好大的劲,结果是忘记了大小写的区别。所以笔者在此提醒你也注意这一点。
还有一点要说抱歉的地方是这个例子中没有用到数据库,虽然也ADOConnection了一次。于是我做了一个test2.aspx。源代码如下:
<%@ import namespace="System.Data" %>
<%@ import namespace="System.Data.ADO" %>
<html>
<head>
<script language="c#" runat="server">
public void page_load(Object sender,EventArgs e){
string sqltext="select * from name";
ADOConnection myconn=new ADOConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;");
myconn.Open();
ADODataSetCommand myAccessDataSetCmd = new ADODataSetCommand();
myAccessDataSetCmd.SelectCommand = new ADOCommand(sqltext,myconn);
DataSet MyDataSet = new DataSet();
myAccessDataSetCmd.FillDataSet(MyDataSet,"jzh1");
jzh.DataSource=MyDataSet.Tables["jzh1"].DefaultView;
jzh.DataBind();
myconn.Close();
}
</script>
</head>
<body>
<asp:datagrid id="jzh" runat="server"/>
</body>
</html>
执行情况如下:
(图五)
具体的例子我都放在了samples文件夹中。你可以慢慢看来。(有一点说明的是,为了方便起见,你最好把test.mdb拷贝到system32文件夹内,这样的原因是每个人的computer不一样,我也不想花大量的篇幅说一些很简单就可以解决的东西)。请原谅我就是这么拽,这句话是刚刚从《少林足球》中学来的。
正文中的正文:ADO.net的数据库操作
对于任何数据库类的操作无非就是五点:建、查、增、删、改。而我们几乎都可以使用sql语法来完成。那么不过就是:select * from datatable、insert into 表名(字段1,…) values(值1,…)、updata datatable set 姓名='姜志辉' where [id]=217、deledte from datatable where [id]=217等类似操作。如果你不会sql语法的话,我建议你最好去书店买本book,详细look look。Because it is important。如例add.aspx:
<%@ import namespace="System.Data" %>
<%@ import namespace="System.Data.ADO" %>
<script language="c#" runat="server">
public void page_load(Object sender,EventArgs e){
String strconn;
String strcomm;
ADOConnection oconn;
ADOCommand ocomm;
strconn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;";
strcomm="INSERT INTO name(name,sex,age,message) Values ('刘洋','女','23','我女朋友')";
oconn=new ADOConnection(strconn);
ocomm=new ADOCommand(strcomm,oconn);
try{
oconn.Open();
ocomm.ExecuteNonQuery();
}
catch(Exception myException){
//出错处理
}
finally{
oconn.Close();
}
}
</script>
执行后,请查看add.aspx。它是通过ADOCommand完成的。其它的操作与此类似。
不是结尾的结尾
不好意思,正文的长度让你失望了。近几日看了一段很有哲理的话,抄在这里:"古时候的女性常常将身体的某处视为禁地,当代的某些女性则常常将身体的某处视为公园。"看看我周围的这些小女生,不错的,很有道理。
如果这算是结尾,我总结一下。
ADO.NET并非是ADO的新版本,它是NET framework平台中负责数据存取的对象。最明显的区别是ADO.NET主要用来处理非线性状态的数据,也就是说它可以在不连线的状态下进行操作,较好的降低了网络负担。
ADO.NET中常用到的几个对象。关于它们的用法我已经提过,这里我们再简单复习一下,更详细的资料希望你去查阅微软的sdk.
Connection对象主要是通过oledb provider、datasource、userid、password等属性建立数据源的连接。这是数据库操作必须的一部。
Command对象主要是用来执行一些增、删、改以及查询的指令。
Datareader对象形如一个只能向后查询的只读recordset。负责将command对象执行的查询结果进行处理。
Dataset对象是一个虚拟的内存数据库,它的优点是可以断开与数据库的连接,节省资源。
Dataview对象过滤掉dataset内的数据,以利于显示。
Datasetcommand对象是用来帮助dataset建立datatable的,可以使用selectcommand、insertcommand、updatecommand以及deletecommand对象来控制dataset。
实例如下:(grid1.aspx)
<%@ import namespace="System.Data"%>
<%@ import namespace="System.Data.ADO"%>
<html>
<head>
<script language="c#" runat="server">
void page_load(object sender,EventArgs e){
String strconn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;";
String strsql="select * from name";
ADOConnection conn=new ADOConnection(strconn);
ADODataSetCommand adocmd=new ADODataSetCommand(strsql,conn);
DataSet ds=new DataSet();
adocmd.FillDataSet(ds,"name");
jzh.DataSource=ds.Tables;
jzh.DataBind();
}
</script>
</head>
<body>
<center>
<asp:datagrid id="jzh" runat="server"
backcolor="#f4fff4"
bordercolor="black"
cellpadding=3
cellspacing="0"
font-name="verdana"
font-size="8pt"
headerstyle-backcolor="#aaaadd"
/>
</center>
</body>
</html>
(grid2.aspx)
<%@ import namespace="System.Data"%>
<%@ import namespace="System.Data.ADO"%>
<html>
<head>
<script language="c#" runat="server">
void page_load(object sender,EventArgs e){
String strconn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;";
String strsql1="select * from name";
String strsql2="select * from address";
DataSet ds=new DataSet();
ADOConnection conn=new ADOConnection(strconn);
ADODataSetCommand adocmd=new ADODataSetCommand(strsql1,conn);
adocmd.SelectCommand=new ADOCommand(strsql2,conn);
//再加一个数据查询使用ADODataSetCommand的SelectCommand功能添加
adocmd.FillDataSet(ds,"名册");
adocmd.FillDataSet(ds,"地址");
//DataTable的添加没有什么变化
jzh.DataSource=ds.Tables;
jzh.DataBind();
}
</script>
</head>
<body>
<center>
<asp:datagrid id="jzh" runat="server"
backcolor="#f4fff4"
bordercolor="black"
cellpadding=3
cellspacing="0"
font-name="verdana"
font-size="8pt"
headerstyle-backcolor="#aaaadd"
/>
</center>
</body>
</html>
(datatable.aspx)
<%@ import namespace="System.Data"%>
<%@ import namespace="System.Data.ADO"%>
<html>
<head>
<script language="c#" runat="server">
void page_load(object sender,EventArgs e){
String strconn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;";
DataSet ds=new DataSet();
//添加数据表帅哥
DataTable jzhtable=ds.Tables.Add("帅哥");
//添加数据标头jzhdatacolumn,并设定各参数
DataColumn jzhDataColumn=new DataColumn();
jzhDataColumn.DataType=System.Type.GetType("System.String");
jzhDataColumn.ColumnName="姓名";
jzhDataColumn.ReadOnly=true;
jzhDataColumn.Unique=true;
jzhtable.Columns.Add(jzhDataColumn);
//添加数据内容
DataRow jzhDataRow=jzhtable.NewRow();
jzhDataRow["姓名"]="姜志辉";
jzhtable.Rows.Add(jzhDataRow);
jzh.DataSource=ds.Tables["帅哥"].DefaultView;;
jzh.DataBind();
}
</script>
</head>
<body>
<center>
<asp:datagrid id="jzh" runat="server"
backcolor="#f4fff4"
bordercolor="black"
cellpadding=3
cellspacing="0"
font-name="verdana"
font-size="8pt"
headerstyle-backcolor="#aaaadd"
/>
</center>
</body>
</html>
(dataview.aspx)
<%@ import namespace="System.Data"%>
<%@ import namespace="System.Data.ADO"%>
<html>
<head>
<script language="c#" runat="server">
void page_load(object sender,EventArgs e){
String strconn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;";
String strsql="select * from name";
ADOConnection conn=new ADOConnection(strconn);
ADODataSetCommand adocmd=new ADODataSetCommand(strsql,conn);
DataSet ds=new DataSet();
adocmd.FillDataSet(ds,"name");
DataView dv=new DataView();
dv=ds.Tables["name"].DefaultView;
jzh.DataSource=dv;
jzh.DataBind();
}
</script>
</head>
<body>
<center>
<asp:datagrid id="jzh" runat="server"
backcolor="#f4fff4"
bordercolor="black"
cellpadding=3
cellspacing="0"
font-name="verdana"
font-size="8pt"
headerstyle-backcolor="#aaaadd"
/>
</center>
</body>
</html>
以上实例请查看本文附带的zip文件。
结尾
bye-bye!