随笔-5  评论-5  文章-0  trackbacks-0

[翻译]Scott Mitchell谈DataSource系列之二 访问数据库中的数据

Accessing and Updating Data in ASP.NET 2.0: Accessing Database Data
By Scott Mitchell
原文地址: http://aspnet.4guysfromrolla.com/articles/022206-1.aspx

ASP.NET 2.0数据源控件系列

ASP.NET 2.0中新近引入了一系列的用来访问和更新数据的WEB控件。这些控件的出现使得网页开发人员可以以声明式的编程方式访问并对数据进行操作,摈弃了原来那种编写数据访问代码的方式。本篇文章是我所写的关于ASP.NET 2.0中最新的数据源控件文章系列专题中的一个。

·数据源控件的基础知识 – 探究数据源控件的基本概念以及它的优点,并且与ASP.NET 1.x平台中的数据访问技术做了一个初步的比较.

·访问数据库中的数据 – 展示如何通过SqlDataSource以及AccessDataSource控件从一个关系形数据库中查询并获得数据.

·使用参数对数据库数据进行筛选 – 学习如何使用硬编码的参数值以及QueryString传递来的参数值,或者是其他WEB控件传递的值,session会话变量值等参数进行筛选,来获取一个数据库中的数据的子集.

·个使用XmlDataSource控件访问XML数据 – 了解如何访问位于远程以及本地的XML数据并且将这些数据显示于WEB控件中.

·创建自定义的参数控件 – 学习如何创建自定义的、声明式的参数控件,该控件基于数据源控件参数集合.

·了解数据源控件的事件机制 – 探究数据源控件的整个生命周期中,如何触发事件.

 

前言
ASP.NET 2.0最棒的特性之一就是它提供的新的数据源控件. 这些控件的出现使得网页开发人员可以以声明式的编程方式访问并对数据进行操作. 简单地说, 使用这些数据源控件你甚至可以不写一行代码就能操作数据.在 ASP.NET 1.x中,需要手工编写很多重复性的代码去访问数据.比如, 在ASP.NET 1.x的WebForm中中显示一个数据表的内容,你大概需要按照如下步骤来编写代码:

1.    连接数据库,

2.    执行命令,

3.    返回结果,然后

4.    操作这些数据/绑定到数据控件(比如DataGrid).

这四步大概需要五到十行的代码量, 有些库—比如 Data Access Application Block –可以减少您需要编写的代码量,然而事实却依然存在:在ASP.NET 1.x 的web应用程序中访问和操作数据您还是得手工编写代码。

在ASP.NET 2.0中,您完全可以通过声明标记访问数据. 在这篇文章中我们将研究使用SqlDataSource 和AccessDataSource 控件访问数据库中的数据. 在这两个控件中你可以设置SELECT 语句并且使用任何参数的WHERE子句来作为他们的属性. 数据库的连接语句, 命令的执行, 以及数据的返回全部由控件自身实现.通过使用声明式的、"零代码"的数据控件你可以在15秒内创建一个显示数据表数据的页面 ,而这却不需要您手工编写一行代码.接着读,您能学到更多!

访问数据
ASP.NET 2.0 提供两大数据源控件来访问数据库数据:

  • SqlDataSource -关系数据库中访问数据的法宝. 控件名中的 "Sql" 并非专门指Microsoft SQL Server,而是指关系数据库中的SQL查询语法; 因此SqlDataSource 可以访问的数据库不仅包括Microsoft SQL Server, 而且包括Microsoft Access数据库, Oracle 数据库等等,基本上包括所有基于任何OLEDB或ODBC的数据存储.
  • AccessDataSource – AccessDataSource和很像. 两者主要的不同在于: AccessDataSource 控件允许你简单地通过它的DataFile属性指定要访问的数据文件(.MDB文件)的路径,而则要求有连接数据库的特定语句.

