ASP.NET 2.0 的数据源、数据绑定控件概述与区别
一、Render UI
1 GridView
GridView 控件用來在表中顯示數據源的值。每列表示一個字段,而每行表示一條記錄。GridView 控件支持下面的功能:
-
綁定至數據源控件,如 SqlDataSource。
-
內置排序功能。
-
內置更新和刪除功能。
-
內置分頁功能。
-
內置行選擇功能。
-
以編程方式訪問 GridView 對象模型以動態設置屬性、處理事件等。
-
多個鍵字段。
-
用于超鏈接列的多個數據字段。
-
可通過主題和樣式進行自定義的外觀。
實驗一:
將DetailsView和GridView放置在一個頁面。然后在DetailsView的SqlDataSource中的查詢參數設置為從GridView傳遞過來。
預期結果:當GridView中的選擇不同的行時,作為DataKeyNames屬性中的第一個字段au_id應該作為參數傳遞給DetailsView的SqlDataSource,DetailsView根據數據源Render。
現象:當GridView中的選擇不同的行時,DetailsView控件沒有展現數據。
分析:
首先懷疑是DetailsView的屬性沒有設置正確,于是將其數據源的查詢參數設置默認值,結果能展現。說明DetailsView和其SqlDataSource的屬性設置正確。
然后懷疑是GridView選擇行時,其SelectedValue為空。于是在其SelectedIndexChanging事件和SelectedIndexChanged中進行調試,發現第一次選擇時GridView的SelectedIndexChanging事件中SelectedValue確實為Null,而SelectedIndexChanged事件中SelectedValue值為預期值。而第二次以及以后的選擇時兩個事件中SelectedValue的值都為預期值。
那么GridView的SelectedValue為什么是Null呢?我查看一下GridView的屬性,EnableViewState設置為false,于是改成True,再試,還是不行。
經過長時間的嘗試,發現在如下兩種情況下程序結果是對的:
一 :先設置DetailsView使用的SqlDataSource中查詢參數的默認值,這樣DetailView會顯示出來,然后將其切換到Edit模式,發現其各字段的值確實是GridView選中行的值,然后再點擊Cancel放棄修改。則DetailView能夠正確響應GridView的選擇操作。再調試代碼,發現GridView的SelectedIndexChanging事件中SelectedValue值不再為空,而是預期值。
二:發現一個更奇特的現象,在SelectedIndexChanging中設置斷點,發現程序運行進來,然后什么都不做,跳出事件處理(如下)
????protected?void?GridView1_SelectedIndexChanging(object?sender,?GridViewSelectEventArgs?e)????...{
????}
程序結果也是對的,但是如果不設置斷點,直接運行,則結果不對。
又經過很長時間的嘗試,沒有辦法了,只好找同事幫忙。剛開始他也覺得離奇。先跟蹤事件發生的順序,接著發現了一個更離奇的現象:在SelectedIndexChanging事件中設置斷點時我添加了對GridView.SelectedValue的監視。雖然在事件響應代碼中我什么都沒有做,但是這個watch好像起了作用。因為他把我添加的這個監視去掉后,錯誤現象又重現了。而添加這個監視,或者在代碼里這樣寫
string?s?=?GridView1.SelectedValue.ToString();才能正常運行。
最后,同事讓我在工程里新建一個頁面,SampleCode拷到這個頁面,然后運行。以確定不是我的環境有錯誤。然后把SamlpeCode和我的代碼做了對比。把一些不一樣的屬性去掉。當改到GridView的SqlDataSource的EnableViewSate屬性時,“奇跡”出現了。SampleCode的該屬性設置為True,而我的是false,我改成True后,程序正常運行。
這時候再去測試SelectedValue的值,發現第一次選擇時,在SelectedIndexChanging事件中SelectedValue仍然為null,和錯誤時的現象沒有什么區別。
錯誤的源頭總算找到了,但是SqlDataSource的EnableViewState究竟做了什么呢?GridView的SelectedValue和SqlDataSource有關嗎?
實驗二:分頁排序
雖然 GridView、DetailsView 和 FormView 提供頁導航 UI 的默認呈現,但是也可以通過設置 PagerTemplate 屬性自定義頁導航的呈現。在該模板中,您可以放置 CommandName 屬性設置為 Page 并且 CommandArgument 屬性設置為 First、Prev、 Next、Last 或 <number>(其中 <number> 是特定頁索引的值)的 Button 控件。
應用分頁模板:
<PagerTemplate>????????????????????????????????<div?style="float:?right">
????????????????????????????????????<asp:RangeValidator?ID="rvTarget"?runat="server"?ControlToValidate="txtTarget"?Type="Integer"
????????????????????????????????????????ErrorMessage="頁碼超出范圍"?MinimumValue="1"?MaximumValue='<%#gvReportForDept.PageCount%>'></asp:RangeValidator>
????????????????????????????????????共<%=gvReportForDept.PageIndex?+?1%>/<%=gvReportForDept.PageCount%>頁 ?第<asp:TextBox
????????????????????????????????????????runat="server"?ID="txtTarget"?onkeypress="searchForDept(event);"?CssClass="gotopage"?MaxLength="10"?Width="25px"
????????????????????????????????????????Text='<%#gvReportForDept.PageIndex?+?1%>'></asp:TextBox>頁
????????????????????????????????????<asp:ImageButton?runat="server"?ID="ibtnGo"?CommandName="Page"?CommandArgument="-1"
????????????????????????????????????????ImageUrl="~/Images/dg_btn_go.gif"?/>
????????????????????????????????????<asp:ImageButton?runat="server"?ID="ibtnFirst"?CommandName="Page"?CommandArgument="First"
????????????????????????????????????????ImageUrl="~/Images/dg_btn_le.gif"?/>
????????????????????????????????????<asp:ImageButton?runat="server"?ID="ibtnPrev"?CommandName="Page"?CommandArgument="Prev"
????????????????????????????????????????ImageUrl="~/Images/dg_btn_l.gif"?/>
????????????????????????????????????<asp:ImageButton?runat="server"?ID="ibtnNext"?CommandName="Page"?CommandArgument="Next"
????????????????????????????????????????ImageUrl="~/Images/dg_btn_r.gif"?/>
????????????????????????????????????<asp:ImageButton?runat="server"?ID="ibtnLast"?CommandName="Page"?CommandArgument="Last"
????????????????????????????????????????ImageUrl="~/Images/dg_btn_re.gif"?/>
????????????????????????????????</div>
????????????????????????????</PagerTemplate>
這將啟用默認的分頁事件。如果需要在分頁中控制邏輯,例如:如果在TextBox中輸入頁碼,然后點擊Go按鈕,則不僅需要客戶端驗證輸入的范圍,還需要在翻頁時驗證頁碼的合理性,所以在PageIndexChanging事件中添加如下代碼:
???????protected?void?gvReportForOrder_PageIndexChanging(object?sender,?GridViewPageEventArgs?e)????????...{
????????????GridViewPagingHandler(sender,?e,?this.gvReportForOrder);
????????}
?????????/**////?<summary>
????????///?處理頁面內GrivView的翻頁事件
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????///?<param?name="gv">GrivView</param>
????????public?void?GridViewPagingHandler(object?sender,?GridViewPageEventArgs?e,?GridView?gv)
????????...{
????????????if?((e.NewPageIndex?>=?0)?&&?(e.NewPageIndex?<?gv.PageCount))
????????????...{
????????????????gv.PageIndex?=?e.NewPageIndex;
????????????????TextBox?target?=?(TextBox)gv.BottomPagerRow.FindControl("txtTarget");
????????????????target.Text?=?Convert.ToString(gv.PageIndex?+?1);
????????????}
????????????else?if?(e.NewPageIndex?==?-2)?//?Go?button
????????????...{
????????????????TextBox?target?=?(TextBox)gv.BottomPagerRow.FindControl("txtTarget");
????????????????int?goPage;
????????????????if?(Int32.TryParse(target.Text,?out?goPage))
????????????????...{
????????????????????if?(goPage?>=?1?&&?goPage?<=?gv.PageCount)
????????????????????...{
????????????????????????gv.PageIndex?=?goPage?-?1;
????????????????????}
????????????????????else
????????????????????...{
????????????????????????e.Cancel?=?true;
????????????????????????return;
????????????????????}
????????????????}
????????????}
????????????else
????????????...{
????????????????e.Cancel?=?true;
????????????????return;
????????????}
????????????try
????????????...{
?????????????????//Bind?DataSource?To?GridView
????????????}
????????????catch
????????????...{
????????????????e.Cancel?=?true;
????????????}
????????}
?2 DetailsView
DetailsView 控件用來在表中顯示來自數據源的單條記錄,其中記錄的每個字段顯示在表的一行中。它可與 GridView 控件結合使用,以用于主/詳細信息方案。DetailsView 控件支持下面的功能:
-
綁定至數據源控件,如 SqlDataSource。
-
內置插入功能。
-
內置更新和刪除功能。
-
內置分頁功能。
-
以編程方式訪問 DetailsView 對象模型以動態設置屬性、處理事件等。
-
可通過主題和樣式進行自定義的外觀。
?實驗一:應用DetailsView的模板列
DetailsView除了已經定義的列外,還有模板列,這和FormView的模板類似,但是又有所不同。
在DetailsView'中可以這樣應用模板列
??<asp:DetailsView?ID="DetailsView1"?runat="server"?DataSourceID="ObjectDataSource2"????????????Height="50px"?Width="125px"?AutoGenerateEditButton="True"?DataKeyNames="au_id"
????????????AutoGenerateRows="False">
????????????<Fields>??????????????????????????
????????????????<asp:TemplateField HeaderText="Author">?
????????????????????<ItemTemplate>?
???????????????????????????????.......????
????????????????????</ItemTemplate>
????????????????????<EditItemTemplate>
??????????????????????????????.........
?????????????????????</EditItemTemplate>
????????????????????<InsertItemTemplate>
????????????????????????????..........
????????????????????</InsertItemTemplate>
????????????????</asp:TemplateField>
????????????</Fields>
????????</asp:DetailsView>
而FormView中這樣應用模板
<asp:FormView?ID="fvDatumDetailX"?runat="server"?DataSourceID="odsDatumDetailX"?DataKeyNames="ID"????????????????????OnItemInserted="fvDatumDetailX_inserted"?OnItemCommand="fvDatumDetailX_itemCommand"?OnItemUpdated="fvDatumDeatailX_updated">????????????<ItemTemplate>
?????????????????........
????????????</ItemTemplate>
????????????<EditItemTemplate>
????????????????.........
????????????</EditItemTemplate>
????????????<InsertItemTemplate>
???????????????..........
????????????</InsertItemTemplate>????????
????????</asp:FormView>
看起來在ItemTemplate節點下的內容似乎是一樣的。但是運行起來發現不一樣:
可以看出:DetailsView只適合對一個字段運用模板,而FormView則適合對整條記錄運用模板。?
結論:
DetailsView和FormView比較:
相同點:
DetailsView和FormView都是對一條記錄進行展現。
不同點:雖然可以靈活運用DetailsView對一個字段運用模板的能力使UI看起來好像是對整條記錄運用的模板。但是我們沒有理由這樣做。
也就是說當以表格的形式方方正正的展示一條記錄時可以使用DetailsView來展示,并且字段的值可以使用模板來展示的比較漂亮。但是字段的值和字段的Text,必定是在同一行的。而FormView則可以更靈活的來布局。
DetailsView 和 FormView 之間的主要差異在于 DetailsView 具有內置的表格呈現方式,而 FormView 需要用戶定義的模板用于呈現。FormView 和 DetailsView 對象模型在其他方面非常類似。
DetailsView和GridView的模板列使用是基本一樣的,唯一的區別是一個橫向的展示數據,一個縱向的展示數據。
3 FormView
Note:關于數據綁定
?Eval 單向綁定:數據是只讀的
?Bind 雙向綁定:數據可以更改,并返回服務器端,服務器可以處理更改后的數據,如存入數據庫.
<%#Eval("Field")>或者<%#expression(Eval("Field")) 用來綁定數據, <Eval=expression> 用來計算表達式。
| 簡單屬性 | 客戶:<%# custID %> |
| 集合 | 訂單:<asp:ListBox id="List1" datasource='<%# myArray %>' runat="server"> |
| 表達式 | 合同:<%# ( customer.FirstName + " " + customer.LastName ) %> |
| 方法結果: | 未結余額:<%# GetBalance(custID) %> |
雖然該語法看起來與 Response.Write 的 ASP 快捷方式 <%= %> 相似,但其行為卻大不相同。ASP Response.Write 快捷方式語法在頁被處理時計算,而 ASP.NET 數據綁定語法僅在 DataBind 方法被調用時計算。
ASP.NET 頁框架提供一個靜態方法,計算后期綁定的數據綁定表達式并可選擇將結果格式化為字符串。DataBinder.Eval 的便利之處在于它消除了開發人員為了將值強制為所需數據類型所必須做的許多顯式強制轉換。當數據綁定控件在模板化的列表中時,它特別有用,因為通常數據行和數據字段的類型都必須轉換。
請考慮下面的示例,其中一個整數將被顯示為貨幣字符串。使用標準的 ASP.NET 數據綁定語法,必須先強制轉換數據行的類型才能檢索數據字段 IntegerValue。接著,該值作為參數被傳遞給 String.Format 方法。
<%#?String.Format("{0:c}",?((DataRowView)Container.DataItem)["IntegerValue"])?%>此語法可能很復雜,難于記憶。相反,DataBinder.Eval 只是一個具有三個參數的方法:數據項的命名容器、數據字段名稱和格式字符串。在諸如 FormView、GridView、DetailsView、DataList 或 Repeater 這樣的模板化控件中,命名容器始終為 Container.DataItem。Page 是可用于 DataBinder.Eval 的另一個命名容器。正如在前一小節中所討論的,ASP.NET 2.0 還包含 DataBinder.Eval 的新的簡化語法(僅僅是 Eval),可以在數據綁定控件模板中使用它來自動解析為 Container.DataItem。
<%#?DataBinder.Eval(Container.DataItem,?"IntegerValue",?"{0:c}")?%><%#?Eval("IntegerValue",?"{0:c}")?%>
格式字符串參數是可選的。如果省略它,則 DataBinder.Eval 返回一個對象類型的值,如下面的示例所示。
<%#?(bool)DataBinder.Eval(Container.DataItem,?"BoolValue")?%>要重點注意的是,相對于標準數據綁定語法,DataBinder.Eval 可能導致顯著的性能損失,因為它使用后期綁定反射。使用 DataBinder.Eval 時需謹慎,尤其是在不需要字符串格式設置的時候。
與 DetailsView 控件一樣,FormView 通過其關聯的數據源控件支持自動 Update、Insert 和 Delete 操作。若要定義編輯或插入操作的輸入 UI,可在定義 ItemTemplate 的同時定義 EditItemTemplate 或 InsertItemTemplate。在本模板中,您可以對輸入控件(如 TextBox、CheckBox 或 DropDownList)進行數據綁定,以綁定到數據源的字段。但是,這些模板中的數據綁定使用“雙向”數據綁定語法,從而允許 FormView 從模板中提取輸入控件的值,以便傳遞到數據源。這些數據綁定使用新的 Bind(fieldname) 語法而不是 Eval。
重要事項: 使用 Bind 語法進行數據綁定的控件必須設置有 ID 屬性。
FormView 支持使用 DefaultMode 屬性指定要顯示的默認模板,但在默認情況下,FormView 以 ReadOnly 模式啟動并呈現 ItemTemplate。若要啟用用于從 ReadOnly 模式轉換為 Edit 或 Insert 模式的 UI,可以向模板添加一個 Button 控件,并將其 CommandName 屬性設置為 Edit 或 New。可以在 EditItemTemplate 內添加 CommandName 設置為 Update 或 Cancel 的按鈕,以用于提交或中止更新操作。類似地,也可以添加 CommandName 設置為 Insert 或 Cancel 的按鈕,以用于提交或中止插入操作。
<asp:FormView?DataSourceID="ObjectDataSource1"?DataKeyNames="PhotoID"?runat="server">??<EditItemTemplate>
????<asp:TextBox?ID="CaptionTextBox"?Text='<%#?Bind("Caption")?%>'?runat="server"/>
????<asp:Button?Text="Update"?CommandName="Update"?runat="server"/>
????<asp:Button?Text="Cancel"?CommandName="Cancel"?runat="server"/>
??</EditItemTemplate>
??<ItemTemplate>
????<asp:Label?Text='<%#?Eval("Caption")?%>'?runat="server"?/>
????<asp:Button?Text="Edit"?CommandName="Edit"?runat="server"/>
??</ItemTemplate>
</asp:FormView>
在對 GridView 或 DetailsView 執行更新或插入操作時,如果該控件的列或字段定義了 BoundField,GridView 或 DetailsView 負責創建 Edit 或 Insert 模式中的輸入 UI,以便它能自動提取這些輸入值以傳遞回數據源。由于模板包含任意的用戶定義的 UI 控件,因此,需要使用雙向數據綁定語法,這樣 FormView 等模板化控件才能知道應從模板中提取哪些控件值以用于更新、插入或刪除操作。在 EditItemTemplate 中仍然可以使用 Eval 語法進行不傳遞回數據源的數據綁定。另請注意,FormView 與 DetailsView 和 GridView 一樣,支持使用 DataKeyNames 屬性保留主鍵字段(即使這些字段并未呈現)的原始值以傳遞回更新/插入操作。?
實驗:Eval?VS. Bind
?<EditItemTemplate>????????????????????????<table>
????????????????????????????<tr>?<td>?ID?</td>
???????????????????????????????????<td><%#Eval("au_id")%>?</td>?</tr>
????????????????????????????<tr>?<td>?au_lname?</td>
????????????????????????????????<td>?<asp:TextBox?ID="TextBox1"?runat="server"?Text='<%#Bind("au_lname")%>'></asp:TextBox>
????????????????????????????????</td></tr>
??????????????????????????<!---其他
?????????????????????????--->
????????????????????????</table>
?<EditItemTemplate>
運行結果和預期結果一致。
4 Repeater
5?DataList
二、DataSource
1 SqlDataSource
SqlDataSource,后者支持用于指定連接字符串、SQL 語句或存儲過程的屬性,用以查詢或修改數據庫。雖然這適合大多數小規模的個人或業余站點,但對于較大規模的企業級應用程序,在應用程序的呈現頁中直接存儲 SQL 語句可能很快就會變得無法維護。這些應用程序通常需要用中間層數據訪問層或業務組件構成的封裝性更好的數據模型。所幸 ASP.NET 數據源控件模型使用 ObjectDataSource 控件支持這種方法。
實驗:通過SqlDataSource將DetailView與GridView結合使用
本實驗是在DetailView的練習中的擴展。
當時的場景是通過將 ControlParameter 關聯到 GridView 的 SelectedValue 屬性來實現主/詳細信息方案。SelectedValue 屬性返回 DataKeyNames 屬性指定的第一個字段的值。
????????<asp:SqlDataSource?ID="SqlDataSource2"?runat="server"??ProviderName="<%$?ConnectionStrings:Pubs.ProviderName?%>"?????????SelectCommand="SELECT?[au_id],?[au_lname],?[au_fname],?[phone],?[address],?[city],?[state],?[zip],?[contract]?FROM?[authors]?WHERE?([au_id]?=?@au_id)"?OnDataBinding="SqlDataSource2_DataBinding"?ConnectionString="<%$?ConnectionStrings:Pubs?%>"
????????UpdateCommand="UPDATE?[authors]?SET?[au_id]?=?@au_id,?[au_lname]?=?@au_lname,?[au_fname]?=?@au_fname,?[state]?=?@state?WHERE?([au_id]?=?@au_id)">
????????????<SelectParameters>
????????????????<asp:ControlParameter?ControlID="GridView1"?Name="au_id"?PropertyName="SelectedValue"?Type="Object"?/>????????????????
????????????</SelectParameters>
????????</asp:SqlDataSource>
GridView的DataKeyNames 屬性可以指定用多個逗號分隔的字段值,例如,如果需要將多個值傳遞給主/詳細信息方案中的詳細信息數據源,便可以這樣做。這些附加鍵字段的值通過 SelectedDataKey 屬性公開,該屬性返回鍵字段的名稱/值對的 DataKey 對象。ControlParameter 甚至能夠通過將 PropertyName 屬性設置為一個表達式來引用這些鍵。例如 SelectedDataKey.Values("au_id"))。
????????<asp:SqlDataSource?ID="SqlDataSource2"?runat="server"??ProviderName="<%$?ConnectionStrings:Pubs.ProviderName?%>"?????????SelectCommand="SELECT?[au_id],?[au_lname],?[au_fname],?[phone],?[address],?[city],?[state],?[zip],?[contract]?FROM?[authors]?WHERE?([au_id]?=?@au_id)"?OnDataBinding="SqlDataSource2_DataBinding"?ConnectionString="<%$?ConnectionStrings:Pubs?%>"
????????UpdateCommand="UPDATE?[authors]?SET?[au_id]?=?@au_id,?[au_lname]?=?@au_lname,?[au_fname]?=?@au_fname,?[state]?=?@state?WHERE?([au_id]?=?@au_id)">
????????????<SelectParameters>
????????????????<asp:ControlParameter?ControlID="GridView1"?Name="au_id"?PropertyName="SelectedDataKey.Values[0]"?Type="Object"?/>
????????????????<asp:ControlParameter?ControlID="GridView1"?Name="au_lname"?PropertyName="SelectedDataKey.Values[1]"?Type="object"?/>????????????????
????????????</SelectParameters>
????????</asp:SqlDataSource>
2 ObjectDataSource
ObjectDataSource 控件對象模型類似于 SqlDataSource 控件。ObjectDataSource 公開一個 TypeName 屬性(而不是 ConnectionString 屬性),該屬性指定要實例化來執行數據操作的對象類型(類名)。類似于 SqlDataSource 的命令屬性,ObjectDataSource 控件支持諸如 SelectMethod、UpdateMethod、InsertMethod 和 DeleteMethod 的屬性,用于指定要調用來執行這些數據操作的關聯類型的方法。
ObjectDataSource 要求它能夠使用的對象具有非常具體的設計模式。這些限制主要是由執行 Web 應用程序請求的無狀態環境施加的。由于為每個請求提供服務通常都要創建和銷毀對象,通過對象數據源綁定的對象也需要是無狀態的。默認情況下,ObjectDataSource 假定 TypeName 屬性所指定的類型具有默認構造函數(無參數),不過,通過處理 ObjectCreating 事件來創建自定義對象實例并將它指定給事件參數的 ObjectInstance 屬性,也可以代表 ObjectDataSource 實例化該類型。與 SelectMethod 屬性關聯的對象方法可以返回任何 Object 或 IEnumerable 列表、集合或數組。在上面的數據訪問層示例中,DataView 對象實現了 Ienumerable。正如下一節將要討論的,這些方法還可能返回強類型集合或對象。
實驗一:將ObjectDataSource綁定到對象
步驟:
在App_Code文件夾中建立AuthorDB類
public?class?AuthorsDB...{
????static?string?connectionString?=?ConfigurationManager.ConnectionStrings["Pubs"].ConnectionString;
????public?AuthorsDB()
????...{
????}
????/**////?<summary>
????///?通過ID獲得詳細情況,用于綁定DetailsView的select方法
????///?</summary>
????///?<param?name="ID"></param>
????///?<returns></returns>
????public?static?DataSet?GetAuthorsByID(string?ID)
????...{
????????IDbConnection?dbConnection?=?new?SqlConnection(connectionString);
????????string?queryString?=?"SELECT?[au_id],?[au_lname],?[au_fname],?[phone],?[address],?[city],?[state],?[zip],?[contract]?FROM?[authors]?WHERE?([au_id]?=?@au_id)";
????????IDbCommand?cmd?=?new?SqlCommand();
????????cmd.CommandText?=?queryString;
????????cmd.Connection?=?dbConnection;
????????IDataParameter?param_ID?=?new?SqlParameter("au_id",?ID);
????????cmd.Parameters.Add(param_ID);
????????IDbDataAdapter?adapter?=?new?SqlDataAdapter();
????????adapter.SelectCommand?=?cmd;
????????DataSet?dataSet?=?new?DataSet();
????????adapter.Fill(dataSet);
????????return?dataSet;
????}
????/**////?<summary>
????///?獲得所有ID,用于綁定DropdownList
????///?</summary>
????///?<returns></returns>
????public?static?DataSet?GetIDs()
????...{
????????try
????????...{
????????????Database?db_Pubs?=?DatabaseFactory.CreateDatabase();
????????????DbCommand?cmd?=?db_Pubs.GetSqlStringCommand(@"SELECT?[au_id]?FROM?[authors]");
????????????DataSet?result?=?db_Pubs.ExecuteDataSet(cmd);
????????????return?result;
????????}
????????catch?(Exception?ex)
????????...{
????????????throw?new?Exception("無法獲取。。。",?ex);
????????}
????}
????/**////?<summary>
????///?用于綁定DetailView的更新方法
????///?</summary>
????///?<param?name="au_id"></param>
????///?<param?name="au_lname"></param>
????///?<param?name="au_fname"></param>
????///?<param?name="state"></param>
????public?static?void?UpdateAuthor(string?au_id,?string?au_lname,?string?au_fname,?string?state)
????...{
????????int?rowAffected?=?0;
????????Database?db_Pubs?=?DatabaseFactory.CreateDatabase();
????????DbCommand?cmd?=?db_Pubs.GetSqlStringCommand(@"UPDATE?[authors]?SET?[au_lname]=@au_lname,?[au_fname]=@au_fname,?[state]=@state?WHERE?([authors].[au_id]?=?@au_id)");
????????db_Pubs.AddInParameter(cmd,?"au_id",?DbType.String,?au_id);
????????db_Pubs.AddInParameter(cmd,?"au_lname",?DbType.String,?au_lname);
????????db_Pubs.AddInParameter(cmd,?"au_fname",?DbType.String,?au_fname);
????????db_Pubs.AddInParameter(cmd,?"state",?DbType.String,?state);
????????try
????????...{
????????????rowAffected?=?db_Pubs.ExecuteNonQuery(cmd);
????????}
????????catch?(Exception?ex)
????????...{
????????????throw?new?Exception("更新失敗!",?ex);
????????}
????????if?(rowAffected?==?0)
????????????throw?new?Exception("更新失敗!");
????}
}
新建DetailsViewDAL.aspx,添加ObjectDataSource,配置數據源和相關方法(碰到ObjectDataSource看不見類文件,重啟VS2005可能可以解決問題)。
結果:可以正確顯示,但是更新時出錯,錯誤信息為:
ObjectDataSource 'ObjectDataSource2' could not find a non-generic method 'UpdateAuthor' that has parameters: au_id, au_lname, au_fname, state, phone, address, city, zip, contract.
分析:
從異常信息來看,應該是更新時調用的方法簽名和AuthorDB中的UpdateAuthor方法的簽名不一致。也就是說,雖然給ObjectDataSource指定了更新方法,但是它調用的時候傳參是按照Select出來的列構造的。
聯想在GridView對數據的綁定,猜想在DetailsView中設置綁定列的ReadOnly屬性,應該可以使不需要更改的列不被生成參數(這也更符合實際中的需要,不可編輯的就不需要更新)。這時發現au_id也不會被作為參數傳遞。于是設置DataKeyNames="au_id",這樣ObjectDataSource會根據 OldValuesParameterFormatString="original_{0}“來生成一個參數original_au_id,這樣調整UpdateAuthor中的參數即可。
????????<asp:DetailsView?ID="DetailsView1"?runat="server"?DataSourceID="ObjectDataSource2"????????????Height="50px"?Width="125px"?AutoGenerateEditButton="True"?DataKeyNames="au_id"?AutoGenerateRows="False">?????
????????????<Fields>
????????????<asp:BoundField??HeaderText="ID"?DataField="au_id"??ReadOnly="true"/>
????????????<asp:BoundField?HeaderText="au_lname"?DataField="au_lname"?/>
????????????<asp:BoundField?HeaderText="au_fname"?DataField="au_fname"?/>
????????????<asp:BoundField?HeaderText="phone"?DataField="phone"??ReadOnly="True"/>????????????
????????????<asp:BoundField?HeaderText="address"?DataField="address"?ReadOnly="True"/>????????????
????????????<asp:BoundField?HeaderText="city"?DataField="city"?ReadOnly="True"/>
????????????<asp:BoundField?HeaderText="state"?DataField="state"?/>
????????????<asp:BoundField?HeaderText="zip"?DataField="zip"?ReadOnly="True"/>????????????
????????????<asp:CheckBoxField?HeaderText="contract"?DataField="contract"?ReadOnly="True"/>???????
????????????</Fields>??
????????</asp:DetailsView>
結果:
實現了部分數據可以編輯,部分數據只讀。
SqlDataSource和ObjectDataSource的比較
ObjectDataSourceStatusEventArgs支持的屬性:
| ? | AffectedRows | Gets or sets the number of rows that are affected by the data operation. |
| ? | Exception | Gets a wrapper for any exceptions that are thrown by the method that is called by the ObjectDataSource control during a data operation. |
| ? | ExceptionHandled | Gets or sets a value indicating whether an exception that was thrown by the business object has been handled. |
| ? | OutputParameters | Gets a collection that contains business object method parameters and their values. |
| ? | ReturnValue | Gets the return value that is returned by the business object method, if any, as an object. |
SqlDataSourceStatusEventArgs支持的屬性:
| ? | AffectedRows | Gets the number of rows affected by a database operation. |
| ? | Command | Gets the database command submitted to the database. |
| ? | Exception | Gets a wrapper for any exceptions thrown by the database during a data operation. |
| ? | ExceptionHandled | Gets or sets a value indicating whether an exception thrown by the database has been handled. |
關于AffectedRows:
SqlDataSource在更新后SqlDataSourceStatusEventArgs有AffectedRows來指示相關Command影響的行數,而ObjectDataSource的ObjectDataSourceStatusEventArgs除了AffectedRows屬性外,還有ReturnValue來判斷相關操作所調用的方法的返回值。
但是不同之處在于,SqlDataSourceStatusEventArgs的AffectedRows屬性通常都能正確的反映Command影響的行數,而ObjectDataSourceStatusEventArgs的AffectedRows確總是為-1。
而DetailsView的DetailsViewUpdatedEventArgs的AffectedRows確是在執行沒有發生異常或者發生異常但是已經處理時為SqlDataSource、ObjectDataSource的AffectedRows,而發生異常時為0。
所以:如果我們確實需要在DetailsView的事件中拿到正確的AffectedRows的值,并且使用了ObjectDataSource,則需要在Updated/Deleted/Inserted事件后手動設置AffectedRows。
????protected?void?ObjectDataSource1_Updated(object?sender,?ObjectDataSourceStatusEventArgs?e)????...{
??????????? .........
????????e.AffectedRows?=?e.ReturnValue;
????}
關于參數:
?對于參數的方向,缺省情況下都是Input型,即用于將值傳入數據源操作。參數也可以是雙向的,例如 InputOutput、Output 和 ReturnValue 參數。可以使用 Parameter 對象的屬性 Direction 指定參數的方向性。若要在數據源操作完成之后檢索這些參數的值,應處理相應的操作后事件,例如 Selected、Updated、Inserted 或 Deleted 事件,以便從傳遞給這些事件的事件參數中獲得參數值。SqlDataSourceStatusEventArgs 有一個 Command 屬性,可以使用該屬性獲得返回值和輸出參數。注意,對于雙向參數,在 SqlDataSource 中將 Parameter 對象的 Size 屬性設置為適當的值很重要。ObjectDataSourceStatusEventArgs 類型支持 OutputParameters 集合和 ReturnValue 屬性。
SqlDataSourceStatusEventArgs 的Output方向的參數一般來自存儲過程的output參數。而ObjectDataSource的Output方向的參數一般來自一個相關方法的一個用out聲明的參數,例如:
public?static?int?UpdateAuthor(string?original_au_id,?string?au_lname,?string?au_fname,?string?state,out?int?My_ReturnValue)...{
????????My_ReturnValue=1;
????????........
????????return?EffactedRows
?}
想象如下場景:ObjectDataSource的更新操作需要調用一個存儲過程,而該存儲過程包含一個output參數,如何返回該參數呢?
首先,ObjectDataSource必須先聲明該參數,My_ReturnValue的Direction為Output.
<asp:ObjectDataSource?ID="ObjectDataSource2"?runat="server"?OldValuesParameterFormatString="original_{0}"????????????????SelectMethod="GetAuthorsByID"?TypeName="AuthorsDB"?UpdateMethod="UpdateAuthor"?OnUpdated="ObjectDataSource2_Updated">
????????????????<UpdateParameters>
????????????????????<asp:Parameter?Name="au_id"?Type="String"?/>
????????????????????<asp:Parameter?Name="au_lname"?Type="String"?/>
????????????????????<asp:Parameter?Name="au_fname"?Type="String"?/>
????????????????????<asp:Parameter?Name="state"?Type="String"?/>
????????????????????<asp:Parameter?Direction="Output"?Name="My_ReturnValue"?Type="Int32"?/>
????????????????</UpdateParameters>
????????????????<SelectParameters>
????????????????????<asp:ControlParameter?ControlID="DropDownList1"?Name="ID"?PropertyName="SelectedValue"
????????????????????????Type="String"?/>
????????????????</SelectParameters>
????????????</asp:ObjectDataSource>
然后,更新方法需要聲明out參數,并且給該參數賦值。
????public?static?int?UpdateAuthor(string?original_au_id,?string?au_lname,?string?au_fname,?string?state,out?int?My_ReturnValue)????...{
????????My_ReturnValue?=?-1;
????????int?rowAffected?=?0;
????????Database?db_Pubs?=?DatabaseFactory.CreateDatabase();
????????DbCommand?cmd?=?db_Pubs.GetSqlStringCommand(@"update?[authors]?set?[au_lname]=@au_lname,?[au_fname]=@au_fname,?[state]=@state?where?([authors].[au_id]?=?@au_id)
???????????????????????????????????????????????????????????????set?@my_returnvalue=3");
???//???DbCommand?cmd?=?db_Pubs.GetStoredProcCommand("MyTest");
????????db_Pubs.AddInParameter(cmd,?"au_id",?DbType.String,?original_au_id);
????????db_Pubs.AddInParameter(cmd,?"au_lname",?DbType.String,?au_lname);
????????db_Pubs.AddInParameter(cmd,?"au_fname",?DbType.String,?au_fname);
????????db_Pubs.AddInParameter(cmd,?"state",?DbType.String,?state);
????????db_Pubs.AddOutParameter(cmd,?"My_ReturnValue",?DbType.Int32,4);
????????try
????????...{
????????????rowAffected?=?db_Pubs.ExecuteNonQuery(cmd);
????????????My_ReturnValue?=?(int)db_Pubs.GetParameterValue(cmd,?"My_ReturnValue");
????????}
????????catch?(Exception?ex)
????????...{
????????????throw?new?Exception("更新失敗!",?ex);
????????}
????????if?(rowAffected?==?0)
????????????throw?new?Exception("更新失敗!");
????????return?rowAffected;
????}
這樣,在更新之后的事件中
????protected?void?ObjectDataSource2_Updated(object?sender,?ObjectDataSourceStatusEventArgs?e)????...{
????????e.ExceptionHandled?=?true;
????????e.AffectedRows?=?1;
????}
可以監視到??e.OutputParameters["My_ReturnValue"]? 3? object {int}。
3 XmlDataSource
4 SitemapDataSource
三、Performance and Security
1 ?緩存數據、頁面
2 ?連接字符串常見處理?
3 沖突檢測
SqlDataSource和ObjectDataSource都支持ConflictDetection屬性。該屬性設置為CompareAllValues,則OldValues會被傳遞,否則不會,而只是傳遞Key和NewValues。
所以,對于ObjectDataSource,該屬性的設置將直接影響到相應方法的簽名。所以如果設置錯誤,將會在編譯時就報異常。而SqlDataSource則只會影響到相應Command的正確性,而不會報錯誤。如
SqlDataSource這樣設置
????????????<asp:SqlDataSource?ConnectionString="<%$?ConnectionStrings:Northwind?%>"?ID="SqlDataSource1"????????????????runat="server"?SelectCommand="SELECT?[OrderID],?[OrderDate],?[ShipCountry]?FROM?[Orders]"
????????????????UpdateCommand="UPDATE?[Orders]?SET?[OrderDate]?=?@OrderDate,?[ShipCountry]?=?@ShipCountry?WHERE?[OrderID]?=?@original_OrderID?AND?[OrderDate]?=?@original_OrderDate?AND?[ShipCountry]?=?@original_ShipCountry"
????????????????ConflictDetection="OverwriteChanges"?OldValuesParameterFormatString="original_{0}"
????????????????OnUpdating="SqlDataSource1_Updating">
????????????????<UpdateParameters>
????????????????????<asp:Parameter?Name="OrderDate"?Type="DateTime"?/>
????????????????????<asp:Parameter?Name="ShipCountry"?Type="String"?/>
????????????????????<asp:Parameter?Name="original_OrderID"?Type="Int32"?/>
????????????????????<asp:Parameter?Name="original_OrderDate"?Type="DateTime"?/>
????????????????????<asp:Parameter?Name="original_ShipCountry"?Type="String"?/>
????????????????</UpdateParameters>
????????????</asp:SqlDataSource>
執行的時候用Sql Server Profiler抓到的語句如下
exec?sp_executesql?N'UPDATE?[Orders]?SET?[OrderDate]?=?@OrderDate,?[ShipCountry]?=?@ShipCountry?WHERE?[OrderID]?=?@original_OrderID?AND?[OrderDate]?=?@original_OrderDate?AND?[ShipCountry]?=?@original_ShipCountry',N'@OrderDate?datetime,@ShipCountry?nvarchar(6),@original_OrderID?
int,@original_OrderDate?datetime,@original_ShipCountry?nvarchar(4000)',@OrderDate=''8888-07-05?
00:00:00:000'',@ShipCountry=N'France',@original_OrderID=10248,@original_OrderDate=NULL,@original_ShipCountry=NULL
Key和NewValues被傳遞了過來,但是OldValues則為NULL,所以更新不成功,但是不會出錯
而將CompareAllValues屬性設置為CompareAllValues后抓到的語句如下:
exec?sp_executesql?N'UPDATE?[Orders]?SET?[OrderDate]?=?@OrderDate,?[ShipCountry]?=?@ShipCountry?WHERE?[OrderID]?=?@original_OrderID?AND?[OrderDate]?=?@original_OrderDate?AND?[ShipCountry]?=?@original_ShipCountry',N'@OrderDate?datetime,@ShipCountry?nvarchar(6),@original_OrderID?
int,@original_OrderDate?datetime,@original_ShipCountry?nvarchar(6)',@OrderDate=''7777-07-05?
00:00:00:000'',@ShipCountry=N'France',@original_OrderID=10248,@original_OrderDate=''6666-07-05?00:00:00:000'',@original_ShipCountry=N'France'
可以發現OldValues被傳遞了過來。
不過需要注意的是:不管設置為OverwriteChanges還是CompareAllValues,在SqlDataSourceCommandEventArgs中都能拿到所有值(即OldValues也能拿到)。
另外,ObjectDataSource的DataObjectTypeName可以和CompareAllValues 結合使用。這樣ObjectDataSource構造參數時會去調用DataObjectTypeName指定類的構造函數。當更新、刪除,插入操作時會調用以該類作為參數,并且正好兩個參數的方法。這樣可以方便編寫代碼。
public?class?Contact...{
????private?int?_contactID;
????public?int?ContactID
????...{
????????get?...{?return?_contactID;?}
????????set?...{?_contactID?=?value;?}
????}
????private?String?_contactName;
????public?String?ContactName
????...{
????????get?...{?return?_contactName;?}
????????set?...{?_contactName?=?value;?}
????}
????public?Contact()
????...{
????????//
????????//?TODO:?Add?constructor?logic?here
????????//
????}
????public?Contact(int?ContactID,?String?ContactName)
????...{
????????_contactID?=?ContactID;
????????_contactName?=?ContactName;
????}
} ????public?int?UpdateContact(Contact?c,?Contact?original_c)
????...{
????????HttpContext.Current.Response.Write("UpdateContact(Contact?c,?Contact?original_c)");
????????return?UpdateContact(c.ContactName,?original_c.ContactID,?original_c.ContactName);
????} ??????<asp:ObjectDataSource?TypeName="ContactsListOptimistic"?ID="ObjectDataSource1"?runat="server"
????????SelectMethod="GetContacts"?UpdateMethod="UpdateContact"?ConflictDetection="CompareAllValues"
????????OldValuesParameterFormatString="original_{0}"?DataObjectTypeName="Contact"?OnUpdated="ObjectDataSource1_Updated">
????????<UpdateParameters>
??????????<asp:Parameter?Name="c"?/>
??????????<asp:Parameter?Name="original_c"?/>
????????</UpdateParameters>
??????</asp:ObjectDataSource>
四、其他
1?處理空值
數據控件支持各種處理空數據或缺少數據的方法。首先,GridView、FormView 和 DetailsView 全都支持一個 EmptyDataText 或 EmptyDataTemplate 屬性,當數據源沒有返回數據行時,可以使用該屬性為控件指定一種呈現。只需設置 EmptyDataText 和 EmptyDataTemplate 之一(當同時設置兩者時,EmptyDataTemplate 優先)。還可以在 BoundField(以及派生字段類型)、TemplateField 或數據源參數對象上指定一個 ConvertEmptyStringToNull 屬性,以指定在調用關聯的數據源操作之前,應將從客戶端發送的 String.Empty 值轉換為空值。ObjectDataSource 還支持一個 ConvertNullToDbNull 屬性,當關聯的方法需要 DbNull 參數而不是空值時,可將該屬性設置為 true(Visual Studio 數據集中的 TableAdapter 類有此要求)。還可以在 BoundField(以及派生字段類型)上指定一個 NullDisplayText 屬性,以便在數據源中返回的字段值為空值時,為該字段指定要顯示的值。如果該值在編輯模式期間未更改,則它將在一個 Update 操作期間作為空值返回數據源。最后,還可以在數據源參數上指定一個 DefaultValue 屬性,以便在傳遞的參數值為空值時,為參數指定一個默認值。這些屬性將按順序應用;例如如果同時設置 ConvertEmptyStringToNull 和 DefaultValue,則 String.Empty 值首先被轉換為空值,隨后被轉換為默認值。
2 處理事件
數據控件事件旨在為您提供在頁面執行生命周期中可插入自己的自定義代碼的適當位置。數據控件一般在特定操作發生之前和之后公開事件。在操作之前激發的事件通常使用 -ing 后綴進行命名,而在操作之后激發的事件則使用 -ed 后綴進行命名。例如,GridView 支持的事件包括:
- PageIndexChanging 和 PageIndexChanged -- 在分頁操作之前和之后引發
- SelectedIndexChanging 和 SelectedIndexChanged -- 在選擇操作之前和之后引發
- Sorting 和 Sorted -- 在排序操作之前和之后引發
- RowEditing 和 RowCancelingEdit -- 在行進入編輯模式之前或在編輯模式被取消之前引發
- RowUpdating 和 RowUpdated -- 在更新操作之前和之后引發
- RowDeleting 和 RowDeleted -- 在刪除操作之前和之后引發
- RowDataBound -- 當行與數據綁定時引發
- RowCreated -- 當創建行用于呈現(作為 TableRow)時引發
- RowCommand -- 當從控件中激發按鈕命令時引發
數據源控件也公開事件,類似于數據綁定控件事件。SqlDataSource 和 ObjectDataSource 控件都支持下列事件:
- Selecting 和 Selected -- 在選擇操作之前和之后引發
- Updating 和 Updated -- 在更新操作之前和之后引發
- Deleting 和 Deleted -- 在刪除操作之前和之后引發
- Inserting 和 Inserted -- 在插入操作之前和之后引發
- Filtering -- 在篩選器操作之前引發
ObjectDataSource 控件還在 TypeName 屬性所指定的對象被創建或銷毀時額外公開一些事件。通過設置所傳遞的事件參數的 ObjectInstance 屬性,可以在 ObjectCreating 事件中實際設置一個自定義對象。
- ObjectCreating 和 ObjectCreated -- 在對象被創建之前和之后引發
- ObjectDisposing -- 在對象被釋放之前引發
結論:
通常,在操作發生之前激發的事件用于取消操作(通過將事件參數的 Cancel 屬性設置為 true),或用于執行參數驗證或對部分數據預處理。在操作之后引發的事件用于編寫自定義代碼以響應給定的操作,或用于檢查操作的成功狀態。例如,可以檢查 Update、Insert 或 Delete 操作導致的 RowsAffected,或檢查 Exception 屬性以確定處理期間是否發生了異常。還可以設置事件參數的 ExceptionHandled 屬性以防止異常向上冒泡到控件或頁。
????????if?(e.Exception?!=?null)????????...{
????????????if?(e.Exception.InnerException?!=?null)
????????????...{
????????????????Response.Write(string.Format("<script>alert('{0}')</script>",?e.Exception.InnerException.Message));
????????????}
????????????else
????????????...{
????????????????Response.Write(string.Format("<script>alert('{0}')</script>",?e.Exception.InnerException.Message));
????????????}
????????????e.ExceptionHandled?=?true;
????????}
??處理參數:
如何處理各種數據控件事件以枚舉通過事件參數傳遞的參數集合?注意,與不需要插入數據庫的字段 相關聯的BoundField 的 InsertVisible 屬性應該設置為 false,例如 OrderID 字段是基礎數據庫中的標識列,不應該將它傳遞給 Insert 操作(數據庫在插入操作發生時自動遞增此值)。另請注意,如果OrderID 字段被標記為 DataKeyNames 中的主鍵,那么此字段的原始值保留在數據綁定控件所傳遞的 Keys 字典中。用戶向輸入控件中輸入的值在 NewValues 字典中傳遞,不過標記為 ReadOnly=false 的字段除外。非鍵字段的原始值也由數據綁定控件保留在一個 OldValues 字典中,以用于傳遞給數據源。這些參數值由 SqlDataSource 按照 NewValues、Keys 和 OldValues 的順序追加到命令上,不過在 ConflictDetection 設置為 OverwriteChanges 時,數據源默認不追加 OldValues。有關數據源如何使用 OldValues 的更多信息,請參考QuickStart中的“使用沖突檢測”一節。
通過按照自己喜歡的順序將靜態 Parameter 對象添加到數據源操作的參數集合,可以更改 SqlDataSource 向命令追加參數的順序。SqlDataSource 自動根據這些 Parameter 對象的順序對數據綁定控件傳遞的參數重新排序。這在數據源的 ProviderName 屬性設置為 System.Data.OleDb 時很有用,因為此設置不支持命名的參數,所以向命令追加參數的順序必須與命令中的匿名參數占位符(“?”)的順序相匹配。當使用命名的參數時,參數的順序無關緊要。可以指定 Parameter 對象的 Type 屬性,以便在執行命令或方法之前,強制將數據綁定控件傳遞的值轉換為適當的數據類型。同樣,可以設置 Parameter 的 Size 屬性,以指示 SqlDataSource 命令中的 DbParameter 的 Size (這是輸入/輸出、輸出和返回值參數所需要的)。
<asp:SqlDataSource?ConnectionString="<%$?ConnectionStrings:NorthwindOLEDB?%>"?ID="SqlDataSource1"????????ProviderName="<%$?ConnectionStrings:NorthwindOLEDB.ProviderName?%>"?runat="server"
????????SelectCommand="SELECT?TOP?10?[OrderID],?[OrderDate],?[ShipCountry]?FROM?[Orders]"
????????UpdateCommand="UPDATE?[Orders]?SET?[OrderDate]?=??,?[ShipCountry]?=???WHERE?[OrderID]?=??"
????????OnUpdating="SqlDataSource1_Updating">
????????<UpdateParameters>
??????????<asp:Parameter?Name="OrderDate"?Type="DateTime"?/>
??????????<asp:Parameter?Name="ShipCountry"?Type="String"?/>
??????????<asp:Parameter?Name="OrderID"?Type="Int32"?/>
????????</UpdateParameters>
??????</asp:SqlDataSource>
參數名稱的默認約定要求按照數據源 Select 操作所選擇的字段對新值進行命名。通過指定 OldValuesParameterFormatString 屬性(例如“original_{0}”),可以對來自 Keys 或 OldValues 的參數重命名,以將它們與 NewValues 區別開來。通過處理相應的事件以便在執行數據源操作之前更改參數的值,您還可以自定義參數的名稱。例如,如果 SqlDataSource 的更新操作與某個存儲過程關聯,該存儲過程采用的參數名稱與匹配默認約定的名稱不同,可以在調用該存儲過程之前在 SqlDataSource Updating 事件中修改參數名稱。
??void?SqlDataSource1_Updating(Object?sender,?System.Web.UI.WebControls.SqlDataSourceCommandEventArgs?e) ?{????e.Command.Parameters["@id"].Value?=?e.Command.Parameters["@ContactID"].Value;
????e.Command.Parameters["@name"].Value?=?e.Command.Parameters["@ContactName"].Value;
????e.Command.Parameters.Remove(e.Command.Parameters["@ContactID"]);
????e.Command.Parameters.Remove(e.Command.Parameters["@ContactName"]);
??}
ObjectDataSource 不依賴特定的參數順序,而只是查找具有匹配的參數名稱的方法。注意,為了解析方法重載,ObjectDataSource 沒有使用參數的 Type 或 Size。只對參數的名稱進行匹配,因此如果業務對象上有兩個具有相同名稱和參數名稱但具有不同參數類型的方法,ObjectDataSource 將無法區分它們。可以在事件中更改 ObjectDataSource 參數的名稱和值,類似于上面的 SqlDataSource 示例。但是,如果使用 DataObjectTypeName 指定要傳遞給 Update、Insert 和 Delete 操作的特定數據對象類型,您將不能修改參數名稱 -- 只能修改值。如果需要修改參數名稱,則不要使用 DataObjectTypeName,而只需在代碼中的數據源事件中手動構造相應的數據對象。
轉載于:https://www.cnblogs.com/4ec/archive/2007/05/30/764873.html
總結
以上是生活随笔為你收集整理的ASP.NET 2.0 的数据源、数据绑定控件概述与区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上海动物园门票多少钱啊?
- 下一篇: 原神定序试炼其二挑战任务达成攻略详解(完