国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
ASP.NET 2.0 的數(shù)據(jù)源、數(shù)據(jù)綁定控件概述與區(qū)別
一、Render UI

1 GridView

GridView 控件用來在表中顯示數(shù)據(jù)源的值。每列表示一個(gè)字段,而每行表示一條記錄。GridView 控件支持下面的功能:

    *

      綁定至數(shù)據(jù)源控件,如 SqlDataSource。
    *

      內(nèi)置排序功能。
    *

      內(nèi)置更新和刪除功能。
    *

      內(nèi)置分頁(yè)功能。
    *

      內(nèi)置行選擇功能。
    *

      以編程方式訪問 GridView 對(duì)象模型以動(dòng)態(tài)設(shè)置屬性、處理事件等。
    *

      多個(gè)鍵字段。
    *

      用于超鏈接列的多個(gè)數(shù)據(jù)字段。
    *

      可通過主題和樣式進(jìn)行自定義的外觀。

實(shí)驗(yàn)一:

將DetailsView和GridView放置在一個(gè)頁(yè)面。然后在DetailsView的SqlDataSource中的查詢參數(shù)設(shè)置為從GridView傳遞過來。

預(yù)期結(jié)果:當(dāng)GridView中的選擇不同的行時(shí),作為DataKeyNames屬性中的第一個(gè)字段au_id應(yīng)該作為參數(shù)傳遞給DetailsView的SqlDataSource,DetailsView根據(jù)數(shù)據(jù)源Render。

現(xiàn)象:當(dāng)GridView中的選擇不同的行時(shí),DetailsView控件沒有展現(xiàn)數(shù)據(jù)。

分析:

首先懷疑是DetailsView的屬性沒有設(shè)置正確,于是將其數(shù)據(jù)源的查詢參數(shù)設(shè)置默認(rèn)值,結(jié)果能展現(xiàn)。說明DetailsView和其SqlDataSource的屬性設(shè)置正確。

然后懷疑是GridView選擇行時(shí),其SelectedValue為空。于是在其SelectedIndexChanging事件和 SelectedIndexChanged中進(jìn)行調(diào)試,發(fā)現(xiàn)第一次選擇時(shí)GridView的SelectedIndexChanging事件中 SelectedValue確實(shí)為Null,而SelectedIndexChanged事件中SelectedValue值為預(yù)期值。而第二次以及以后的選擇時(shí)兩個(gè)事件中SelectedValue的值都為預(yù)期值。

那么GridView的SelectedValue為什么是Null呢?我查看一下GridView的屬性,EnableViewState設(shè)置為false,于是改成True,再試,還是不行。

經(jīng)過長(zhǎng)時(shí)間的嘗試,發(fā)現(xiàn)在如下兩種情況下程序結(jié)果是對(duì)的:

一:先設(shè)置DetailsView使用的SqlDataSource中查詢參數(shù)的默認(rèn)值,這樣DetailView會(huì)顯示出來,然后將其切換到Edit模式,發(fā)現(xiàn)其各字段的值確實(shí)是GridView選中行的值,然后再點(diǎn)擊Cancel放棄修改。則DetailView能夠正確響應(yīng)GridView的選擇操作。再調(diào)試代碼,發(fā)現(xiàn)GridView的SelectedIndexChanging事件中SelectedValue值不再為空,而是預(yù)期值。

二:發(fā)現(xiàn)一個(gè)更奇特的現(xiàn)象,在SelectedIndexChanging中設(shè)置斷點(diǎn),發(fā)現(xiàn)程序運(yùn)行進(jìn)來,然后什么都不做,跳出事件處理(如下)
    protected void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
    ...{
    }

程序結(jié)果也是對(duì)的,但是如果不設(shè)置斷點(diǎn),直接運(yùn)行,則結(jié)果不對(duì)。

又經(jīng)過很長(zhǎng)時(shí)間的嘗試,沒有辦法了,只好找同事幫忙。剛開始他也覺得離奇。先跟蹤事件發(fā)生的順序,接著發(fā)現(xiàn)了一個(gè)更離奇的現(xiàn)象:在 SelectedIndexChanging事件中設(shè)置斷點(diǎn)時(shí)我添加了對(duì)GridView.SelectedValue的監(jiān)視。雖然在事件響應(yīng)代碼中我什么都沒有做,但是這個(gè)watch好像起了作用。因?yàn)樗盐姨砑拥倪@個(gè)監(jiān)視去掉后,錯(cuò)誤現(xiàn)象又重現(xiàn)了。而添加這個(gè)監(jiān)視,或者在代碼里這樣寫
string s = GridView1.SelectedValue.ToString();

才能正常運(yùn)行。