两者实质上都有一个重要的共同特征, 仅有的不同在于你如何指定数据库的连接信息.实际上, the AccessDataSource控件其实是个多余因为Microsoft Access数据库完全可以简单地使用SqlDataSource 控件来访问. (是的, 你需要提供一个连接字符串,而不是简单地指定该数据文件的路径; 但是Visual Studio 2005 可以针对App_Data文件夹中的数据文件自动创建合适的连接语句.)

在这篇文章中我们将会具体研究一下SqlDataSource, 略微谈一下它和AccessDataSource的不同点. 此外, SqlDataSource和AccessDataSource控件都可以访问和修改数据;但是,这里我们仅研究对数据的访问,在接下来的文章中我们再去研究如何修改数据. 并且在这里我们将主要通过使用Visual Studio 2005 中的设计视图来研究这些数据控件. 尽管在源码视图中你也可以手动设置这些属性,但在设计视图中可以通过向导方便快捷地指定数据库的连接以及要执行的命令.

好吧,开始吧.打开Visual Studio 2005,新建一个网站,或者也可以在本文的最后下载相关代码文件. 这里我使用Microsoft Access 的NorthWind数据库来实现连接、获取以及显示数据,它包含在下载文件中. (注:这个数据库文件是经过我稍微修改过的削减版Northwind,里面包含的窗体、模块、报表以及其中的宏都被我删去了,以减小文件体积.)

ASP.NET 2.0引入了 App_Data文件夹, 你可以选择把这个文件夹添加到你的网站爱存储数据文件, 比如XML文件, Access数据库文件 (.mdb),还有 SQL Server 2000、 SQL Server 2005 Express 版的数据库文件(.mdf). 下载的代码文件中你可以发现包含有Northwind.mdb文件 App_Data的文件夹.当然啦, ASP.NET 也允许你不把数据文件放在App_Data文件夹中. 当我们使用像Microsoft SQL Server这样的专业级数据库时,通常数据库要注册在独立的服务器中.

不管你的数据文件放在哪儿,当你想访问这个数据库内容时,在你的页面上添加一个 SqlDataSource控件(或者 AccessDataSource控件). 创建一个新的ASP.NET页面,打开设计视图.然后,在工具箱中拖一个 SqlDataSource控件到你的页面上.刚开始在设计视图中它显示为一个灰色的小框; 浏览器访问页面时它不会显示问任何HTML标记. 为了正常访问数据, 我们还得设置SqlDataSource控件的一系列属性,指明要连接的数据库和要执行的查询语句. 这些都可以在属性面板中设置, 使用向导会更快些:在SqlDataSource 控件的智能标记上选择"Configure Data Source" 链接.

使用向导配置SqlDataSource控件
点击"Configure Data Source"链接后开始配置向导, 首先选择一个数据库文件. 第一步,如下图所示, 向导会提示你选择一个要访问的数据库文件. 下拉列表框里默认的连接是存储在Web.config文件中的<connectionStrings> 字段中定义好的连接以及App_Data文件夹中的连接. 和其他服务器上的数据库建立连接时, 单击新建连接按钮,然后指定数据库服务器以及验证信息. (查询更多关于<connectionStrings> 字段的信息请参考我以前的一篇文章, Working with Databases in ASP.NET 2.0 and Visual Studio 2005[译者注:此篇未翻译].)

 

选择数据库后,点击下一步按钮. 假如你在Web.config文件中没有定义该数据库的<connectionStrings>字段, 向导会友善地提示你. 把连接信息存储在Web.config文件中有大量的优点,最显著的一点便是这样能使你的程序可维护性更好. 想象一下, 以后你可能会更改数据库服务器的地址, 这样你只需在Web.config文件中更改一处即可.如果没有定义这个数据段,你就得把程序中每个出现连接字段的地方都要更改. 此外,把连接字段存储在Web.config文件中你还可以 加密连接字段 ,更好地保护你的网站. (但是,如果你加密过了连接字段,向导便不会将它自动写入到<connectionStrings>字段.) 下面的截图显示了第二步的过程; 可以看出, 我已经选择把连接字段存储到Web.config 文件中并命名为NorthwindConnectionString.

