Asp.Net2.0 GridView的例子(2):利用DataSource控件访问数据(续)


通过ObjectDataSource控件访问数据


通过SqlDataSource控件在ASP.NET页面里包含有与数据访问有关的细节。你会在SqlDataSource的描述性语法里面找到隐藏着的连接串,可能找到SQL语句(SELECT,INSERT,UPDATE,和DELETE),以及一组对应每种SQL语句的参数。这种方法的弱势就是把数据存储器的细节紧紧的绑定在ASP.NET页面上了。如果你的数据库的基础模式(表结构)更改了,你就不得不去修改所有用到修改部分数据的ASP.NET页面。另外,放置数据访问逻辑到页面会增加页面的复杂性。可能应用程序的数据库模式对新加入项目组的程序员来说会是大而笨重。通过把数据访问逻辑绑到页面,开发人员必须对数据模型和模型跟程序的关系有详细的了解才能创建或者修改ASP.NET页。


对于大型Web应用程序的较好方法是把程序的架构分层。典型的做法是把Web应用程序分开三层:


 1. 表现层,ASP.NET页面。
 2. 数据访问层(DAL),由一组处理表现层对后端数据存储层请求的类组成。
 3. 数据存储层,如Microsoft SQL Server管理的数据库。


假定你已经建立好数据访问层(DAL),ASP.NET 2.0 ObjectDataSource控件可以用来封装从DAL获得的信息。准备用ObjectDataSource控件时,你必须提供一下两点信息:


 1. 包含访问数据的方法的DAL类完整正确的类型名。
 2. 访问,删除,更新和插入数据的方法名。


为了示范如何使用ObjectDataSource,我创建了一个简单的访问Northwind数据库的DAL。该DAL由带有ProductID,ProductName,QuantityPerUnit,UnitPrice和UnitsInStock等属性(propertis)的Product类,以及叫ProductDAL的类组成。ProductDAL类包含有由叫GetProducts()的静态方法(static method),该方法返回一个Product的列表。下面是这两个类:


Product 和 ProductDAL(Visual Basic)

Imports Microsoft.VisualBasic
Public Class Product
#Region
"Private Member Variables"
Private _productID As Integer
Private _productName As String
Private _quantityPerUnit As String
'Consider making _unitPrice & _unitInStock nullable fields,
'since they are NULL in the Northwind database.
Private _unitPrice As Decimal
Private _unitsInStock As Integer
#
End Region
#Region
"Constructors"
Public Sub New()
End Sub
Public Sub New(ByVal productID As Integer, _
ByVal productName As String, ByVal quantityPerUnit As String, _
ByVal unitPrice As Decimal, ByVal unitsInStock As Integer)
Me._productID
= productID
Me._productName
= productName
Me._quantityPerUnit
= quantityPerUnit
Me._unitPrice
= unitPrice
Me._unitsInStock
= unitsInStock
End Sub
#
End Region
#Region
"Public Properties"
Public Property ProductID() As Integer
Get
Return _productID
End Get
Set(ByVal value As Integer)
If value < 0 Then
Throw New ArgumentException("ProductID must be " & _
" greater than or equal to zero.")
Else
_productID
= value
End If
End Set
End Property
Public Property ProductName() As String
Get
Return _productName
End Get
Set(ByVal value As String)
_productName
= value
End Set
End Property
Public Property QuantityPerUnit() As String
Get
Return _quantityPerUnit
End Get
Set(ByVal value As String)
_quantityPerUnit
= value
End Set
End Property
Public Property UnitPrice() As Decimal
Get
Return _unitPrice
End Get
Set(ByVal value As Decimal)
If value < 0 Then
Throw New ArgumentException("UnitPrice must be " & _
"greater than or equal to zero.")
Else
_unitPrice
= value
End If
End Set
End Property
Public Property UnitsInStock() As Integer
Get
Return _unitsInStock
End Get
Set(ByVal value As Integer)
If value < 0 Then
Throw New ArgumentException("UnitsInStock must be " & _
"greater than or equal to zero.")
Else
_unitsInStock
= value
End If
End Set
End Property
#
End Region
End Class