最后,同事讓我在工程里新建一個(gè)頁(yè)面,SampleCode拷到這個(gè)頁(yè)面,然后運(yùn)行。以確定不是我的環(huán)境有錯(cuò)誤。然后把SamlpeCode和我的代碼做了對(duì)比。把一些不一樣的屬性去掉。當(dāng)改到GridView的SqlDataSource的EnableViewSate屬性時(shí),“奇跡”出現(xiàn)了。 SampleCode的該屬性設(shè)置為True,而我的是false,我改成True后,程序正常運(yùn)行。

這時(shí)候再去測(cè)試SelectedValue的值,發(fā)現(xiàn)第一次選擇時(shí),在SelectedIndexChanging事件中SelectedValue仍然為null,和錯(cuò)誤時(shí)的現(xiàn)象沒有什么區(qū)別。

錯(cuò)誤的源頭總算找到了,但是SqlDataSource的EnableViewState究竟做了什么呢?GridView的SelectedValue和SqlDataSource有關(guān)嗎?

實(shí)驗(yàn)二:分頁(yè)排序

雖然 GridView、DetailsView 和 FormView 提供頁(yè)導(dǎo)航 UI 的默認(rèn)呈現(xiàn),但是也可以通過設(shè)置 PagerTemplate 屬性自定義頁(yè)導(dǎo)航的呈現(xiàn)。在該模板中,您可以放置 CommandName 屬性設(shè)置為 Page 并且 CommandArgument 屬性設(shè)置為 First、Prev、 Next、Last 或 <number>(其中 <number> 是特定頁(yè)索引的值)的 Button 控件。

應(yīng)用分頁(yè)模板:
<PagerTemplate>
                                <div style="float: right">
                                    <asp:RangeValidator ID="rvTarget" runat="server" ControlToValidate="txtTarget" Type="Integer"
                                        ErrorMessage="頁(yè)碼超出范圍" MinimumValue="1" MaximumValue='<%#gvReportForDept.PageCount%>'></asp:RangeValidator>
                                    共<%=gvReportForDept.PageIndex + 1%>/<%=gvReportForDept.PageCount%>頁(yè)  第<asp:TextBox
                                        runat="server" ID="txtTarget" onkeypress="searchForDept(event);" CssClass="gotopage" MaxLength="10" Width="25px"
                                        Text='<%#gvReportForDept.PageIndex + 1%>'></asp:TextBox>頁(yè) 
                                    <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>

這將啟用默認(rèn)的分頁(yè)事件。如果需要在分頁(yè)中控制邏輯,例如:如果在TextBox中輸入頁(yè)碼,然后點(diǎn)擊Go按鈕,則不僅需要客戶端驗(yàn)證輸入的范圍,還需要在翻頁(yè)時(shí)驗(yàn)證頁(yè)碼的合理性,所以在PageIndexChanging事件中添加如下代碼:
       protected void gvReportForOrder_PageIndexChanging(object sender, GridViewPageEventArgs e)
        ...{
            GridViewPagingHandler(sender, e, this.gvReportForOrder);
        }
         /**//// <summary>
        /// 處理頁(yè)面內(nèi)GrivView的翻頁(yè)事件
        /// </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 控件用來在表中顯示來自數(shù)據(jù)源的單條記錄,其中記錄的每個(gè)字段顯示在表的一行中。它可與 GridView 控件結(jié)合使用,以用于主/詳細(xì)信息方案。DetailsView 控件支持下面的功能:

    *

      綁定至數(shù)據(jù)源控件,如 SqlDataSource。
    *

      內(nèi)置插入功能。
    *

      內(nèi)置更新和刪除功能。
    *

      內(nèi)置分頁(yè)功能。
    *

      以編程方式訪問 DetailsView 對(duì)象模型以動(dòng)態(tài)設(shè)置屬性、處理事件等。
    *

      可通過主題和樣式進(jìn)行自定義的外觀。

實(shí)驗(yàn)一:應(yīng)用DetailsView的模板列

DetailsView除了已經(jīng)定義的列外,還有模板列,這和FormView的模板類似,但是又有所不同。

在DetailsView'中可以這樣應(yīng)用模板列
  <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中這樣應(yīng)用模板
<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節(jié)點(diǎn)下的內(nèi)容似乎是一樣的。但是運(yùn)行起來發(fā)現(xiàn)不一樣:

可以看出:DetailsView只適合對(duì)一個(gè)字段運(yùn)用模板,而FormView則適合對(duì)整條記錄運(yùn)用模板。

結(jié)論:

DetailsView和FormView比較:

相同點(diǎn):

DetailsView和FormView都是對(duì)一條記錄進(jìn)行展現(xiàn)。

不同點(diǎn):雖然可以靈活運(yùn)用DetailsView對(duì)一個(gè)字段運(yùn)用模板的能力使UI看起來好像是對(duì)整條記錄運(yùn)用的模板。但是我們沒有理由這樣做。

也就是說當(dāng)以表格的形式方方正正的展示一條記錄時(shí)可以使用DetailsView來展示,并且字段的值可以使用模板來展示的比較漂亮。但是字段的值和字段的Text,必定是在同一行的。而FormView則可以更靈活的來布局。