与AccessDataSource相比...

AccessDataSource控件和SqlDataSource控件有一些小的差别 –与SqlDataSource中指定连接语句不同, AccessDataSource控件需要指定数据库的文件路径. 因此, AccessDataSource控件的示例和上图有些不同. 特别地,第一张图片显示了文件的路径; 由于没有连接语句, 第二张图片并不会在AccessDataSource中出现. 然而, 下面的图片中都是AccessDataSource和SqlDataSource中适用的.

下一张图片中向导会提示你要选择你的 SELECT语句. 图片上方你能看到两个单选框,你可以选择查询数据表/视图然后选择要返回的列 (如下图), 或者手写定制SQL语句或者选择存储过程. 如果你想从表或视图中指定列,简单地从下拉列表框中选择表或视图,然后检查要查询的列. 这里我从Products表中选择了ProductID, ProductName, UnitPrice, 和 UnitsInStock 四列. 这段查询将回返回Products表中的全部记录; 以后的文章中我们将会研究如何过滤返回的数据.



默认情况下返回的数据是按照数据库中数据存储的顺序排列的. 如果表中有聚合索引(比如主键约束), 那么数据将会按照该列排序; 否则,数据将会按照他们被存储时的输入顺序排列. 要指定不同的排列顺序, 点击 ORDER BY按钮. 这里你可以选择按照哪一列来排列, 并且可以指定升序或者降序. 如下图显示了带有ORDER BY子句的SELECT语句.



如果查询数据表/视图,然后选择要返回的列,你只能对一个表或视图中的数据进行配置. 在关系数据库中,通常各个表中的数据都有关联关系,这就需要使用 JOIN语句了. 或者需要我们从存储过程中获取数据. 在本文的例子中我们需要选择 "Specify a custom SQL statement of stored procedure" 但选框然后点击Next. 如下图所示. 这时你可以在SELECT 选项卡下手动编写SQL语句,或者在下拉列表框里选择一个存储过程.



如果你创建的SQL语句比较麻烦或者语法有些生僻, 你最好选择点击“查询生成器”按钮(Query Builder),这时系统将会运行一个图形化工具,允许你在表中选择某些列并自动使用JOIN语法.下图就显示了查询生成器的截图. 在这里, 我添加了两个表到查询窗口— Categories 表和 Products 表—然后检查一下需要返回的列. 同时我也指定了查询结果的顺序首先是按照CategoryName 排列, 然后按照ProductName. 只需几次鼠标点击,查询生成器便方便地完成了SELECT查询.



配置完成SELECT查询—比如选择表或视图、或者选择一个存储过程、或者手动编写SQL 语句—以后, 点击Next按钮,到最后一步. 这里你可以运行一下配置好的查询,预览一下返回的数据. 点击”完成”按钮,向导创建完毕.



在属性面板中配置SqlDataSource
在ASP.NET 2.0之前我一直坚决拥护"手写代码阵营." 我不喜欢向导,认为那样太过于抽象并且如果过于依赖地使用它,尽管开发人员能实现一些技术,可事实上却不能掌握这些知识点. 这样的问题一直困扰着使用向导的开发人员,尤其是出现问题的时候;因为过于依赖向导,他们就不知道遇到问题时到底是哪儿出错了.

一般而言我对于向导还是持同样的看法, 但在Visual Studio 2005中我却着实迷上了向导. 可能因为这样省了不少时间, 但根本原因在于向导做的都是属性的设置. 他们并没为你生成一大堆的代码,那样的话使用向导就比较危险了. 尽管如此,如果你不喜欢向导, 那也不错,因为配置SqlDataSource控件的属性也是犹如在公园里散步一样的简单.简单地配置一下下列属性, 你可以通过属性面板或者声明标记来实现:

  • ConnectionString – 把这条属性设置为你的数据库连接. 可以是完整的连接语句或者Web.config文件中<connectionStrings> 字段的值. 后者 的属性设置如下: ConnectionString="<%$ ConnectionStrings:ConnectionStringName %>".

