您的位置:首页 > 移动开发 > Objective-C

使用 ASP.NET 2.0 ObjectDataSource 控件

2010-08-08 19:20 141 查看
Stephen Walther

Superexpert

适用于:

Microsoft ASP.NET 2.0

Microsoft Visual Studio 2005

摘要
:ADO.NET 和 SqlDataSource
使得人们可以很容易地访问 ASP.NET 2.0 中的两层数据。但是,它们在 n 层应用程序中就不是那么有效了,而 ObjectDataSource
却能在 n 层应用程序中为业务对象提供相同的易用性。学习如何使用 ASP.NET 2.0 Framework 并利用 ObjectDataSource
控件生成严格意义上的多层 Web 应用程序。

本页内容



简介



使用 ObjectDataSource 控件显示数据



结合使用参数与 ObjectDataSource 控件



使用 ObjectDataSource 控件编辑数据



结合使用 ObjectDataSource 控件和 SqlDataSource 控件



小结

简介

在 Microsoft ASP.NET 2.0 Framework 中,数据库访问得到了极大的简化。利用全新的 SqlDataSource
控件,您无需编写一行代码就可以选择、更新、插入和删除数据库数据。

生成简单的应用程序时,SqlDataSource
控件是一个很好的选择。如果您需要迅速生成一个使用户可以显示和编辑数据库记录的 Web 页,使用 SqlDataSource
控件在几分钟之内就能完成此工作。

例如,我自己就曾计时生成了这么一个页面。通过结合使用 SqlDataSource
控件与 GridView
控件,我在 1 分 15秒 内就能生成一个用于显示 Northwind Products 数据库表的内容的页面。就有这么快!

但是,SqlDataSource
控件存在一个问题。如果您使用 SqlDataSource
控件,那您就是在做不太妙的事情。SqlDataSource
控件的缺点在于它迫使您将用户界面层与业务逻辑层混合在一起。任何应用程序架构师都会告诉您:混合多个层的行为是不可取的。

生成严格意义上的多层 Web 应用程序时,您应该具有清晰的用户界面层、业务逻辑层和数据访问层。仅仅由于 SqlDataSource
控件的强制而在用户界面层引用 SQL 语句或存储过程是完全错误的。

那么为什么您要关心这些东西呢?不错,在很多情况下,您不必在意。如果您正在创建一个简单的 Web 应用程序,完全可以使用 SqlDataSource
控件。例如,如果您需要生成一个由单独页面组成的应用程序来显示数据库的表的内容,那么将应用程序划分为多个应用程序层就很不明智。

遗憾的是(如果您已经为此“交过学费”,则会感到幸运),并非所有的 Web 应用程序都很简单。应用程序达到一定的复杂程度之后,如果将其划分为多个应用程序层,则生成和维护它们就更轻松。


应用程序划分为多个应用程序层有很多优点。如果您有一个清晰的业务逻辑层,就能够创建一个可以从多个页面调用的方法库。换句话说,创建一个清晰的业务逻辑
层提升了代码重用。此外,创建清晰而独立的应用程序层使得应用程序更易于修改。例如,清晰的层次使您无需修改数据访问代码就可以修改用户界面。

如果您需要使用 ASP.NET Framework 生成多层 Web 应用程序,那么您可以使用 ASP.NET 2.0 Framework 所引入的另一个新控件:ObjectDataSource
控件ObjectDataSource
控件使您可将诸如 GridView
DropDownList
这样的用户界面控件绑定到一个中间层组件。

这篇文章的主题就是 ObjectDataSource
控件。在这篇文章中,您将学习如何使用此控件来显示和编辑数据库数据。我们还将讨论如何结合使用 ObjectDataSource
控件和 SqlDataSource
控件以简化数据库访问。



返回页首

使用 ObjectDataSource 控件显示数据

我们在这里设想您需要创建一个用于显示 Products 数据库表的内容的 Web 页面。再进一步设想您的某个现有业务组件包含了一种用于检索此数据的方法。

例如,清单 1 中的组件包含了一个名为 GetProducts
的方法,此方法返回一个 DataReader 来表示 Products 数据库表的内容。