DetailsView 和 FormView 之間的主要差異在于 DetailsView 具有內(nèi)置的表格呈現(xiàn)方式,而 FormView 需要用戶定義的模板用于呈現(xiàn)。FormView 和 DetailsView 對(duì)象模型在其他方面非常類似。

DetailsView和GridView的模板列使用是基本一樣的,唯一的區(qū)別是一個(gè)橫向的展示數(shù)據(jù),一個(gè)縱向的展示數(shù)據(jù)。

3 FormView

Note:關(guān)于數(shù)據(jù)綁定

Eval 單向綁定:數(shù)據(jù)是只讀的
Bind 雙向綁定:數(shù)據(jù)可以更改,并返回服務(wù)器端,服務(wù)器可以處理更改后的數(shù)據(jù),如存入數(shù)據(jù)庫(kù).

<%#Eval("Field")>或者<%#expression(Eval("Field")) 用來綁定數(shù)據(jù), <Eval=expression> 用來計(jì)算表達(dá)式。

簡(jiǎn)單屬性 客戶:<%# custID %>
集合 訂單:<asp:ListBox id="List1" datasource='<%# myArray %>' runat="server">
表達(dá)式 合同:<%# ( customer.FirstName + " " + customer.LastName ) %>
方法結(jié)果: 未結(jié)余額:<%# GetBalance(custID) %>

雖然該語法看起來與 Response.Write 的 ASP 快捷方式 <%= %> 相似,但其行為卻大不相同。ASP Response.Write 快捷方式語法在頁(yè)被處理時(shí)計(jì)算,而 ASP.NET 數(shù)據(jù)綁定語法僅在 DataBind 方法被調(diào)用時(shí)計(jì)算。

ASP.NET 頁(yè)框架提供一個(gè)靜態(tài)方法,計(jì)算后期綁定的數(shù)據(jù)綁定表達(dá)式并可選擇將結(jié)果格式化為字符串。DataBinder.Eval 的便利之處在于它消除了開發(fā)人員為了將值強(qiáng)制為所需數(shù)據(jù)類型所必須做的許多顯式強(qiáng)制轉(zhuǎn)換。當(dāng)數(shù)據(jù)綁定控件在模板化的列表中時(shí),它特別有用,因?yàn)橥ǔ?shù)據(jù)行和數(shù)據(jù)字段的類型都必須轉(zhuǎn)換。

請(qǐng)考慮下面的示例,其中一個(gè)整數(shù)將被顯示為貨幣字符串。使用標(biāo)準(zhǔn)的 ASP.NET 數(shù)據(jù)綁定語法,必須先強(qiáng)制轉(zhuǎn)換數(shù)據(jù)行的類型才能檢索數(shù)據(jù)字段 IntegerValue。接著,該值作為參數(shù)被傳遞給 String.Format 方法。
<%# String.Format("{0:c}", ((DataRowView)Container.DataItem)["IntegerValue"]) %>

此語法可能很復(fù)雜,難于記憶。相反,DataBinder.Eval 只是一個(gè)具有三個(gè)參數(shù)的方法:數(shù)據(jù)項(xiàng)的命名容器、數(shù)據(jù)字段名稱和格式字符串。在諸如 FormView、GridView、DetailsView、DataList 或 Repeater 這樣的模板化控件中,命名容器始終為 Container.DataItem。Page 是可用于 DataBinder.Eval 的另一個(gè)命名容器。正如在前一小節(jié)中所討論的,ASP.NET 2.0 還包含 DataBinder.Eval 的新的簡(jiǎn)化語法(僅僅是 Eval),可以在數(shù)據(jù)綁定控件模板中使用它來自動(dòng)解析為 Container.DataItem。
<%# DataBinder.Eval(Container.DataItem, "IntegerValue", "{0:c}") %>
<%# Eval("IntegerValue", "{0:c}") %>

格式字符串參數(shù)是可選的。如果省略它,則 DataBinder.Eval 返回一個(gè)對(duì)象類型的值,如下面的示例所示。
<%# (bool)DataBinder.Eval(Container.DataItem, "BoolValue") %>

要重點(diǎn)注意的是,相對(duì)于標(biāo)準(zhǔn)數(shù)據(jù)綁定語法,DataBinder.Eval 可能導(dǎo)致顯著的性能損失,因?yàn)樗褂煤笃诮壎ǚ瓷?。使?DataBinder.Eval 時(shí)需謹(jǐn)慎,尤其是在不需要字符串格式設(shè)置的時(shí)候。