Imports Microsoft.VisualBasic
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Collections.Generic
Public Class ProductDAL
Public Shared Function GetProducts() As List(Of Product)
' returns a list of Product instances based on the
' data in the Northwind Products table
Dim sql As String = "SELECT ProductID, ProductName, " & _
"QuantityPerUnit, UnitPrice, UnitsInStock FROM Products"
Dim myConnection As New & _
SqlConnection( ConfigurationManager.ConnectionStrings(
& _
"NWConnectionString").ConnectionString)
Dim myCommand As New SqlCommand(sql, myConnection)
myConnection.Open()
Dim reader As SqlDataReader = & _
myCommand.ExecuteReader(CommandBehavior.CloseConnection)
Dim results As New List(Of Product)()
While reader.Read()
Dim product As New Product()
product.ProductID
= Convert.ToInt32(reader("ProductID"))
product.ProductName
= reader("ProductName").ToString()
product.QuantityPerUnit
= & _
reader(
"QuantityPerUnit").ToString()
If reader("UnitPrice").Equals(DBNull.Value) Then
product.UnitPrice
= 0
Else
product.UnitPrice
= & _
Convert.ToDecimal(reader(
"UnitPrice"))
End If
If reader("UnitsInStock").Equals(DBNull.Value) Then
product.UnitsInStock
= 0
Else
product.UnitsInStock
= & _
Convert.ToInt32(reader(
"UnitsInStock"))
End If
results.Add(product)
End While
reader.Close()
myConnection.Close()
Return results
End Function
End Class
Product 和 ProductDAL(C#)




























using
System;
/// <summary>
/// Summary description for Product
/// </summary>
public class Product
{
#region Private Member Variables
private int productID;
private string productName;
private string quantityPerUnit;
// Consider making _unitPrice & _unitInStock nullable fields,
// since they are NULL in the Northwind database.
private decimal unitPrice;
private int unitsInStock;
#endregion
#region Constructors
public Product() { }
public Product(int productID, string productName,
string quantityPerUnit, decimal unitPrice, int unitsInStock)
{
this.productID = productID;
this.productName = productName;
this.quantityPerUnit = quantityPerUnit;
this.unitPrice = unitPrice;
this.unitsInStock = unitsInStock;
}
#endregion
#region Public Properties
public int ProductID
{
get
{
return productID;
}
set
{
if (productID < 0)
throw new ArgumentException(@"ProductID must be
greater than or equal to zero.");
else
productID
= value;
}
}
public string ProductName
{
get
{
return productName;
}
set
{
productName
= value;
}
}
public string QuantityPerUnit
{
get
{
return quantityPerUnit;
}
set
{
quantityPerUnit
= value;
}
}
public decimal UnitPrice
{
get
{
return unitPrice;
}
set
{
if (unitPrice < 0)
throw new ArgumentException(@"UnitPrice must be
greater than or equal to zero.");
else
unitPrice
= value;
}
}
public int UnitsInStock
{
get
{
return unitsInStock;
}
set
{
if (unitsInStock < 0)
throw new ArgumentException(@"UnitsInStock must
be greater than or equal to zero.");
else
unitsInStock
= value;
}
}
#endregion
}



using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
/// <summary>
/// Summary description for ProductDAL
/// </summary>
public class ProductDAL
{
public static List<Product> GetProducts()
{
// returns a list of Product instances based on the
// data in the Northwind Products table
string sql = @"SELECT ProductID, ProductName, QuantityPerUnit,
UnitPrice, UnitsInStock FROM Products";
using (SqlConnection myConnection = new
SqlConnection(ConfigurationManager.ConnectionStrings[
"NWConnectionString"].ConnectionString))
{
SqlCommand myCommand
= new SqlCommand(sql, myConnection);
myConnection.Open();
SqlDataReader reader
=
myCommand.ExecuteReader(CommandBehavior.CloseConnection);
List
<Product> results = new List<Product>();
while (reader.Read())
{
Product product
= new Product();
product.ProductID
=
Convert.ToInt32(reader[
"ProductID"]);
product.ProductName
= reader["ProductName"].ToString();
product.QuantityPerUnit
=
reader[
"QuantityPerUnit"].ToString();
if (reader["UnitPrice"].Equals(DBNull.Value))
product.UnitPrice
= 0;
else
product.UnitPrice
=
Convert.ToDecimal(reader[
"UnitPrice"]);
if (reader["UnitsInStock"].Equals(DBNull.Value))
product.UnitsInStock
= 0;
else
product.UnitsInStock
=
Convert.ToInt32(reader[
"UnitsInStock"]);
results.Add(product);
}
reader.Close();
myConnection.Close();
return results;
}
}
}

就如在代码中看到的,GetProducts()在SqlDataReader中检索来自Northwind数据的Products表的
相关字段,然后历遍得到的结果,为每个结果创建一个Product实例并加入到Products的列表里。由
GetProducts()方法返回该列表。这些类文件(Product 和 ProductDAL)应该放到web应用程序
的“/app_code”目录里。这样做保证类文件会被自动编译和能被应用程序的ASP.NET页面访问到。

在一个ASP.NET页面显示来自DAL类的数据,先在页面添加一个ObjectDataSource控件,点击控件
智能标签上面的配置数据源链接。将会打开一个跟配置SqlDataSource时相似的向导,
但跟SqlDataSource的向导先问你要连接串不同,ObjectDataSource的向导第一步会要你选择包含
有访问数据方法的类(见图5)。一旦你选择了,向导的第二步就需要你选择用来选取数据,删除数据,
更新数据和插入数据的方法。因为我们只有一个选取(select)数据的方法,就只选GetProducts()方法
并不用指定删除,更新或者插入的方法。图6为ObjectDataSource向导的第二步。

(图5)


(图6)
这就是涉及从ObjectDataSource选取数据的方法。到这里,可以添加一个GridView控件到页面并且设置
刚配置好的ObjectDataSource控件为GridView的数据源。下面的是ObjectDataSource和GridView的
陈述性语法。和SqlDataSource的情况一样,但是注意,显示由一个DAL对象返回的数据不需要把源代码
放到ASP.NET页面。

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
>
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<aspSurprisebjectDataSource ID="productsDataSource"
Runat
="server" SelectMethod="GetProducts"
TypeName
="ProductDAL">
</aspSurprisebjectDataSource>
<asp:GridView ID="GridView1" Runat="server"
DataSourceID
="productsDataSource">
</asp:GridView>&nbsp;

</div>
</form>
</body>
</html>

图7是通过浏览器查看绑定ObjectDataSource的GridView的屏幕截图。注意,GridView显示所有的记录
来自Products表每列对应Product类的公开属性(public property)。