数据访问两种模式的比较
ASP.NET2.0扩展了ASP.NET1.1里数据访问的模式,简单概括起来具有两种模式
1、使用数据源控件(SqlDataSource/ObjectDataSource)
1)建立一个项目TwoMode
2)建立数据库连接
由于ASP.NET2.0提供了App_Data目录,所以你可以直接把数据库文件拷贝到该目录下,然后在“解决方案资源管理器”中,刷新该文件,就可以看到该文件了,如下图
然后切换到“数据库视图”里,就可以看到该数据库了,如图
不过在使用时,有时候,当你把一个新的数据库文件*.MDF拷贝到App_Code目录下展开时,会出现连接超时的现象,这是因为系统第一次访问该数据库时,除了需要验证必要的信息外,还需要生成数据库日志文件,所以,你只要再次展开数据库文件即可。
3)连接数据库
把数据源控件(为了便于说明,这里使用SqlDataSource控件)拖放到default.aspx上
单击“智能感应”右边的Configure Data Source,出现数据库连接配置向导
这里,系统会子定识别在App_Data目录下的数据库,如果你不把数据库放置在App_Data下,那你就自己建立连接吧
然后把数据库连接保存在web.config里
下一步,选择数据库
当然,你可以测试运行的结果
接下来,把一个GridView控件放到default上,设置数据源为SqlDataSource1,就可以了
你也可以利用“Auto Format”设置其样式
(2)数据集和数据适配器(传统的数据访问模式)
前面介绍了使用DataSource控件访问数据库的过程,本节介绍利用数据适配集/数据适配器的访问数据库。这两种设计模式的差别,使得GridView的设计即要支持DataSource控件的数据绑定模式,还需要支持数据集和数据适配器这种数据绑定模式,由于这对峰峦冤孽的存在,才让GirdView控件的设计时较为复杂。当然天天感觉,你只要知道这两种差别并具有一些概念就可以了,也不用深究,毕竟大家不是控件开发专家。
2.4数据集与数据适配器
VS.NET2005
支持传统的数据绑定方式,并为该方式提供了可视化操作,本级将介绍数据集和数据适配器。
2.4.1
强类型化数据集简介
对于大多数应用程序而言,不管将来应用于
Web Server
上还是
Windows Form
上,数据访问都是一个重要的环节。数据访问更倾向于处理对数据库的读写,您可以单独创建
Helper
类来处理这些共性,但是您仍然需要编写大量的代码。
事实上,我们可能有这样一种感觉:创建数据访问层很乏味,因为对于
DAL
的不同方法,执行
SQL
语句或存储过程的
ADO.NET
代码通常是相同或相似的。尽管可以使用本书前面的方法自定义
ADO.NET
代码编写自己的
DAL
,但是
Visual Studio
还是提供了一种方便的方式,可以根据简单向导的输入生成数据访问层。这种情况下的数据访问层是强类型
的
DataSet
对象。
DataSet
包含
TableAdapter
类型,这些类型公开用于返回强类型
DataTable
对象的方法。这些方法适合用于直接绑定到
ObjectDataSource
,也适合用于从业务逻辑层组件进行调用。
1
)类型化数据集
VS.NET2005
提供了数据集和数据适配器,使用它们可以大大减少代码的编写,利用
Visual Stduio.NET
设计器可以以声明的方式生成强类型化数据集。这里的数据集也是从
ADO.NET DataSet
,
DataTable
和
DataRow
派生的类,该类对外界提供了安全的
API
接口。通过
API
接口使得我们可以很容易访问
DataSet
里的数据与数据模式。
可以通过在
VS.NET2005
里通过简单的拖、放操作来生成这些强类型数据集,利用属性设计器还可以建立数据访问模式。其实您的这些操作就是生成一个类型化的
XML
模式文件定义(
XML Schema Definition
,
XSD
)。改
XSD
文件包含了数据库设计模式结构,系统能够根据该结构来将数据包含在
DataSet
中,换句话说,
VS.NET2005
将使用该
XSD
文件来生成一个包含数据集类定义的代码文件。
当你在应用程序里访问数据时,数据将根据数据表的不同被组织为一个个业务逻辑实体,例如
Category
实体,
Product
实体等(数据适配器表),为了能够使用这些数据,您需要将这些逻辑实体转换为类的对象,所以您可以自己为每一个实体编写一个类对象。这些实体对象一般会为数据访问提供一些属性和方法,您可以在类里使用这些属性和方法以返回强类型集合
强类型化的数据集为建立和委托自定义类对象提供了方便,从本质上说您建立的类对象是一个类型化的
DataSet
,该
DataSet
包含了业务逻辑实体和一些数据集合,但是主要区别是您在以声明的方式编写模式文件,您可以利用
VS.NET2005
的支持以可视化的方式编辑,删除
XML
数据模式文件,
VS.NET
能够感知模式文件的变化并更新代码文件类的成员。
另外,由于强类型化
DataSet
是从
ADO.NET
相关类派生,所以您可以重复利用
ADO.NET
提供的数据操作能够,例如数据绑定,数据分页、排序、过滤等常见的工作。
最后一点,也是最重要的一点当您在
VS.NET2005
建立数据集后,您可以为每一张表获取强类型的数据适配器表,使用该数据适配器您可以极大的减少常规代码大编写。该数据适配器进一步封装了数据的链接
Connection
,数据的执行
Command
,后面会详细介绍这些内容。
2
)
DataSets
和
Business Objects
的比较
一个常见的讨论是:是否在应用程序里使用
DataSets
。虽然
DataSets
确实为应用程序代码的编写提供了方便,但是由于它封装了许多实现细节,因为在理解性和可控性方面都具有一定的局限性。在这方面自定义
Business Objects
具有可度性强,理解简单的有点。但是正如前述,
DataSets
可以减类似代码的重复编写。事实上,对于
Web
而言,数据的读取原比数据的写入占有重要的比例,所以在这简单的数据读取方面,
DataSets
将比
Business Objects
更具有优势。
2.4.2
建立数据集与数据适配器
本书在第一章曾介绍如何利用
VS.NET2005
建立数据库,本节继续使用
Database
数据库来说明数据集和数据适配器的使用。在“
Server Explorer
”视图里,您可以看到
Database
数据库里已经有了
Categories
和
products
两张表,如图
2-42
。
图
2-42 Database
数据库
1)
使用
DataSet
设计器
接下来我们将建立
Database
的业务逻辑层,在“解决方案资源管理器”里单击鼠标右键选择“
Add New Item...
”,选择“
DataSet
”并将它命名
Database.xsd
如图
2-43
。
在
VS.NET
里建立的
DataSet
将采用默认的文件命名方式。例如此处建立的文件名为
Database.xsd
,则系统以后建立的
DataSet
派生类就命名为
Database
。相反,如果您此处建立的
DataSet
命名为
MyDAL
,则以后建立的
DataSet
派生类就命名为
MyDAL
类。
接下来会弹出一个对话框,询问你是否将该文件添加到
App_Code
目录下,我们选择“
Yes
”以便后面代码共享。
注意:
App_Code
文件夹除了类文件
*.cs
外,
*.XSD,Web Service
等也都可以共享
此后,系统将在
App_Code
目录下建立
Database.xsd
文件并启动“
TableAdapter Configuration Wizard
”向导如图
2-44
图
2-44 TableAdapter Configuration Wizard
”向导
2)
建立第一个数据适配器
在图
2-44
里,单击
Next
,系统会询问你是否使用
DatabaseConnectionString
作为连接字符串并保存在
web.config
里,选中“
Yes
”复选框如
引入下一步,选择
SQL
语句的命令类型,可以是
SQL
语句,也可以新建存储过程或者是已经存在的存储过程。在这里我们使用第一项“
Use SQL statements
”,如图
2-26
。
图
2-46
使用
SQL
语句
在下一步里,我们使用“
Query Builder
”来建立
SQL
语句,如图
2-47
,你可以单击“
Execute Query
”来查看该
SQL
语句执行的结果。
图
2-47 Query Builder
查询器
当返回后将自生成如下的
SQL
语句,参考图
2-48
。
SELECT ProductID, ProductName, CategoryID, Price, InStore, Description
FROM Products
图
2-48
生成
SQL
语句
在图
2-48
里还有一个“
Advanced Options...
”(高级选项),单击后将弹出高级选项对话框,如图
2-49
图
2-49
高级对话框
在高级选项里,默认是选中“
Generate Insert
,
Update And Delete statements
”的,所以系统会根据
Select
语句自动生成相应的插入、更新和删除语句,而“
Use optimistic concurrency
”(冲突检测)和
Refresh the data table
(刷新表格数据)是不选中的。
单击
Next
,将进入“
Choose Methods to Generate
”页面,在该页面系统会让我们命名在业务逻辑处理中的方法名称,这里有两类方法模式:
Fill
类:
DataSet
将使用
Fill
类生成一个以
DataSet
或者
DataTable
作为参数的方法,该方法将使用前面生成的
SQL
语句来填充数据集。
Get
类:该类方法用来获取前面
SQL
语句或者存储过程执行的返回结果值。
图
2-50
显示了我的设定,其中
Fill
类使用的是
Fill
方法,而
Get
类命名的方法是
GetAllProducts
。
另外我还选中了下面的
GenerateDBDirectMethods
,这样系统将自动根据我前面的
Insert
、
Update
和
Delete
语句生成相应的方法。
单击“
Next
”会显示系统自动生成的结果,如果成功了,可以单击
Finish
之间完成该向导。
当关闭向导后,系统会自动打开
VS.NET
的设计器,在该设计器里可以看到类视图如图
2-51
。
图
2-51
向导生成结果图
在图
2-51
上单击鼠标右键,选择“
View Code
“,我们可以查看系统自动生成的
XSD
源代码,下面我们看看系统都生成了哪些代码
1、
使用
Connection
标识数据库连接
在前面向导里数据库的连接配置是通过
Connections
的
Connection
表示的,这种配置会映射在
XSD
文档里,如代码
2-21
。正如您所看到的,数据库链接还包括了
Name
、
Provider
等属性,它们都用于以后数据库的连接。
<Connections>
<Connection
AppSettingsObjectName="Web.config"
AppSettingsPropertyName="DatabaseConnectionString"
ConnectionStringObject=""
IsAppSettingsProperty="True"
Modifier="Assembly"
Name="DatabaseConnectionString (Web.config)"
ParameterPrefix="@"
PropertyReference="AppConfig.System.Configuration.ConfigurationManager.0.ConnectionStrings.DatabaseConnectionString.ConnectionString"
Provider="System.Data.SqlClient">
</Connection>
</Connections>
代码
2-21 Database.xsd
代码片段(
1
)
2
、数据的执行用
XXXCommand
表示(这里是偶的解释,可以跳过)
在前面的
SQL
语句向导里,由于要求系统根据
Select
语句自动生成
Delete
、
Update
和
Insert
语句以及方法,所以系统将使用
<SelectCommand>
、
<DeleteCommand>
、
<UpdateCommand>
和
<InsertCommand>
来表示这些方法,并建立这些方法所需要的参数,如
2-22
。
<DbSource
ConnectionRef="DatabaseConnectionString (Web.config)"
DbObjectName="dbo.Products" DbObjectType="Table"
FillMethodModifier="Public"
FillMethodName="Fill" GenerateMethods="Both"
GenerateShortCommands="True" GeneratorGetMethodName="GetAllProducts"
GeneratorSourceName="Fill" GetMethodModifier="Public"
GetMethodName="GetAllProducts" QueryType="Rowset"
ScalarCallRetval="System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
UseOptimisticConcurrency="False"
UserGetMethodName="GetAllProducts" UserSourceName="Fill">
<DeleteCommand>
<DbCommand CommandType="Text" ModifiedByUser="False">
<CommandText>DELETE FROM [Products] WHERE (([ProductID] = @Original_ProductID))</CommandText>
<Parameters>
<Parameter AllowDbNull="False" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@Original_ProductID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="ProductID" SourceColumnNullMapping="False" SourceVersion="Original">
</Parameter>
</Parameters>
</DbCommand>
</DeleteCommand>
<InsertCommand>
<DbCommand CommandType="Text" ModifiedByUser="False">
<CommandText>INSERT INTO [Products] ([ProductName], [CategoryID], [Price], [InStore], [Description]) VALUES (@ProductName, @CategoryID, @Price, @InStore, @Description)</CommandText>
<Parameters>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@ProductName" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="ProductName" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@CategoryID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="CategoryID" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Currency" Direction="Input" ParameterName="@Price" Precision="0" ProviderType="Money" Scale="0" Size="0" SourceColumn="Price" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int16" Direction="Input" ParameterName="@InStore" Precision="0" ProviderType="SmallInt" Scale="0" Size="0" SourceColumn="InStore" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@Description" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="Description" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
</Parameters>
</DbCommand>
</InsertCommand>
<SelectCommand>
<DbCommand CommandType="Text" ModifiedByUser="True">
<CommandText>SELECT ProductID, ProductName, CategoryID, Price, InStore, Description
FROM Products</CommandText>
<Parameters>
</Parameters>
</DbCommand>
</SelectCommand>
<UpdateCommand>
<DbCommand CommandType="Text" ModifiedByUser="False">
<CommandText>UPDATE [Products] SET [ProductName] = @ProductName, [CategoryID] = @CategoryID, [Price] = @Price, [InStore] = @InStore, [Description] = @Description WHERE (([ProductID] = @Original_ProductID))</CommandText>
<Parameters>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@ProductName" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="ProductName" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@CategoryID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="CategoryID" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Currency" Direction="Input" ParameterName="@Price" Precision="0" ProviderType="Money" Scale="0" Size="0" SourceColumn="Price" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int16" Direction="Input" ParameterName="@InStore" Precision="0" ProviderType="SmallInt" Scale="0" Size="0" SourceColumn="InStore" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@Description" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="Description" SourceColumnNullMapping="False" SourceVersion="Current">
</Parameter>
<Parameter AllowDbNull="False" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@Original_ProductID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="ProductID" SourceColumnNullMapping="False" SourceVersion="Original">
</Parameter>
</Parameters>
</DbCommand>
</UpdateCommand>
</DbSource>
</MainSource>
代码
2-22 Database.xsd
部分代码(
2
)
3)
使用
Mapping
映射属性
对于数据库的列,系统使用
Mapping
元素将其映射为类的属性,并设置其类型,如代码
2
-
23.
<Mappings>
<Mapping SourceColumn="ProductID" DataSetColumn="ProductID" />
<Mapping SourceColumn="ProductName" DataSetColumn="ProductName" />
<Mapping SourceColumn="CategoryID" DataSetColumn="CategoryID" />
<Mapping SourceColumn="Price" DataSetColumn="Price" />
<Mapping SourceColumn="InStore" DataSetColumn="InStore" />
<Mapping SourceColumn="Description" DataSetColumn="Description" />
</Mappings>
<Sources>
代码
2-23
列和类属性的映射
通过上面的处理,这样我们就可以在代码里用如下的方法定义数据适配器、数据表和数据行,
DatabaseTableAdapters.ProductsTableAdapter pta =
new DatabaseTableAdapters.ProductsTableAdapter();
Database.ProductsDataTable table = new Database.ProductsDataTable();
Database.ProductsRow row = new Database.ProductsRow()
在使用时请注意默认的命名方式:
DatabaseTableAdapters
映射整个适配器的命名空间,在该命名空间里包含多个数据适配表。
Simpe_DataAdapter.aspx
演示了上面代码的使用。代码
2-24
是
Simple_DataAdapter.aspx
布局代码
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Simple_DataAdapter.aspx.cs" Inherits="Simple_DataAdapter" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" CellPadding="4" Font-Names="Verdana"
Font-Size="XX-Small" ForeColor="#333333" GridLines="None">
... ...
</asp:GridView>
</div>
</form>
</body>
</html>
代码
2-24 Simple_DataAdapter.aspx
布局代码
代码
2-25
是该页面的后台代码。
public partial class Simple_DataAdapter : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DatabaseTableAdapters.ProductsTableAdapter pta = new DatabaseTableAdapters.ProductsTableAdapter();
GridView1.DataSource = pta.GetAllProducts();
GridView1.DataBind();
}
}
代码
2-25 Simple_DataAdapter.aspx.cs
后台代码
代码里的
GetAllProducts
来源与图
2-52
里预定义的方法。图
2-52
显示了运行结果。从整个操作中,我们几乎不用写代码,也不用设计到
ADO.NET
的细节就能够完成数据库里数据的读取。
图
2-52 Simple_DataAdapter.aspx
运行结果
这里仅仅演示了数据集和数据适配器的基本使用,事实上,用数据集和数据适配器能够完成诸如 参数传递,存储过程,等工作,如果你在设计数据库时定义了表的关系,DataAdapter同样能够自动建立起映射关系。
查看。还是那句话,它用于DataAdapter显示数据挺好,而执行诸如update,delete等工作,确实是吃力不讨好的工作
如果你想知道DataAdapter的执行原理,也可以查看以前我发表的一篇文章
http://mqingqing123.cnblogs.com/archive/2005/10/11/252410.html
因为系统为你做的,就是自动化编译
以上内容仅供参考,不保证正确性。