與 DetailsView 控件一樣,F(xiàn)ormView 通過其關(guān)聯(lián)的數(shù)據(jù)源控件支持自動(dòng) Update、Insert 和 Delete 操作。若要定義編輯或插入操作的輸入 UI,可在定義 ItemTemplate 的同時(shí)定義 EditItemTemplate 或 InsertItemTemplate。在本模板中,您可以對(duì)輸入控件(如 TextBox、CheckBox 或 DropDownList)進(jìn)行數(shù)據(jù)綁定,以綁定到數(shù)據(jù)源的字段。但是,這些模板中的數(shù)據(jù)綁定使用“雙向”數(shù)據(jù)綁定語法,從而允許 FormView 從模板中提取輸入控件的值,以便傳遞到數(shù)據(jù)源。這些數(shù)據(jù)綁定使用新的 Bind(fieldname) 語法而不是 Eval。

重要事項(xiàng): 使用 Bind 語法進(jìn)行數(shù)據(jù)綁定的控件必須設(shè)置有 ID 屬性。

FormView 支持使用 DefaultMode 屬性指定要顯示的默認(rèn)模板,但在默認(rèn)情況下,F(xiàn)ormView 以 ReadOnly 模式啟動(dòng)并呈現(xiàn) ItemTemplate。若要啟用用于從 ReadOnly 模式轉(zhuǎn)換為 Edit 或 Insert 模式的 UI,可以向模板添加一個(gè) Button 控件,并將其 CommandName 屬性設(shè)置為 Edit 或 New。可以在 EditItemTemplate 內(nèi)添加 CommandName 設(shè)置為 Update 或 Cancel 的按鈕,以用于提交或中止更新操作。類似地,也可以添加 CommandName 設(shè)置為 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>

在對(duì) GridView 或 DetailsView 執(zhí)行更新或插入操作時(shí),如果該控件的列或字段定義了 BoundField,GridView 或 DetailsView 負(fù)責(zé)創(chuàng)建 Edit 或 Insert 模式中的輸入 UI,以便它能自動(dòng)提取這些輸入值以傳遞回?cái)?shù)據(jù)源。由于模板包含任意的用戶定義的 UI 控件,因此,需要使用雙向數(shù)據(jù)綁定語法,這樣 FormView 等模板化控件才能知道應(yīng)從模板中提取哪些控件值以用于更新、插入或刪除操作。在 EditItemTemplate 中仍然可以使用 Eval 語法進(jìn)行不傳遞回?cái)?shù)據(jù)源的數(shù)據(jù)綁定。另請(qǐng)注意,F(xiàn)ormView 與 DetailsView 和 GridView 一樣,支持使用 DataKeyNames 屬性保留主鍵字段(即使這些字段并未呈現(xiàn))的原始值以傳遞回更新/插入操作。

實(shí)驗(yàn):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>

運(yùn)行結(jié)果和預(yù)期結(jié)果一致。

4 Repeater

5 DataList

二、DataSource

1 SqlDataSource

SqlDataSource,后者支持用于指定連接字符串、SQL 語句或存儲(chǔ)過程的屬性,用以查詢或修改數(shù)據(jù)庫(kù)。雖然這適合大多數(shù)小規(guī)模的個(gè)人或業(yè)余站點(diǎn),但對(duì)于較大規(guī)模的企業(yè)級(jí)應(yīng)用程序,在應(yīng)用程序的呈現(xiàn)頁(yè)中直接存儲(chǔ) SQL 語句可能很快就會(huì)變得無法維護(hù)。這些應(yīng)用程序通常需要用中間層數(shù)據(jù)訪問層或業(yè)務(wù)組件構(gòu)成的封裝性更好的數(shù)據(jù)模型。所幸 ASP.NET 數(shù)據(jù)源控件模型使用 ObjectDataSource 控件支持這種方法。

實(shí)驗(yàn):通過SqlDataSource將DetailView與GridView結(jié)合使用

本實(shí)驗(yàn)是在DetailView的練習(xí)中的擴(kuò)展。

當(dāng)時(shí)的場(chǎng)景是通過將 ControlParameter 關(guān)聯(lián)到 GridView 的 SelectedValue 屬性來實(shí)現(xiàn)主/詳細(xì)信息方案。SelectedValue 屬性返回 DataKeyNames 屬性指定的第一個(gè)字段的值。
        <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 屬性可以指定用多個(gè)逗號(hào)分隔的字段值,例如,如果需要將多個(gè)值傳遞給主/詳細(xì)信息方案中的詳細(xì)信息數(shù)據(jù)源,便可以這樣做。這些附加鍵字段的值通過 SelectedDataKey 屬性公開,該屬性返回鍵字段的名稱/值對(duì)的 DataKey 對(duì)象。ControlParameter 甚至能夠通過將 PropertyName 屬性設(shè)置為一個(gè)表達(dá)式來引用這些鍵。例如 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 控件對(duì)象模型類似于 SqlDataSource 控件。ObjectDataSource 公開一個(gè) TypeName 屬性(而不是 ConnectionString 屬性),該屬性指定要實(shí)例化來執(zhí)行數(shù)據(jù)操作的對(duì)象類型(類名)。類似于 SqlDataSource 的命令屬性,ObjectDataSource 控件支持諸如 SelectMethod、UpdateMethod、InsertMethod 和 DeleteMethod 的屬性,用于指定要調(diào)用來執(zhí)行這些數(shù)據(jù)操作的關(guān)聯(lián)類型的方法。

