在 Microsoft ASP.NET 2.0 Framework 中,數(shù)據(jù)庫(kù)訪問(wèn)得到了極大的簡(jiǎn)化。利用全新的 SqlDataSource 控件,您無(wú)需編寫(xiě)一行代碼就可以選擇、更新、插入和刪除數(shù)據(jù)庫(kù)數(shù)據(jù)。
生成簡(jiǎn)單的應(yīng)用程序時(shí),SqlDataSource 控件是一個(gè)很好的選擇。如果您需要迅速生成一個(gè)使用戶(hù)可以顯示和編輯數(shù)據(jù)庫(kù)記錄的 Web 頁(yè),使用 SqlDataSource 控件在幾分鐘之內(nèi)就能完成此工作。
例如,我自己就曾計(jì)時(shí)生成了這么一個(gè)頁(yè)面。通過(guò)結(jié)合使用 SqlDataSource 控件與 GridView 控件,我在 1 分 15秒 內(nèi)就能生成一個(gè)用于顯示 Northwind Products 數(shù)據(jù)庫(kù)表的內(nèi)容的頁(yè)面。就有這么快!
但是,SqlDataSource 控件存在一個(gè)問(wèn)題。如果您使用 SqlDataSource 控件,那您就是在做不太妙的事情。SqlDataSource 控件的缺點(diǎn)在于它迫使您將用戶(hù)界面層與業(yè)務(wù)邏輯層混合在一起。任何應(yīng)用程序架構(gòu)師都會(huì)告訴您:混合多個(gè)層的行為是不可取的。
生成嚴(yán)格意義上的多層 Web 應(yīng)用程序時(shí),您應(yīng)該具有清晰的用戶(hù)界面層、業(yè)務(wù)邏輯層和數(shù)據(jù)訪問(wèn)層。僅僅由于 SqlDataSource 控件的強(qiáng)制而在用戶(hù)界面層引用 SQL 語(yǔ)句或存儲(chǔ)過(guò)程是完全錯(cuò)誤的。
那么為什么您要關(guān)心這些東西呢?不錯(cuò),在很多情況下,您不必在意。如果您正在創(chuàng)建一個(gè)簡(jiǎn)單的 Web 應(yīng)用程序,完全可以使用 SqlDataSource 控件。例如,如果您需要生成一個(gè)由單獨(dú)頁(yè)面組成的應(yīng)用程序來(lái)顯示數(shù)據(jù)庫(kù)的表的內(nèi)容,那么將應(yīng)用程序劃分為多個(gè)應(yīng)用程序?qū)泳秃懿幻髦恰?/p>
遺憾的是(如果您已經(jīng)為此“交過(guò)學(xué)費(fèi)”,則會(huì)感到幸運(yùn)),并非所有的 Web 應(yīng)用程序都很簡(jiǎn)單。應(yīng)用程序達(dá)到一定的復(fù)雜程度之后,如果將其劃分為多個(gè)應(yīng)用程序?qū)?,則生成和維護(hù)它們就更輕松。
將應(yīng)用程序劃分為多個(gè)應(yīng)用程序?qū)佑泻芏鄡?yōu)點(diǎn)。如果您有一個(gè)清晰的業(yè)務(wù)邏輯層,就能夠創(chuàng)建一個(gè)可以從多個(gè)頁(yè)面調(diào)用的方法庫(kù)。換句話(huà)說(shuō),創(chuàng)建一個(gè)清晰的業(yè)務(wù)邏輯層提升了代碼重用。此外,創(chuàng)建清晰而獨(dú)立的應(yīng)用程序?qū)邮沟脩?yīng)用程序更易于修改。例如,清晰的層次使您無(wú)需修改數(shù)據(jù)訪問(wèn)代碼就可以修改用戶(hù)界面。
如果您需要使用 ASP.NET Framework 生成多層 Web 應(yīng)用程序,那么您可以使用 ASP.NET 2.0 Framework 所引入的另一個(gè)新控件:ObjectDataSource 控件ObjectDataSource 控件使您可將諸如 GridView 和 DropDownList 這樣的用戶(hù)界面控件綁定到一個(gè)中間層組件。
這篇文章的主題就是 ObjectDataSource 控件。在這篇文章中,您將學(xué)習(xí)如何使用此控件來(lái)顯示和編輯數(shù)據(jù)庫(kù)數(shù)據(jù)。我們還將討論如何結(jié)合使用 ObjectDataSource 控件和 SqlDataSource 控件以簡(jiǎn)化數(shù)據(jù)庫(kù)訪問(wèn)。
ObjectDataSource 控件包含 4 個(gè)重要屬性:SelectMethod 屬性、UpdateMethod 屬性、InsertMethod 屬性和 DeleteMethod 屬性。綜合利用這些屬性,您能夠指定執(zhí)行標(biāo)準(zhǔn)數(shù)據(jù)庫(kù)操作所需的所有方法。
例子:
綁定到數(shù)據(jù)訪問(wèn)層
數(shù)據(jù)訪問(wèn)層組件封裝 ADO.NET 代碼以通過(guò) SQL 命令查詢(xún)和修改數(shù)據(jù)庫(kù)。它通常提煉創(chuàng)建 ADO.NET 連接和命令的詳細(xì)信息,并通過(guò)可使用適當(dāng)?shù)膮?shù)調(diào)用的方法公開(kāi)這些詳細(xì)信息。典型的數(shù)據(jù)訪問(wèn)層組件可按如下方式公開(kāi):
public class MyDataBllLayer {
public DataView GetRecords();
public int UpdateRecord(int recordID, String recordData);
public int DeleteRecord(int recordID);
public int InsertRecord(int recordID, String recordData);
}
通常是在業(yè)務(wù)邏輯訪問(wèn)層定義對(duì)數(shù)據(jù)庫(kù)里記錄的操作,上面就定義了GetRecords、UpdateRecord、DeleteRecord和InsertRecord四個(gè)方法來(lái)讀取、更新、刪除和插入數(shù)據(jù)庫(kù)里的數(shù)據(jù),這些方法基本上是根據(jù)SQL里的Select、Update、Delete和Insert語(yǔ)句而定義。
和上面方法相對(duì)應(yīng), ObjectDataSource提供了四個(gè)屬性來(lái)設(shè)置該控件引用的數(shù)據(jù)處理,可以按照如下方式關(guān)聯(lián)到該類(lèi)型,代碼如下
<asp:ObjectDataSource TypeName="MyDataLayer" runat="server"
SelectMethod="GetRecords"
UpdateMethod="UpdateRecord"
DeleteMethod="DeleteRecord"
InsertMethod="InsertRecord"
/>
這里的SelectMethon設(shè)置為MyDataBllLayer里的GetRecords()方法,在使用時(shí)需要注意ObjectDataSource旨在以聲明的方式簡(jiǎn)化數(shù)據(jù)的開(kāi)發(fā),所以這里設(shè)置SelectMethod的值為GetRecords而不是GetRecords()。
同樣依次類(lèi)推,UpdateMethod/DeleteMethod/InsertMethod分別對(duì)應(yīng)的是UpdateRecord
/DeleteRecord/InsertRecord方法。
在上面GetRecords()的定義時(shí),可以看到該方法返回的類(lèi)型是DataView,由于ObjectDataSource將來(lái)需要作為綁定控件的數(shù)據(jù)來(lái)源,所以它的返回類(lèi)型必須如下的返回類(lèi)型之一:
Ienumerable、DataTable、DataView、DataSet或者Object。
除此以外,ObjectDataSource還有一個(gè)重要的屬性TypeName,ObjectDataSource控件使用反射技術(shù)來(lái)從來(lái)從業(yè)務(wù)邏輯程序?qū)拥念?lèi)對(duì)象調(diào)用相應(yīng)的方法,所以TypeName的屬性值就是用來(lái)標(biāo)識(shí)該控件工作時(shí)使用的類(lèi)名稱(chēng),下面的例子演示了ObjectDataSource的基本使用。
在該例子里定義了一個(gè)數(shù)據(jù)業(yè)務(wù)邏輯層來(lái)處理數(shù)據(jù)庫(kù)鏈接和業(yè)務(wù)邏輯,這些處理都是有App_Code文件夾下的NorthwndDB.cs文件完成,先大致瀏覽一下該文件里定義的方法:
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
public class EmployeeInfo
{
private string _connectionString;
public EmployeeInfo()
{ _connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
}
public SqlDataReader GetEmployees()
{
SqlConnection con = new SqlConnection(_connectionString);
string selectString = "SELECT EmployeeID,LastName,Firstname,Title,Address,City,Region,PostalCode FROM Employees ORDER BY EmployeeID";
SqlCommand cmd = new SqlCommand(selectString, con);
con.Open();
SqlDataReader dtr =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
return dtr;
}
public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode)
{
SqlConnection con = new SqlConnection(_connectionString);
string updateString = "UPDATE Employees SET Address=@Address,City=@City WHERE EmployeeID=@EmployeeID";
SqlCommand cmd = new SqlCommand(updateString, con);
cmd.Parameters.AddWithValue("@Address", Address);
cmd.Parameters.AddWithValue("@City", City);
cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
public void DeleteEmployee(int EmployeeId)
{
SqlConnection con = new SqlConnection(_connectionString);
string deleteString = "DELETE Employees WHERE EmployeeID=@EmployeeID";
SqlCommand cmd = new SqlCommand(deleteString, con);
cmd.Parameters.AddWithValue("@EmployeeId", EmployeeId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
在這段代碼里,定義了GetEmployees方法來(lái)獲取所有員工級(jí)別信息,UpdateEmployee方法更新員工的基本資料,DeleteEmployee方法用來(lái)刪除員工資料,這樣就可以在ObjectDataSource1.aspx里使用如下代碼調(diào)用業(yè)務(wù)邏輯的處理,如下
<asp:GridView
ID="GridView1"
DataSourceID="ObjectDataSource1"
DataKeyNames="EmployeeId"
AutoGenerateColumns="true"
AutoGenerateEditButton="True"
AutoGenerateDeleteButton="True"
Runat="Server" CellPadding="4" Font-Names="Verdana" Font-Size="X-Small" ForeColor="#333333" GridLines="None">
… …
</asp:GridView>
<asp:ObjectDataSource
ID="ObjectDataSource1"
TypeName="EmployeeInfo"
SelectMethod="GetEmployees"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
Runat="Server">
<UpdateParameters>
<asp:Parameter Name="EmployeeId" Type="Int32" />
<asp:Parameter Name="Address" />
<asp:Parameter Name="City" />
</UpdateParameters>
</asp:ObjectDataSource>
上面使用了GrieView控件后面會(huì)有專(zhuān)門(mén)介紹,這里我們專(zhuān)注ObjectDataSource控件的使用,在該控件里設(shè)置 TypeName為"EmployeeInfo"表示將來(lái)調(diào)用的類(lèi)名稱(chēng)為EmployeeInfo,調(diào)用SelectMethond/UpdateMethod/DeleteMethod調(diào)用的的方法分別是EmployeeInfo類(lèi)里的GetEmployees/UpdateEmployee/DeleteEmployee方法。
具體運(yùn)行可以自己試驗(yàn)。從運(yùn)行結(jié)果里單擊“Edit”可以更新員工的資料,單擊“Delete”將刪除員工的資料。
在運(yùn)行上面的例子里,可能看到UpdateEmployee的定義如下:
public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode)
{ ... ...
cmd.Parameters.AddWithValue("@Address", Address);
cmd.Parameters.AddWithValue("@City", City);
cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId);
... ...
}
這段代碼表示更新員工資料時(shí),其實(shí)只更新了員工的地址(Address)和所在的程序(City),而對(duì)于姓名(FirstName,LastName)、職稱(chēng)(Title)等并沒(méi)有更新。
既然FistName、LastName、Title等并沒(méi)有更新,為什么不將UpdateEmployee寫(xiě)成如下方式呢?
public void UpdateEmployee(int EmployeeId string Address, string City,)
{ ... ...
cmd.Parameters.AddWithValue("@Address", Address);
cmd.Parameters.AddWithValue("@City", City);
cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId);
... ...
}
也就是只保留需要的三個(gè)參數(shù)而將其它變量不寫(xiě),如果這樣做將發(fā)生錯(cuò)誤如下:
提示錯(cuò)誤為:ObjectDataSource1找不到一個(gè)包含Address,City,LastName,F(xiàn)irstname,Title,Region,PostalCode和Employee參數(shù)的非泛型方法(具體原因我還沒(méi)有進(jìn)行驗(yàn)證,我的感覺(jué)是ObjectDataSource是根據(jù)Select語(yǔ)句自動(dòng)生成Delete/Insert/Update等的,所以在更新時(shí),同樣需要該參數(shù),你可以到如下MSDN查看SelectMethod的說(shuō)明:
http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.objectdatasource.selectmethod(VS.80).aspx
)。
而我看到的例子,大多都是如下寫(xiě)法:
public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode)
{
UpdateEmployee(EmployeeId,Address,City)
}
public void UpdateEmployee(int EmployeeId, string Address, string City )
{
SqlConnection con = new SqlConnection(_connectionString);
string updateString = "UPDATE Employees SET Address=@Address,City=@City WHERE EmployeeID=@EmployeeID";
SqlCommand cmd = new SqlCommand(updateString, con);
cmd.Parameters.AddWithValue("@Address", Address);
cmd.Parameters.AddWithValue("@City", City);
cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
通過(guò)重載UpdateEmployee方法,便于數(shù)據(jù)的擴(kuò)展和維護(hù)。
綁定到業(yè)務(wù)邏輯
為了更好的進(jìn)行業(yè)務(wù)處理,需要進(jìn)一步封裝業(yè)務(wù)邏輯,以便返回強(qiáng)類(lèi)型,舉例定義一個(gè)Product來(lái)封裝數(shù)據(jù)庫(kù),具體由Product.cs類(lèi)來(lái)實(shí)現(xiàn)并放在App_Code目錄.
using System;
public class Product
{
protected int _productID;
protected String _productName;
protected int _categoryID;
protected decimal _price;
protected int _inStore;
protected String _description;
public int ProductID
{
get { return _productID; }
set { _productID = value; }
}
public String ProductName
{
get { return _productName; }
set { _productName = value; }
}
public int CategoryID
{
get { return _categoryID; }
set { _categoryID = value; }
}
public decimal Price
{
get { return _price; }
set { _price = value; }
}
public int InStore
{
get { return _inStore; }
set { _inStore = value; }
}
public String Description
{
get { return _description; }
set { _description = value; }
}
public Product()
{ }
public Product(int productID, string productName, int categoryID, decimal price, int instore, string description)
{
this._productID = productID;
this._productName = productName;
this._categoryID = categoryID;
this._price = price;
this._inStore = instore;
this._description = description;
}
}
然后定義業(yè)務(wù)邏輯類(lèi)ProductDB.cs來(lái)進(jìn)行處理:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.Data.SqlClient;
/// <summary>
/// ProductDB 的摘要說(shuō)明
/// </summary>
public class ProductDB
{
public ProductDB()
{
//
// TODO: 在此處添加構(gòu)造函數(shù)邏輯
//
}
public List<Product> GetProduct()
{
List<Product> products = new List<Product>();
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString);
string commandText = "select * from Products";
SqlCommand command = new SqlCommand(commandText,conn);
conn.Open();
SqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
Product prod = new Product();
prod.ProductID = (int)dr["ProductID"];
prod.ProductName = (string)dr["ProductName"];
prod.CategoryID = (int)dr["CategoryID"];
prod.Price = (decimal)dr["price"];
prod.InStore = (Int16)dr["InStore"];
prod.Description = (String)dr["Description"];
products.Add(prod);
}
dr.Close();
conn.Close();
return products;
}
public void UpdateProduct(Product pro)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString);
SqlCommand updatecmd = new SqlCommand("UPDATE Products set ProductName=@ProductName,CategoryID=@CategoryID,Price=@Price,InStore=@InStore,Description=@Description where ProductID=@ProductID", conn);
updatecmd.Parameters.Add(new SqlParameter("@ProductName", pro.ProductName));
updatecmd.Parameters.Add(new SqlParameter("CategoryID", pro.CategoryID));
updatecmd.Parameters.Add(new SqlParameter("@Price", pro.Price));
updatecmd.Parameters.Add(new SqlParameter("@InStore", pro.InStore));
updatecmd.Parameters.Add(new SqlParameter("@Description", pro.Description));
updatecmd.Parameters.Add(new SqlParameter("@ProductID", pro.ProductID));
conn.Open();
updatecmd.ExecuteNonQuery();
conn.Close();
}
public void DeleteProduct(Product pro)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString);
SqlCommand delcmd = new SqlCommand("delete from Products where ProductID=@ProductID", conn);
delcmd.Parameters.Add(new SqlParameter("@ProductID", pro.ProductID));
conn.Open();
delcmd.ExecuteNonQuery();
conn.Close();
}
}
最后建立前臺(tái)頁(yè)面文件,添加objectdatasource控件顯示數(shù)據(jù)
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DataObjectTypeName="Product"
DeleteMethod="DeleteProduct" SelectMethod="GetProduct" TypeName="ProductDB" UpdateMethod="UpdateProduct">
</asp:ObjectDataSource>
<asp:GridView ID="GridView1" runat="server" AutoGenerateDeleteButton="True" AutoGenerateEditButton="True"
CellPadding="4" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" Font-Names="Verdana"
Font-Size="XX-Small" ForeColor="#333333" GridLines="None">
<FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#E3EAEB" />
<EditRowStyle BackColor="#7C6F57" />
<SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333" />
<PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Center" />
<HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
聯(lián)系客服