系列文章導航:
溫故知新ASP.NET 2.0(C#)(1) - MasterPage(母版頁)
溫故知新ASP.NET 2.0(C#)(1) - MasterPage(母版頁)
溫故知新ASP.NET 2.0(C#)(2) - Themes(主題)
溫故知新ASP.NET 2.0(C#)(3) - SiteMap(站點地圖)
溫故知新ASP.NET 2.0(C#)(4) - 緩存&SqlCacheDependency
溫故知新ASP.NET 2.0(C#)(5) - Localization
溫故知新ASP.NET 2.0(C#)(8) - DataSourceControl
溫故知新ASP.NET 2.0(C#)(6) - Membership&RoleManager
溫故知新ASP.NET 2.0(C#)(7) - Profile
溫故知新ASP.NET 2.0(C#)(8) - DataSourceControl
介紹
在 ASP.NET 2.0 中有幾個新的數據源控件,例如,SqlDataSource、ObjectDataSource、XmlDataSource、AccessDataSource 和 SiteMapDataSource。它們全都可以用來從它們各自類型的數據源中檢索數據,并且可以綁定到各種數據綁定控件。數據源控件減少了為檢索和綁定數據甚至對數據進行排序、分頁或編輯而需要編寫的自定義代碼的數量。
其中 ObjectDataSource 控件可針對各種基礎數據存儲區(如 SQL 數據庫或 XML)啟用聲明性數據綁定模型。因為頁開發人員也常常將數據檢索(也可能包含業務邏輯)封裝在一個組件對象中,從而在呈現頁和數據提供程序之間引入另一個層。ObjectDataSource 控件允許開發人員使用此傳統的三層結構構造應用程序,同時仍然能夠利用 ASP.NET 中的聲明性數據綁定模型的易用性優點。
關鍵
1、在數據層創建 強類型的DataSet和TableAdapter,TableAdapter查詢可以使用現有的存儲過程。注:直接把表或存儲過程拖進來會自動創建TableAdapter;
2、中間層的類用[System.ComponentModel.DataObject]聲明為數據組件,CRUD方法分別對應 [DataObjectMethod(DataObjectMethodType.Insert)],[DataObjectMethod(DataObjectMethodType.Select)],[DataObjectMethod(DataObjectMethodType.Update)],[DataObjectMethod(DataObjectMethodType.Delete)] ;
3、web層使用ObjectDataSource展現數據,ObjectDataSource就相當于一個代理。ObjectDataSource只是查找具有匹配的參數名稱的方法,它不會使用參數的 Type 或 Size,而只是對參數的名稱進行匹配;
4、其它
·<asp:Parameter />有ConvertEmptyStringToNull屬性,默認是true。另外還有Direction屬性
·注意<asp:BoundField />的這幾個屬性NullDisplayText,HtmlEncode,ApplyFormatInEditMode,InsertVisible,DataFormatString,ReadOnly
·DataKeyNames有多個值的話用“,”分隔,用<asp:ControlParameter />綁定的話給其加一個“PropertyName”屬性,值類似如下“SelectedDataKey.Values[0]”
·關于綁定:簡單屬性<%# custID %>;集合<asp:ListBox id="List1" datasource='<%# myArray %>' runat="server">;表達式<%# ( customer.FirstName + " " + customer.LastName ) %>;方法<%# GetBalance(custID) %>
·<%# Eval("field1") %> 和 <%# Bind("field1") %>,Eval是單向綁定,Bind是雙向邦定
·<asp:ObjectDataSource />有一個OldValuesParameterFormatString屬性一般不用,不過如果要處理樂觀并發之類的就會用到。當該屬性的值為“original_{0}”的時候“original_參數名”則為初始值
·還有一些如編程方式給參數賦值,錯誤處理,得到返回值之類的請看源碼
示例
相關存儲過程和數據層略;
單例模式的實現
App_Code/Singleton.cs

Code
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;
/**//// <summary>
/// Singleton 的摘要說明
/// </summary>
public class Singleton<T> where T : new()
{
public static T Instance
{
get { return SingletonCreator.instance; }
}
class SingletonCreator
{
internal static readonly T instance = new T();
}
}
中間層代碼
App_Code/Test.cs

Code
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 TestDatabaseTableAdapters;
using System.ComponentModel;
/**//// <summary>
/// Test 的摘要說明
/// </summary>
[DataObject]
public class Test
{
[DataObjectMethod(DataObjectMethodType.Select, true)]
public TestDatabase.TestDataTable GetTest()
{
return Singleton<TestTableAdapter>.Instance.GetTest();
}
[DataObjectMethod(DataObjectMethodType.Select, false)]
public TestDatabase.TestDataTable GetTestById(int id)
{
return Singleton<TestTableAdapter>.Instance.GetTestById(id);
}
[DataObjectMethod(DataObjectMethodType.Insert, true)]
public int?[] InsertTest(int? parentId, string name, DateTime? publishTime, decimal? price, bool? isGood, out int? minId)
{
// 僅為說明如何做錯誤處理
if (String.IsNullOrEmpty(name))
throw new ArgumentException("參數不能是空", "name");
int? id = null;
int? count = null;
minId = null;
Singleton<TestTableAdapter>.Instance.InsertTest(parentId, name, publishTime, price, isGood, ref id, ref count, ref minId);
return new int?[] { id, count };
}
[DataObjectMethod(DataObjectMethodType.Delete, true)]
public int? DeleteTest(int id)
{
int? rowAffected;
rowAffected = Singleton<TestTableAdapter>.Instance.DeleteTest(id);
return rowAffected;
}
[DataObjectMethod(DataObjectMethodType.Update, true)]
public int? UpdateTest(int? id, int? parentId, string name, DateTime? publishTime, decimal? price, bool? isGood)
{
int? rowAffected;
rowAffected = Singleton<TestTableAdapter>.Instance.UpdateTest(id, parentId, name, publishTime, price, isGood);
return rowAffected;
}
}
DataSourceControl/Test.aspx

Code
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Test.aspx.cs"
Inherits="DataSourceControl_Test" Title="數據源控件測試" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<p>
<asp:Label ID="lblMsg" runat="server" ForeColor="red" />
</p>
<table cellpadding="6">
<tr>
<td valign="top">
<asp:DetailsView ID="DetailsView1" runat="server" AllowPaging="True" AutoGenerateRows="False"
DataKeyNames="Id" DataSourceID="ObjectDataSource1" Height="50px" Width="125px" OnItemInserted="DetailsView1_ItemInserted">
<Fields>
<asp:BoundField DataField="Id" HeaderText="Id" InsertVisible="False" ReadOnly="True"
SortExpression="Id" />
<asp:BoundField DataField="ParentId" HeaderText="ParentId" SortExpression="ParentId" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="PublishTime" HeaderText="PublishTime" SortExpression="PublishTime"
InsertVisible="False" />
<asp:BoundField DataField="Price" HeaderText="Price" SortExpression="Price" DataFormatString="{0:c}" HtmlEncode="False" />
<asp:CheckBoxField DataField="IsGood" HeaderText="IsGood" SortExpression="IsGood" />
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
</td>
<td valign="top">
<asp:DetailsView ID="DetailsView2" runat="server" Height="50px" Width="125px" AutoGenerateRows="False" DataKeyNames="Id" DataSourceID="ObjectDataSource2">
<Fields>
<asp:BoundField DataField="Id" HeaderText="Id" InsertVisible="False" ReadOnly="True"
SortExpression="Id" />
<asp:BoundField DataField="ParentId" HeaderText="ParentId" SortExpression="ParentId" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="PublishTime" HeaderText="PublishTime" SortExpression="PublishTime" />
<asp:BoundField DataField="Price" HeaderText="Price" SortExpression="Price" DataFormatString="{0:c}" HtmlEncode="false" />
<asp:CheckBoxField DataField="IsGood" HeaderText="IsGood" SortExpression="IsGood" />
</Fields>
</asp:DetailsView>
</td>
</tr>
</table>
<p>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="Id"
DataSourceID="ObjectDataSource1" AllowPaging="True" AllowSorting="True" OnRowUpdating="GridView1_RowUpdating">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowSelectButton="True" />
<asp:BoundField DataField="Id" HeaderText="Id" InsertVisible="False" ReadOnly="True"
SortExpression="Id" />
<asp:BoundField DataField="ParentId" HeaderText="ParentId" SortExpression="ParentId"
NullDisplayText="我的值是NULL" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="PublishTime" HeaderText="PublishTime" SortExpression="PublishTime"
ReadOnly="true" />
<asp:BoundField DataField="Price" HeaderText="Price" SortExpression="Price" DataFormatString="{0:c}" HtmlEncode="false" ApplyFormatInEditMode="True" />
<asp:CheckBoxField DataField="IsGood" HeaderText="IsGood" SortExpression="IsGood" />
</Columns>
</asp:GridView>
</p>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetTest"
TypeName="Test" InsertMethod="InsertTest" DeleteMethod="DeleteTest" UpdateMethod="UpdateTest"
OnInserting="ObjectDataSource1_Inserting" OnInserted="ObjectDataSource1_Inserted">
<InsertParameters>
<%--ConvertEmptyStringToNull屬性默認為true--%>
<asp:Parameter Name="parentId" Type="Int32" ConvertEmptyStringToNull="true" />
<asp:Parameter Name="name" Type="String" />
<asp:Parameter Name="publishTime" Type="DateTime" />
<asp:Parameter Name="price" Type="Decimal" />
<asp:Parameter Name="isGood" Type="Boolean" />
<asp:Parameter Direction="Output" Name="minId" Type="Int32" />
</InsertParameters>
<DeleteParameters>
<asp:Parameter Name="id" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="id" Type="Int32" />
<asp:Parameter Name="parentId" Type="Int32" />
<asp:Parameter Name="name" Type="String" />
<asp:Parameter Name="publishTime" Type="DateTime" />
<asp:Parameter Name="price" Type="Decimal" />
<asp:Parameter Name="isGood" Type="Boolean" />
</UpdateParameters>
</asp:ObjectDataSource>
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server" OldValuesParameterFormatString="original_{0}"
SelectMethod="GetTestById" TypeName="Test">
<SelectParameters>
<asp:ControlParameter ControlID="GridView1" Name="id" PropertyName="SelectedValue"
Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</asp:Content>
DataSourceControl/Test.aspx.cs

Code
using System;
using System.Data;
using System.Configuration;
using System.Collections;
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;
public partial class DataSourceControl_Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ObjectDataSource1_Inserting(object sender, ObjectDataSourceMethodEventArgs e)
{
// 編程方式給參數賦值
if (e.InputParameters["publishTime"] == null)
{
e.InputParameters["publishTime"] = DateTime.Now;
}
}
protected void ObjectDataSource1_Inserted(object sender, ObjectDataSourceStatusEventArgs e)
{
// 錯誤處理
if (e.Exception != null)
{
if (e.Exception.InnerException != null)
{
Exception inner = e.Exception.InnerException;
if (inner is ArgumentException)
{
string paramName = ((ArgumentException)inner).ParamName;
lblMsg.Text = string.Concat("參數 ", paramName, " 有問題");
}
}
}
else
{
int?[] ary = (int?[])e.ReturnValue;
lblMsg.Text = "新插入信息的ID是:" + ary[0].ToString();
lblMsg.Text += "<br />數據總數是:" + ary[1].ToString();
lblMsg.Text += "<br />最小ID是:" + e.OutputParameters["minId"].ToString();
}
}
protected void DetailsView1_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
{
if (e.Exception != null)
{
// 錯誤已處理
e.ExceptionHandled = true;
// DetailsView保持插入狀態
e.KeepInInsertMode = true;
}
}
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
// 價格格式轉換為decimal格式
if (e.NewValues["Price"] != null)
e.NewValues["Price"] = decimal.Parse(e.NewValues["Price"].ToString(), System.Globalization.NumberStyles.Currency);
}
}