ObjectDataSource 要求它能夠使用的對(duì)象具有非常具體的設(shè)計(jì)模式。這些限制主要是由執(zhí)行 Web 應(yīng)用程序請(qǐng)求的無狀態(tài)環(huán)境施加的。由于為每個(gè)請(qǐng)求提供服務(wù)通常都要?jiǎng)?chuàng)建和銷毀對(duì)象,通過對(duì)象數(shù)據(jù)源綁定的對(duì)象也需要是無狀態(tài)的。默認(rèn)情況下,ObjectDataSource 假定 TypeName 屬性所指定的類型具有默認(rèn)構(gòu)造函數(shù)(無參數(shù)),不過,通過處理 ObjectCreating 事件來創(chuàng)建自定義對(duì)象實(shí)例并將它指定給事件參數(shù)的 ObjectInstance 屬性,也可以代表 ObjectDataSource 實(shí)例化該類型。與 SelectMethod 屬性關(guān)聯(lián)的對(duì)象方法可以返回任何 Object 或 IEnumerable 列表、集合或數(shù)組。在上面的數(shù)據(jù)訪問層示例中,DataView 對(duì)象實(shí)現(xiàn)了 Ienumerable。正如下一節(jié)將要討論的,這些方法還可能返回強(qiáng)類型集合或?qū)ο蟆?

實(shí)驗(yàn)一:將ObjectDataSource綁定到對(duì)象

步驟:

在App_Code文件夾中建立AuthorDB類
public class AuthorsDB
...{
    static string connectionString = ConfigurationManager.ConnectionStrings["Pubs"].ConnectionString;
    public AuthorsDB()
    ...{

    }
    /**//// <summary>
    /// 通過ID獲得詳細(xì)情況,用于綁定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,配置數(shù)據(jù)源和相關(guān)方法(碰到ObjectDataSource看不見類文件,重啟VS2005可能可以解決問題)。

結(jié)果:可以正確顯示,但是更新時(shí)出錯(cuò),錯(cuò)誤信息為:
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.

分析:

從異常信息來看,應(yīng)該是更新時(shí)調(diào)用的方法簽名和AuthorDB中的UpdateAuthor方法的簽名不一致。也就是說,雖然給ObjectDataSource指定了更新方法,但是它調(diào)用的時(shí)候傳參是按照Select出來的列構(gòu)造的。

聯(lián)想在GridView對(duì)數(shù)據(jù)的綁定,猜想在DetailsView中設(shè)置綁定列的 ReadOnly屬性,應(yīng)該可以使不需要更改的列不被生成參數(shù)(這也更符合實(shí)際中的需要,不可編輯的就不需要更新)。這時(shí)發(fā)現(xiàn)au_id也不會(huì)被作為參數(shù)傳遞。于是設(shè)置DataKeyNames="au_id",這樣ObjectDataSource會(huì)根據(jù) OldValuesParameterFormatString="original_{0}“來生成一個(gè)參數(shù)original_au_id,這樣調(diào)整 UpdateAuthor中的參數(shù)即可。
        <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>

結(jié)果:

實(shí)現(xiàn)了部分?jǐn)?shù)據(jù)可以編輯,部分?jǐn)?shù)據(jù)只讀。

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支持的屬性:

Name Description
  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.

關(guān)于AffectedRows:

SqlDataSource在更新后 SqlDataSourceStatusEventArgs有AffectedRows來指示相關(guān)Command影響的行數(shù),而 ObjectDataSource的ObjectDataSourceStatusEventArgs除了AffectedRows屬性外,還有 ReturnValue來判斷相關(guān)操作所調(diào)用的方法的返回值。

但是不同之處在于,SqlDataSourceStatusEventArgs的AffectedRows屬性通常都能正確的反映Command影響的行數(shù),而ObjectDataSourceStatusEventArgs的AffectedRows確總是為-1。

而DetailsView的 DetailsViewUpdatedEventArgs的AffectedRows確是在執(zhí)行沒有發(fā)生異?;蛘甙l(fā)生異常但是已經(jīng)處理時(shí)為 SqlDataSource、ObjectDataSource的AffectedRows,而發(fā)生異常時(shí)為0。

所以:如果我們確實(shí)需要在DetailsView的事件中拿到正確的AffectedRows的值,并且使用了ObjectDataSource,則需要在Updated/Deleted/Inserted事件后手動(dòng)設(shè)置AffectedRows。
    protected void ObjectDataSource1_Updated(object sender, ObjectDataSourceStatusEventArgs e)
    ...{
            .........
        e.AffectedRows = e.ReturnValue;
    }