对于AccessDataSource控件,设置它的 DataFile 属性为你的数据库文件路径,比如 ~/App_Data/Northwind.mdb.

  • ProviderName – 数据提供程序的名称. 默认情况下, SqlDataSource 控件为SqlClient, 专为Microsoft SQL Server设计的数据提供程序. 使用其他的数据库时,视具体情况来设置. .NET Framework中包含以下四种数据提供程:
    • System.Data.SqlClient – 快速访问Microsoft SQL Server (默认)
    • System.Data.OleDb – 访问OLE-DB类型的数据存储,比如Access
    • System.Data.Odbc – 访问较老的ODBC类型的数据存储.
    • System.Data.OracleClient – 快速访问Oracle数据库.

如果在Web.config 定义了连接语句,你可以使用如下的语法来设置此属性的值: ProviderName="<%$ ConnectionStrings:ConnectionStringName.ProviderName %>"

  • SelectCommand – 要执行的SELECT 查询, 比如SELECT [ProductID], [ProductName] FROM [Products] ORDER BY [ProductName].

使用SqlDataSource 控件获取数据
典型情况下, 访问数据库中的数据时会在某种样式下显示或者处理数据. 为了简单地显示数据, 使用任意一个Web数据控件 (比如 GridView) ,把它的 DataSourceID 属性设置为 SqlDataSource控件的属性. (这可以通过设计视图中该数据控件的智能标记中实现. 在它的下拉列表框中选择你要使用的SqlDataSource控件,绑定到该Web数据控件上.) 访问页面时,该Web数据控件会自动获取该 SqlDataSource控件的数据并显示出. 本文的代码中包含此操作的示例.下图展示了使用GridView显示了Products 表中ProductID, ProductName, UnitPrice, 和UnitsInStock 四列数据并以UnitPrice 和ProductName排列.



你也可以使用程序控制的方式设置SqlDataSource 控件. 具体实现之前,我们先看一下使用SqlDataSource数据源控件访问数据的机制. 如果熟悉ASP.NET 1.x ,你应该知道它的数据访问主要涉及以下两大技术:

  • DataReader— DataReader 提供“只进”( forward-only)的,只读的数据访问, 并且使用灵活的数据连接. 比DataSets/DataTables/DataViews效率更高.
  • DataSet/DataTable/DataView - DataTable 通过查询语句提供数据的访问;DataSet 是一系列DataTables的集合; DataViews可以得到DataTable中经过过滤和排序的数据子集. 你可以查看Contrasting the ADO.NET DataReader and DataSet 参看他们的差异以及共同点.

SqlDataSource可以返回 DataSet或者DataReader;通过设置它的DataSourceMode 属性, 默认为DataSet. 使用GridView内置的排序和分页功能, 或者SqlDataSource的缓冲功能(后面的篇文章中将要讨论!) 就要SqlDataSource返回 DataSet. (AccessDataSource控件也有DataSourceMode属性.)

使用程序控制的方法访问SqlDataSource的数据,可以调用 Select() 方法,该方法需要一个输入参数 DataSourceSelectArguments. This parameter can be used to pass along requests for the SqlDataSource to message the data before returning it. 比方说, 使用排序的GridView时, sorting a column calls the Select() method passing in a DataSourceSelectArguments instance with its SortExpression property set to the column name the end user sorted the data by. 假如你不希望SqlDataSource排序、过滤或者返回一整页的数据, 那就直接把 DataSourceSelectArguments属性设为空,如下代码段示例.