清单 1: ProductInfo.cs (C#)

using System;

using System.Data;

using System.Data.SqlClient;

public class ProductInfo

{

const string conString =

"Server=localhost;Trusted_Connection=true;Database=Northwind";

public static SqlDataReader GetProducts()

{

SqlConnection con = new SqlConnection(conString);

string selectString = "SELECT * FROM Products";

SqlCommand cmd = new SqlCommand(selectString, con);

con.Open();

SqlDataReader dtr =

cmd.ExecuteReader(CommandBehavior.CloseConnection);

return dtr;

}

}

清单 1: ProductInfo.vb (Visual Basic .NET)

Imports System.Data

Imports System.Data.SqlClient

Public Class ProductInfo

Const conString As String = _

"Server=localhost;Trusted_Connection=true;Database=Northwind"

Public Function GetProducts() As SqlDataReader

Dim con As New SqlConnection(conString)

Dim selectString As String = "SELECT * FROM Products"

Dim cmd As New SqlCommand(selectString, con)

con.Open()

Dim dtr As SqlDataReader =  _

cmd.ExecuteReader(CommandBehavior.CloseConnection)

Return dtr

End Function

End Class

如果您将清单 1 中包含的这个类添加到应用程序的 Code 目录中,那么 ASP.NET Framework 将自动编译这个类。换句话说,只要向 Code 目录添加了这个类,就可以立即在 ASP.NET 页中使用它。

我们将使用 GridView
控件(在 ASP.NET 2.0
Framework 中替换了 DataGrid
控件)来显示由 GetProducts
方法返回的数据库记录。清单 2 中的 ASP.NET 页包含了一个绑定到 ObjectDataSource
控件的 GridView


清单 2: ShowProducts.aspx

<html>

<head>

<title>Show Products</title>

</head>

<body>

<form id="form1" runat="server">

<asp:GridView

ID="GridView1"

DataSourceID="ObjectDataSource1"

Runat="Server" />

<asp:ObjectDataSource

ID="ObjectDataSource1"

TypeName="ProductInfo"

SelectMethod="GetProducts"

Runat="Server" />

</form>

</body>

</html>

清单 2 中声明的 ObjectDataSource
控件包含两个重要的属性。TypeName
属性指示类名,而 SelectMethod
属性指示在选择数据时要在此类上调用的方法名。

在清单 2 中,ObjectDataSource
控件用于调用 ProductInfo
类上的 GetProducts
方法。由于 GridView
控件绑定到了 ObjectDataSource
控件上,因此通过 GridView
控件的 DataSourceID
属性,GridView
控件即可显示产品列表(请参见图 1)。



图 1. 使用 ObjectDataSource 控件显示产品

您可以结合使用 ObjectDataSource
控件与任何标准的 ASP.NET 数据绑定控件(例如,GridView
DropDownList
TreeView
Repeater
控件)。ObjectDataSource
控件使您能够将任何标准控件绑定到组件。

SelectMethod
可以引用静态方法(在 Visual Basic .NET 中共享)或实例方法。如果您使用的是实例方法,则 ObjectDataSource
控件在调用这个方法前,会自动创建此组件的一个实例。在完成方法调用后,将自动销毁此组件。



返回页首

结合使用参数与 ObjectDataSource 控件

您可以将参数与使用 ObjectDataSource
控件调用的方法一起使用。当您调用某方法时,如果需要将某些值(例如,控件属性或查询字符串的值)传递给此方法,则这种方式就非常有用。

在前一节中,我们使用 ObjectDataSource
控件创建了一个页面,用于显示来自 Products 数据库表的所有记录。在本节中,我们将修改此页面,以便允许用户从 DropDownList
控件(请参见图 2)选择产品类别。



图 2. 从 DropDownList 选择产品类别

清单 3 包含了修改后的 ProductInfo 组件。

清单 3: ProductInfo2.cs (C#)

using System;

using System.Data;

using System.Data.SqlClient;

public class ProductInfo2

{

const string conString =

"Server=localhost;Trusted_Connection=true;Database=Northwind";

public SqlDataReader GetProducts(string category)

{

SqlConnection con = new SqlConnection(conString);

string selectString = "SELECT Products.* " +

"FROM Products INNER JOIN Categories " +

"ON Products.CategoryID=Categories.CategoryId " +

"WHERE CategoryName=@CategoryName";

SqlCommand cmd = new SqlCommand(selectString, con);

cmd.Parameters.AddWithValue("@CategoryName", category);

con.Open();

SqlDataReader dtr =

cmd.ExecuteReader(CommandBehavior.CloseConnection);

return dtr;

}

}

清单 3: ProductInfo2.vb (Visual Basic .NET)

Imports System.Data

Imports System.Data.SqlClient

Public Class ProductInfo2

Const conString As String = _

"Server=localhost;Trusted_Connection=true;Database=Northwind"

Public Function GetProducts(ByVal category As String) _

As SqlDataReader

Dim con As New SqlConnection(conString)

Dim selectString As String = "SELECT Products.* " &

"FROM Products INNER JOIN Categories " & _

"ON Products.CategoryID=Categories.CategoryId " & _

"WHERE CategoryName=@CategoryName"

Dim cmd As New SqlCommand(selectString, con)

cmd.Parameters.AddWithValue("@CategoryName", category)

con.Open()

Dim dtr As SqlDataReader = _

cmd.ExecuteReader(CommandBehavior.CloseConnection)

Return dtr

End Function

End Class

清单 3 中经过修改的 ProductInfo 组件包含了一个经过修改的 GetProducts
方法,此方法包含了一个用于类别名的参数。这个参数用于限制从数据库返回的产品。

清单 4 包含了 DropDownList
GridView
ObjectDataSource
控件,使您可以选择要显示的不同类别的产品。

清单 4: ShowProducts2.aspx

<html>

<head>

<title>Show Products</title>

</head>

<body>

<form id="form1" runat="server">

<asp:DropDownList

id="DropCategories"

AutoPostBack="true"

Runat="Server">

<asp:ListItem Value="Beverages" />

<asp:ListItem Value="Seafood" />

</asp:DropDownList>

<br /><br />

<asp:GridView

ID="GridView1"

DataSourceID="ObjectDataSource1"

Runat="Server" />

<asp:ObjectDataSource

ID="ObjectDataSource1"

TypeName="ProductInfo2"

SelectMethod="GetProducts"

Runat="Server">

<SelectParameters>

<asp:ControlParameter

Name="category"

ControlID="DropCategories" />

</SelectParameters>

</asp:ObjectDataSource>

</form>

</body>

</html>

从清单 4 的 DropDownList
控件选择新类别时,GridView
控件将自动地只显示来自选定类别的产品。

请注意,清单 4 中的 ObjectDataSource
控件包含了一个 SelectParameters
元素。这个元素列出了调用由 ObjectDataSource
控件的 SelectMethod
属性指定的方法时使用的所有参数。在本例中,SelectedParameters
元素包含了一个名为 category 的单个参数。这个参数表示来自 DropCategories
DropDownList
控件的 SelectedValue
属性的值。



返回页首

使用 ObjectDataSource 控件编辑数据

ObjectDataSource
控件包含 4 个重要属性:SelectMethod
属性、UpdateMethod
属性、InsertMethod
属性和 DeleteMethod
属性。综合利用这些属性,您能够指定执行标准数据库操作所需的所有方法。

例如,您可以使用 ObjectDataSource
控件来编辑数据库数据。在清单 5 中,修改后的 ProductInfo
类包含了一个新的 UpdateProduct
DeleteProduct
方法。

清单 5: ProductInfo3.cs (C#)

using System;

using System.Data;

using System.Data.SqlClient;

public class ProductInfo3

{

const string conString =

"Server=localhost;Trusted_Connection=true;Database=Northwind";

public static SqlDataReader GetProducts()

{

SqlConnection con = new SqlConnection(conString);

string selectString = "SELECT ProductId,ProductName, " +

"UnitPrice FROM Products ORDER BY ProductId";

SqlCommand cmd = new SqlCommand(selectString, con);

con.Open();

SqlDataReader dtr =

cmd.ExecuteReader(CommandBehavior.CloseConnection);

return dtr;

}

public static void UpdateProduct(int original_productId,

string productName, decimal unitPrice)

{

SqlConnection con = new SqlConnection(conString);

string updateString = "UPDATE Products SET " +

"ProductName=@ProductName,UnitPrice=@UnitPrice " +

"WHERE ProductID=@ProductID";

SqlCommand cmd = new SqlCommand(updateString, con);

cmd.Parameters.AddWithValue("@ProductName", productName);

cmd.Parameters.AddWithValue("@UnitPrice", unitPrice);

cmd.Parameters.AddWithValue("@ProductId", original_productId);

con.Open();

cmd.ExecuteNonQuery();

con.Close();

}

public static void DeleteProduct(int original_productId)

{

SqlConnection con = new SqlConnection(conString);

string deleteString = "DELETE Products " +

"WHERE ProductID=@ProductID";

SqlCommand cmd = new SqlCommand(deleteString, con);

cmd.Parameters.AddWithValue("@ProductId", original_productId);

con.Open();

cmd.ExecuteNonQuery();

con.Close();

}

}

清单 5: ProductInfo3.vb (Visual Basic .NET)

Imports System.Data

Imports System.Data.SqlClient

Public Class ProductInfo3

Const conString As String = _

"Server=localhost;Trusted_Connection=true;Database=Northwind"

Public Shared Function GetProducts() As SqlDataReader

Dim con As New SqlConnection(conString)

Dim selectString As String = "SELECT ProductId, " & _

"ProductName,UnitPrice FROM Products ORDER BY ProductId"

Dim cmd As New SqlCommand(selectString, con)

con.Open()

Dim dtr As SqlDataReader = _

cmd.ExecuteReader(CommandBehavior.CloseConnection)

Return dtr

End Function

Public Shared Sub UpdateProduct(ByVal original_productId _

As Integer, ByVal productName As String, _

ByVal unitPrice As Decimal)

Dim con As New SqlConnection(conString)

Dim updateString As String = "UPDATE Products " & _

"SET ProductName=@ProductName,UnitPrice=@UnitPrice " & _

"WHERE ProductID=@ProductID"

Dim cmd As New SqlCommand(updateString, con)

cmd.Parameters.AddWithValue("@ProductName", productName)

cmd.Parameters.AddWithValue("@UnitPrice", unitPrice)

cmd.Parameters.AddWithValue("@ProductId", original_productId)

con.Open()

cmd.ExecuteNonQuery()

con.Close()

End Sub

Public Shared Sub DeleteProduct(ByVal original_productId _

As Integer)

Dim con As New SqlConnection(conString)

Dim deleteString As String = "DELETE Products " & _

"WHERE ProductID=@ProductID"

Dim cmd As New SqlCommand(deleteString, con)

cmd.Parameters.AddWithValue("@ProductId", original_productId)

con.Open()

cmd.ExecuteNonQuery()

con.Close()

End Sub

End Class

您可以将这个修改过的 ProductInfo
类与清单 6 中包含的ObjectDataSource
控件一起使用,以编辑 Products 数据库表的内容。

清单 6: ShowProducts3.aspx

<html>

<head>

<title>Show Products</title>

</head>

<body>

<form id="form1" runat="server">

<asp:GridView

ID="GridView1"

DataSourceID="ObjectDataSource1"

DataKeyNames="ProductId"

AutoGenerateColumns="false"

AutoGenerateEditButton="true"

AutoGenerateDeleteButton="true"

Runat="Server">

<Columns>

<asp:BoundField

DataField="ProductName"/>

<asp:BoundField

DataField="UnitPrice"

DataFormatString="{0:c}"/>

</Columns>

</asp:GridView>

<asp:ObjectDataSource

ID="ObjectDataSource1"

TypeName="ProductInfo3"

SelectMethod="GetProducts"

UpdateMethod="UpdateProduct"

DeleteMethod="DeleteProduct"

Runat="Server">

<UpdateParameters>

<asp:Parameter

Name="original_productId"

Type="Int32" />

<asp:Parameter

Name="productName" />

<asp:Parameter

Name="unitPrice"

Type="Decimal"/>

</UpdateParameters>

</asp:ObjectDataSource>

</form>

</body>

</html>

在清单 6 中,GridView
控件显示了ProductName 和 UnitPrice 这两个列的值。由于 GridView
控件的 AutoGenerateEditButton
AutoGenerateDeleteButton
属性均设置为值 True,GridView
将自动生成用于编辑和删除产品行的用户界面(请参见图 3)。



图 3. 使用 ObjectDataSource 控件编辑数据

当您单击 Update 链接更新产品时,ObjectDataSource
控件将调用 UpdateProduct
方法。请注意,ObjectDataSource
控件在其 UpdateParameters
元素中列出了传递给 UpdateProduct
方法的参数。

有一个参数需要额外进行讨论。我们需要将被更新的行的 ProductID 列的值传递给 UpdateProduct
方法由于没有在 GridView
中显示 ProductID 列,我们必须将 ProductID 列分配给 GridView
控件的 DataKeyNames
属性。这个列的名称变为 original_productId,而不是 productId,因为我们正在向 update 方法传递 ProductID 列的未编辑版本。

如果您单击 Delete 链接,ObjectDataSource
控件将调用 DeleteProduct
方法。由于 GridView
控件的 DataKeyNames
属性具有值 ProductId,因此会再次将一个名为 original_productId 的参数自动传递给 DeleteProduct
方法。



返回页首

结合使用 ObjectDataSource 控件和 SqlDataSource 控件

到目前为止,我们已经将 ObjectDataSource
控件与使用 SqlDataReader
对象的组件一起使用,以便检索数据库数据。这里还有另一种选择。即不在组件内使用 SqlDataReader
DataSet
等 ADO.NET 对象,而是在组件中使用 SqlDataSource
控件。

您可以在组件中使用 SqlDataSource
控件的这一事实似乎很奇怪。通常,您不在组件中使用控件,因为控件一般具有可视化表示形式,而且控件参与页面执行生命周期。而 DataSource
控件在这一点上有些特殊。

如果您希望简化组件中的数据库访问代码,您可以在此组件中使用 SqlDataSource
控件。清单 7 展示了这种方式。

清单 7: ProductInfo4.cs (C#)

using System;

using System.Collections;

using System.Web.UI;

using System.Web.UI.WebControls;

public class ProductInfo4

{

const string conString =

"Server=localhost;Trusted_Connection=true;Database=Northwind";

public static IEnumerable GetProducts()

{

string selectString = "SELECT * FROM Products";

SqlDataSource dsrc = new SqlDataSource(conString,

selectString);

dsrc.DataSourceMode = SqlDataSourceMode.DataSet;

return dsrc.Select(DataSourceSelectArguments.Empty);

}

}

清单 7: ProductInfo4.vb (Visual Basic .NET)

Imports System.Collections

Imports System.Web.UI

Imports System.Web.UI.WebControls

Public Class ProductInfo4

Const conString As String = _

"Server=localhost;Trusted_Connection=true;Database=Northwind"

Public Shared Function GetProducts() As IEnumerable

Dim selectString As String = "SELECT * FROM Products"

Dim dsrc As New SqlDataSource(conString, selectString)

dsrc.DataSourceMode = SqlDataSourceMode.DataSet

Return dsrc.Select(DataSourceSelectArguments.Empty)

End Function

End Class

在清单 7 中,我们实例化了 SqlDataSource
控件的一个新实例。SqlDataSource
的构造函数接受了一个用于数据库连接字符串的参数和一个用于与 select 命令一起使用的命令文本的参数。接着,将 DataSourceMode
属性的值设为 DataSet(这里的另一个选项是 DataReader)。最后,在 SqlDataSource
控件的实例上调用 Select
方法,并返回表示来自 Products 数据库表的所有记录的 DataView


您可以将清单 7 中的 ProductInfo
类与清单 8 中包含的 ObjectDataSource
控件一起使用:

清单 8: ShowProducts4.aspx

<html>

<head>

<title>Show Products</title>

</head>

<body>

<form id="form1" runat="server">

<asp:GridView

ID="GridView1"

DataSourceID="ObjectDataSource1"

Runat="Server" />

<asp:ObjectDataSource

ID="ObjectDataSource1"

TypeName="ProductInfo4"

SelectMethod="GetProducts"

Runat="Server" />

</form>

</body>

</html>

在清单 8 中,GridView
控件绑定到了 ObjectDataSource
控件上。而 ObjectDataSource
控件又调用了 ProductInfo4
类的 GetProducts
方法,以检索由 GridView
显示的数据。最后,GetProducts
方法使用 SqlDataSource
控件检索数据库数据。



返回页首

小结

ASP.NET 2.0 Framework 极大地简化了数据库访问,使您可以更轻松地生成简单和复杂的 ASP.NET 应用程序。如果您需要生成一个简单的数据库驱动 Web 应用程序,那么您可以使用新的 SqlDataSource
控件。如果您需要生成一个更为复杂的应用程序或示例,您可以在传统的 3 层应用程序中使用 ObjectDataSource
控件。

ObjectDataSource
控件使您能够继续在数据驱动页面中使用中间层组件。其主要优势在于使您无需编写任何代码即可绑定到一个组件,从而极大简化了您的用户界面。使用 ObjectDataSource
控件,我可以在 3 分钟 20 秒的时间内生成一个可以显示 Product 数据库表的组件和页面。尽管这种方式花的时间比使用 SqlDataSource
控件长,但我感觉这样做时页面的体系结构要好得多。

关于作者

Stephen Walther
著有 ASP.NET方面最畅销的书�� ASP.NET Unleashed
。他还是 ASP.NET Community Starter Kit(Microsoft 公司生产的一个示例 ASP.NET 应用程序)的架构师和首席开发人员。他还通过自己的公司 Superexpert (http://www.superexpert.com
) 为美国的多家公司(包括 NASA 和 Microsoft)提供 ASP.NET 培训。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