關(guān)于參數(shù):

對(duì)于參數(shù)的方向,缺省情況下都是Input型,即用于將值傳入數(shù)據(jù)源操作。參數(shù)也可以是雙向的,例如 InputOutput、Output 和 ReturnValue 參數(shù)。可以使用 Parameter 對(duì)象的屬性 Direction 指定參數(shù)的方向性。若要在數(shù)據(jù)源操作完成之后檢索這些參數(shù)的值,應(yīng)處理相應(yīng)的操作后事件,例如 Selected、Updated、Inserted 或 Deleted 事件,以便從傳遞給這些事件的事件參數(shù)中獲得參數(shù)值。SqlDataSourceStatusEventArgs 有一個(gè) Command 屬性,可以使用該屬性獲得返回值和輸出參數(shù)。注意,對(duì)于雙向參數(shù),在 SqlDataSource 中將 Parameter 對(duì)象的 Size 屬性設(shè)置為適當(dāng)?shù)闹岛苤匾?。ObjectDataSourceStatusEventArgs 類型支持 OutputParameters 集合和 ReturnValue 屬性。

SqlDataSourceStatusEventArgs 的Output方向的參數(shù)一般來自存儲(chǔ)過程的output參數(shù)。而ObjectDataSource的Output方向的參數(shù)一般來自一個(gè)相關(guān)方法的一個(gè)用out聲明的參數(shù),例如:
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
}

想象如下場(chǎng)景:ObjectDataSource的更新操作需要調(diào)用一個(gè)存儲(chǔ)過程,而該存儲(chǔ)過程包含一個(gè)output參數(shù),如何返回該參數(shù)呢?

首先,ObjectDataSource必須先聲明該參數(shù),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參數(shù),并且給該參數(shù)賦值。
    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;
    }

可以監(jiān)視到  e.OutputParameters["My_ReturnValue"]  3  object {int}。

3 XmlDataSource

4 SitemapDataSource

三、Performance and Security

1  緩存數(shù)據(jù)、頁(yè)面

2  連接字符串常見處理

3 沖突檢測(cè)

SqlDataSource和ObjectDataSource都支持ConflictDetection屬性。該屬性設(shè)置為CompareAllValues,則OldValues會(huì)被傳遞,否則不會(huì),而只是傳遞Key和NewValues。

所以,對(duì)于ObjectDataSource,該屬性的設(shè)置將直接影響到相應(yīng)方法的簽名。所以如果設(shè)置錯(cuò)誤,將會(huì)在編譯時(shí)就報(bào)異常。而SqlDataSource則只會(huì)影響到相應(yīng)Command的正確性,而不會(huì)報(bào)錯(cuò)誤。如

SqlDataSource這樣設(shè)置
            <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>

執(zhí)行的時(shí)候用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,所以更新不成功,但是不會(huì)出錯(cuò)

而將CompareAllValues屬性設(shè)置為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'

可以發(fā)現(xiàn)OldValues被傳遞了過來。

不過需要注意的是:不管設(shè)置為OverwriteChanges還是CompareAllValues,在SqlDataSourceCommandEventArgs中都能拿到所有值(即OldValues也能拿到)。

另外,ObjectDataSource的DataObjectTypeName可以和CompareAllValues 結(jié)合使用。這樣ObjectDataSource構(gòu)造參數(shù)時(shí)會(huì)去調(diào)用DataObjectTypeName指定類的構(gòu)造函數(shù)。當(dāng)更新、刪除,插入操作時(shí)會(huì)調(diào)用以該類作為參數(shù),并且正好兩個(gè)參數(shù)的方法。這樣可以方便編寫代碼。
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 處理空值

數(shù)據(jù)控件支持各種處理空數(shù)據(jù)或缺少數(shù)據(jù)的方法。首先,GridView、FormView 和 DetailsView 全都支持一個(gè) EmptyDataText 或 EmptyDataTemplate 屬性,當(dāng)數(shù)據(jù)源沒有返回?cái)?shù)據(jù)行時(shí),可以使用該屬性為控件指定一種呈現(xiàn)。只需設(shè)置 EmptyDataText 和 EmptyDataTemplate 之一(當(dāng)同時(shí)設(shè)置兩者時(shí),EmptyDataTemplate 優(yōu)先)。還可以在 BoundField(以及派生字段類型)、TemplateField 或數(shù)據(jù)源參數(shù)對(duì)象上指定一個(gè) ConvertEmptyStringToNull 屬性,以指定在調(diào)用關(guān)聯(lián)的數(shù)據(jù)源操作之前,應(yīng)將從客戶端發(fā)送的 String.Empty 值轉(zhuǎn)換為空值。ObjectDataSource 還支持一個(gè) ConvertNullToDbNull 屬性,當(dāng)關(guān)聯(lián)的方法需要 DbNull 參數(shù)而不是空值時(shí),可將該屬性設(shè)置為 true(Visual Studio 數(shù)據(jù)集中的 TableAdapter 類有此要求)。還可以在 BoundField(以及派生字段類型)上指定一個(gè) NullDisplayText 屬性,以便在數(shù)據(jù)源中返回的字段值為空值時(shí),為該字段指定要顯示的值。如果該值在編輯模式期間未更改,則它將在一個(gè) Update 操作期間作為空值返回?cái)?shù)據(jù)源。最后,還可以在數(shù)據(jù)源參數(shù)上指定一個(gè) DefaultValue 屬性,以便在傳遞的參數(shù)值為空值時(shí),為參數(shù)指定一個(gè)默認(rèn)值。這些屬性將按順序應(yīng)用;例如如果同時(shí)設(shè)置 ConvertEmptyStringToNull 和 DefaultValue,則 String.Empty 值首先被轉(zhuǎn)換為空值,隨后被轉(zhuǎn)換為默認(rèn)值。