Select()方法返回一个实现IEnumerable接口的对象. 具体说来, DataSourceMode 属性设为DataSet时返回DataView;如果设为DataReader, 那就返回DataReader. 下面两段代码介绍了如何使用程序控制的方式使用SqlDataSource来访问数据. 第一段,是用VB写的,返回一个DataSet然后通过迭带循环显示结果集的一个子集数据. 第二段,是用C#写的,使用一个 SqlDataSource 返回一个值 (所有产品的平均单价)然后显示在一个Label上.

HTML 部分

1<asp:Label ID="RandomProductNames" runat="server"></asp:Label>
2
3<asp:SqlDataSource ID="rndProductsDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
4  ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>" SelectCommand="SELECT [ProductID], [ProductName] FROM [Products]">
5</asp:SqlDataSource>

Page_Load 事件

 
 1'用程序控制的方式使用SqlDataSource –返回一个DataView
 2Dim dv As DataView = _
 3   CType(rndProductsDataSource.Select(DataSourceSelectArguments.Empty), DataView)
 4
 5Dim rndCoinFlip As New Random
 6RandomProductNames.Text = String.Empty
 7
 8For Each dr As DataRow In dv.Table.Rows
 9   'See if we want to show this
10   If rndCoinFlip.Next(2= 0 Then
11      '显示
12      RandomProductNames.Text &= _
13               dr("ProductName").ToString() & "<br />"
14   Else
15      '不显示
16   End If
17Next 

 

 

HTML 部分

1The average price of all products in the Products database table is:
2<asp:Label ID="AvgPrice" runat="server" ForeColor="Red"></asp:Label>
3
4<asp:SqlDataSource ID="avgPriceDataSource" runat="server" 
5   ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
6   ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>"
7   SelectCommand="SELECT AVG(UnitPrice) FROM Products">
8</asp:SqlDataSource>


Page_Load 事件
 1// 使用SqlDataSource返回DataReader
 2OleDbDataReader reader = (OleDbDataReader)
 3      avgPriceDataSource.Select(DataSourceSelectArguments.Empty);
 4
 5// 读取该值
 6if (reader.Read())
 7   // 把单价值格式化为货币
 8   AvgPrice.Text = string.Format("{0:c}", reader[0]);
 9else
10   // 呵呵, 没有结果!
11   AvgPrice.Text = "抱歉,这没法知道.";
12
13// 关闭reader
14reader.Close(); 
15 
16

注:在这两个例子中我直接使用返回Select() 方法返回DataView 或者OleDbDataReader 对象, 这取决于SqlDataSource控件的DataSourceMode属性. (因DataReader是特定数据提供程序的对象, 假如我使用SqlClient那这里我就得使用SqlDataReader了;而如果我使用了OracleProvider, 那我这里就得使用OracleDataReader了,等等.)

小结
本文介绍了使用SqlDataSource和AccessDataSource控件访问和修改数据的基础知识. 现在只是简单的返回数据表中的数据,接下来的文章中我们将使用SqlDataSource 完成更丰富的应用. 使用SqlDataSource控件来访问数据可以通过"配置数据源"向导来显示数据库连接已经要查询的数据, 该向导可以在该控件的智能标记打开.数据源控件配置完成后,可以通过将其绑定到数据控件或者通过程序控制的方式显示数据,后者主要是使用SqlDataSource控件的Select()方法. 程序控制访问数据时具体的代码要视返回类型而定 (这又取决于DataSourceMode 属性的值).

祝编程愉快!

· By Scott Mitchell

附件

· 下载本文中的示例代码

posted on 2006-11-29 21:35 小白杨 阅读(2233) 评论(3) 编辑 收藏

评论:
#1楼 2007-11-05 14:41 | 陈宇[未注册用户]
您好!我的2005中到配置select这的时候specify columns from table or view这一项是黑的没法选是什么原因能告诉我吗?
 回复 引用   
#2楼 2007-11-05 17:47 | WoodEasy[未注册用户]
@陈宇
从表或视图中选择列,你选择的数据库和表都正常么?

 回复 引用   
#3楼 2007-11-29 12:05 | 执迷不悟      
收下这篇文章了,谢谢~
 回复 引用 查看