2 處理事件

數(shù)據(jù)控件事件旨在為您提供在頁(yè)面執(zhí)行生命周期中可插入自己的自定義代碼的適當(dāng)位置。數(shù)據(jù)控件一般在特定操作發(fā)生之前和之后公開事件。在操作之前激發(fā)的事件通常使用 -ing 后綴進(jìn)行命名,而在操作之后激發(fā)的事件則使用 -ed 后綴進(jìn)行命名。例如,GridView 支持的事件包括:

    * PageIndexChanging 和 PageIndexChanged -- 在分頁(yè)操作之前和之后引發(fā)
    * SelectedIndexChanging 和 SelectedIndexChanged -- 在選擇操作之前和之后引發(fā)
    * Sorting 和 Sorted -- 在排序操作之前和之后引發(fā)
    * RowEditing 和 RowCancelingEdit -- 在行進(jìn)入編輯模式之前或在編輯模式被取消之前引發(fā)
    * RowUpdating 和 RowUpdated -- 在更新操作之前和之后引發(fā)
    * RowDeleting 和 RowDeleted -- 在刪除操作之前和之后引發(fā)
    * RowDataBound -- 當(dāng)行與數(shù)據(jù)綁定時(shí)引發(fā)
    * RowCreated -- 當(dāng)創(chuàng)建行用于呈現(xiàn)(作為 TableRow)時(shí)引發(fā)
    * RowCommand -- 當(dāng)從控件中激發(fā)按鈕命令時(shí)引發(fā)

數(shù)據(jù)源控件也公開事件,類似于數(shù)據(jù)綁定控件事件。SqlDataSource 和 ObjectDataSource 控件都支持下列事件:

    * Selecting 和 Selected -- 在選擇操作之前和之后引發(fā)
    * Updating 和 Updated -- 在更新操作之前和之后引發(fā)
    * Deleting 和 Deleted -- 在刪除操作之前和之后引發(fā)
    * Inserting 和 Inserted -- 在插入操作之前和之后引發(fā)
    * Filtering -- 在篩選器操作之前引發(fā)

ObjectDataSource 控件還在 TypeName 屬性所指定的對(duì)象被創(chuàng)建或銷毀時(shí)額外公開一些事件。通過設(shè)置所傳遞的事件參數(shù)的 ObjectInstance 屬性,可以在 ObjectCreating 事件中實(shí)際設(shè)置一個(gè)自定義對(duì)象。

    * ObjectCreating 和 ObjectCreated -- 在對(duì)象被創(chuàng)建之前和之后引發(fā)
    * ObjectDisposing -- 在對(duì)象被釋放之前引發(fā)

結(jié)論:

通常,在操作發(fā)生之前激發(fā)的事件用于取消操作(通過將事件參數(shù)的 Cancel 屬性設(shè)置為 true),或用于執(zhí)行參數(shù)驗(yàn)證或?qū)Σ糠謹(jǐn)?shù)據(jù)預(yù)處理。在操作之后引發(fā)的事件用于編寫自定義代碼以響應(yīng)給定的操作,或用于檢查操作的成功狀態(tài)。例如,可以檢查 Update、Insert 或 Delete 操作導(dǎo)致的 RowsAffected,或檢查 Exception 屬性以確定處理期間是否發(fā)生了異常。還可以設(shè)置事件參數(shù)的 ExceptionHandled 屬性以防止異常向上冒泡到控件或頁(yè)。
        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;
        }

  處理參數(shù):

如何處理各種數(shù)據(jù)控件事件以枚舉通過事件參數(shù)傳遞的參數(shù)集合?注意,與不需要插入數(shù)據(jù)庫(kù)的字段 相關(guān)聯(lián)的BoundField 的 InsertVisible 屬性應(yīng)該設(shè)置為 false,例如 OrderID 字段是基礎(chǔ)數(shù)據(jù)庫(kù)中的標(biāo)識(shí)列,不應(yīng)該將它傳遞給 Insert 操作(數(shù)據(jù)庫(kù)在插入操作發(fā)生時(shí)自動(dòng)遞增此值)。另請(qǐng)注意,如果OrderID 字段被標(biāo)記為 DataKeyNames 中的主鍵,那么此字段的原始值保留在數(shù)據(jù)綁定控件所傳遞的 Keys 字典中。用戶向輸入控件中輸入的值在 NewValues 字典中傳遞,不過標(biāo)記為 ReadOnly=false 的字段除外。非鍵字段的原始值也由數(shù)據(jù)綁定控件保留在一個(gè) OldValues 字典中,以用于傳遞給數(shù)據(jù)源。這些參數(shù)值由 SqlDataSource 按照 NewValues、Keys 和 OldValues 的順序追加到命令上,不過在 ConflictDetection 設(shè)置為 OverwriteChanges 時(shí),數(shù)據(jù)源默認(rèn)不追加 OldValues。有關(guān)數(shù)據(jù)源如何使用 OldValues 的更多信息,請(qǐng)參考QuickStart中的“使用沖突檢測(cè)”一節(jié)。

通過按照自己喜歡的順序?qū)㈧o態(tài) Parameter 對(duì)象添加到數(shù)據(jù)源操作的參數(shù)集合,可以更改 SqlDataSource 向命令追加參數(shù)的順序。SqlDataSource 自動(dòng)根據(jù)這些 Parameter 對(duì)象的順序?qū)?shù)據(jù)綁定控件傳遞的參數(shù)重新排序。這在數(shù)據(jù)源的 ProviderName 屬性設(shè)置為 System.Data.OleDb 時(shí)很有用,因?yàn)榇嗽O(shè)置不支持命名的參數(shù),所以向命令追加參數(shù)的順序必須與命令中的匿名參數(shù)占位符(“?”)的順序相匹配。當(dāng)使用命名的參數(shù)時(shí),參數(shù)的順序無關(guān)緊要??梢灾付?Parameter 對(duì)象的 Type 屬性,以便在執(zhí)行命令或方法之前,強(qiáng)制將數(shù)據(jù)綁定控件傳遞的值轉(zhuǎn)換為適當(dāng)?shù)臄?shù)據(jù)類型。同樣,可以設(shè)置 Parameter 的 Size 屬性,以指示 SqlDataSource 命令中的 DbParameter 的 Size (這是輸入/輸出、輸出和返回值參數(shù)所需要的)。
<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>

參數(shù)名稱的默認(rèn)約定要求按照數(shù)據(jù)源 Select 操作所選擇的字段對(duì)新值進(jìn)行命名。通過指定 OldValuesParameterFormatString 屬性(例如“original_{0}”),可以對(duì)來自 Keys 或 OldValues 的參數(shù)重命名,以將它們與 NewValues 區(qū)別開來。通過處理相應(yīng)的事件以便在執(zhí)行數(shù)據(jù)源操作之前更改參數(shù)的值,您還可以自定義參數(shù)的名稱。例如,如果 SqlDataSource 的更新操作與某個(gè)存儲(chǔ)過程關(guān)聯(lián),該存儲(chǔ)過程采用的參數(shù)名稱與匹配默認(rèn)約定的名稱不同,可以在調(diào)用該存儲(chǔ)過程之前在 SqlDataSource Updating 事件中修改參數(shù)名稱。
  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 不依賴特定的參數(shù)順序,而只是查找具有匹配的參數(shù)名稱的方法。注意,為了解析方法重載,ObjectDataSource 沒有使用參數(shù)的 Type 或 Size。只對(duì)參數(shù)的名稱進(jìn)行匹配,因此如果業(yè)務(wù)對(duì)象上有兩個(gè)具有相同名稱和參數(shù)名稱但具有不同參數(shù)類型的方法,ObjectDataSource 將無法區(qū)分它們??梢栽谑录懈?ObjectDataSource 參數(shù)的名稱和值,類似于上面的 SqlDataSource 示例。但是,如果使用 DataObjectTypeName 指定要傳遞給 Update、Insert 和 Delete 操作的特定數(shù)據(jù)對(duì)象類型,您將不能修改參數(shù)名稱 -- 只能修改值。如果需要修改參數(shù)名稱,則不要使用 DataObjectTypeName,而只需在代碼中的數(shù)據(jù)源事件中手動(dòng)構(gòu)造相應(yīng)的數(shù)據(jù)對(duì)象。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
ASP.NET 2.0 數(shù)據(jù)操作:插入、更新、刪除數(shù)據(jù)時(shí)的事件
第六章_后臺(tái)商品顯示
在GridView的頁(yè)腳中顯示統(tǒng)計(jì)信息
有關(guān)SqlDataSource的一些知識(shí)
使用 IIS 進(jìn)行 ASP.NET 2.0 成員/角色管理(2):實(shí)現(xiàn)
OutputCache屬性詳解(四)— SqlDependency
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服