Entity Framework技術系列之6:數據綁定

前言

ASP.NET針對各種數據訪問技術,均提供了數據源控件,以實現在頁面對數據進行直接綁定。下圖是ASP.NET中數據源控件架構圖:

 

圖1 ASP.NET數據源控件架構圖

由上圖可見,針對Entity Framework的實體數據模型,ASP.NET提供了EntityDataSource數據源控件,在ASP.NET頁面綁定實體數據。通過與ASP.NET的其他數據綁定控件進行配合,你甚至可以不用在後臺寫任何代碼,就可以輕鬆實現實體數據的CRUD功能。同時,該數據源控件還可以加載關聯對象數據,通過它可以實現豐富的頁面功能。

本文接下來就在上一篇文章中使用的實體數據模型的基礎上,實現一個包含查詢、添加、修改和刪除的用戶信息列表頁面和一個顯示、添加和修改用戶詳細信息的表單頁面,展示EntityDataSource控件如何應用於常見的ASP.NET WebForm應用場景中。

 

列表

在列表頁面中,我將實現用戶及其詳細信息實體數據的列表顯式,以及根據輸入條件進行模糊查詢篩選,並支持在列表中添加、修改和刪除用戶實體數據。

一、列表顯式

首先在頁面中放入一個EntityDataSource控件(可以通過工具箱拖拽到頁面,也可以在頁面的代碼視圖中手動編碼,後同),並設置其相關屬性:

1 <asp:EntityDataSource ID="edsUsers" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="Users" Include="UserDetail" OrderBy="it.Account">
2 </asp:EntityDataSource>

由於需要在列表中展示用戶詳細信息,所以這裏需要顯式指定Include屬性加載UserDetail實體數據。注意,EntityDataSource不支持延遲加載,需要顯式指定需要的關聯實體對象,否則將不會加載,這與通過實體上下文環境獲取實體數據時的情況不太一樣。

ASP.NET頁面列表數據綁定控件有很多選擇,如DataGrid、GridView、Repeater、ListView等。本文選擇ListView作爲列表數據綁定控件。在頁面中放入一個ListView控件,並設置其相關屬性和模板內容:

複製代碼
 1 <asp:ListView ID="lvUsers" runat="server" DataSourceID="edsUsers" >
 2     <LayoutTemplate>
 3         <table border="1" width="800">
 4             <thead>
 5                 <tr>
 6                     <th>帳號</th>
 7                     <th width="200">姓名</th>
 8                     <th width="60">性別</th>
 9                     <th width="120">生日</th>
10                     <th width="150">操作</th>
11                 </tr>
12             </thead>
13             <tbody>
14                 <tr id="itemPlaceholder" runat="server"></tr>
15             </tbody>
16         </table>
17         <uc:Pager ID="Pager1" runat="server" />
18     </LayoutTemplate>
19     <ItemTemplate>
20         <tr>
21             <td><a href='Form.aspx?ID=<%# Eval("ID") %>' target="_blank"><%# Eval("Account") %></a></td>
22             <td><%# Eval("UserDetail.Name") %></td>
23             <td><%# Eval("UserDetail.Sex") %></td>
24             <td><%# Eval("UserDetail.Birthday", "{0:yyyy-MM-dd}")%></td>
25             <td></td>
26         </tr>
27     </ItemTemplate>
28     <EmptyDataTemplate>
29         沒有符合條件的數據
30     </EmptyDataTemplate>
31 </asp:ListView>
複製代碼

在佈局上這裏用了一點小技巧,帳號列沒有設置寬度,這樣可以根據父級標籤元素的寬度來自適應。

Pager是對ASP.NET的DataPager控件進行簡單封裝的用戶控件。ListView控件搭配DataPager控件可以實現數據庫層的分頁查詢。Pager用戶控件主要代碼如下:

複製代碼
 1 <div id="pager">
 2     <asp:DataPager ID="DataPager" runat="server" PageSize="20">
 3         <Fields>
 4             <asp:NextPreviousPagerField ButtonType="Image" ButtonCssClass="ImageButton-Pager" ShowFirstPageButton="true" ShowNextPageButton="false"
 5                 ShowPreviousPageButton="true" ShowLastPageButton="false" FirstPageImageUrl="~/Images/icon_first_16x16.png"
 6                 PreviousPageImageUrl="~/Images/icon_previous_16x16.png" RenderNonBreakingSpacesBetweenControls="False" />
 7             <asp:NumericPagerField ButtonCount="6" CurrentPageLabelCssClass="LinkButton-Pager-Current" NumericButtonCssClass="LinkButton-Pager" />
 8             <asp:NextPreviousPagerField ButtonType="Image" ButtonCssClass="ImageButton-Pager" ShowFirstPageButton="false" ShowNextPageButton="true"
 9                 ShowPreviousPageButton="false" ShowLastPageButton="true" LastPageImageUrl="~/Images/icon_last_16x16.png"
10                 NextPageImageUrl="~/Images/icon_next_16x16.png" RenderNonBreakingSpacesBetweenControls="False" />
11             <asp:TemplatePagerField>
12                 <PagerTemplate>
13                     <%# Container.PageSize %> 條/頁,共 <%# Math.Ceiling((double)Container.TotalRowCount / Container.PageSize)%> 頁,合計共 <%# Container.TotalRowCount %> 條記錄
14                 </PagerTemplate>
15             </asp:TemplatePagerField>
16         </Fields>
17     </asp:DataPager>
18 </div>
複製代碼

瀏覽頁面,已經可以看到列表裏顯示了用戶實體數據(上一篇文章的源碼中的單元測試可以爲你完成測試數據的準備工作),如下圖所示:

 

圖2 簡單列表

二、條件查詢

圖2中的列表功能非常簡單,不具有互動性,接下來爲它增加按條件查詢篩選功能。首先,在頁面中加入查詢表單控件:

1 帳號:
2 <asp:TextBox ID="tbAccount" runat="server" />
3 <asp:Button ID="btnSearch" runat="server" Text="搜索" />

然後,需要在EntityDataSource控件中加入WhereParameters查詢參數。WhereParameters支持多種參數,包括ControlParameter、QueryStringParameter、FormParameter、SessionParameter、CookieParameter等等,用於不同的參數值來源。這裏使用ControlParameter,從搜索表單控件獲取參數值,代碼如下所示:

複製代碼
1 <asp:EntityDataSource ID="edsUsers" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="Users" Include="UserDetail" AutoGenerateWhereClause="true">
2     <WhereParameters>
3         <asp:ControlParameter Name="Account" DbType="String" ControlID="tbAccount" PropertyName="Text" ConvertEmptyStringToNull="true" />
4     </WhereParameters>
5 </asp:EntityDataSource>
複製代碼

注意,除了爲EntityDataSource控件加入WhereParameters,還需要設置AutoGenerateWhereClause=”true”。

運行頁面,發現此時列表已支持查詢功能。但是細心的讀者會發現有一個問題,它不支持模糊查詢。這是因爲EntityDataSource控件自動生成的Where語句都是精確匹配的,要支持模糊查詢,需要自定義Where屬性,並設置AutoGenerateWhereClause=”false”,或不設置(該屬性默認值爲“false”):

1 <asp:EntityDataSource ID="edsUsers" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="Users" Include="UserDetail" Where="@Account is null or it.Account like '%'+@Account+'%'">

運行頁面,模糊查詢功能測試通過,如下圖所示:

 

圖3 模糊查詢

三、添加實體數據

EntityDataSource控件支持實體添加功能,只需要做很少的工作。首先,在ListView控件中加入InsertItemTemplate模板內容項:

複製代碼
 1 <asp:ListView ID="lvUsers" runat="server" DataSourceID="edsUsers" InsertItemPosition="LastItem">
 2  3     <InsertItemTemplate>
 4         <tr>
 5             <td><asp:TextBox ID="tbAccount" runat="server" Text='<%# Bind("Account") %>' /></td>
 6             <td></td>
 7             <td></td>
 8             <td></td>
 9             <td><asp:Button ID="btnAdd" runat="server" Text="添加" CommandName="Insert" ValidationGroup="Insert" /></td>
10         </tr>
11     </InsertItemTemplate>
12 13 </asp:ListView>
複製代碼

這裏有兩個地方非常關鍵,一是將實體屬性與控件值進行綁定,二是設置提交按鈕的事件名稱爲“Insert”。另外,別忘了設置ListView的InsertItemPosition屬性,否則添加表單將不會顯示。

然後,需要設置EntityDataSource控件的EnableInsert=”true”,使其允許通過它添加實體數據。另外,可以通過EntityDataSource控件的Inserted事件重新綁定數據,以實現頁面數據刷新。前臺代碼如下:

1 <asp:EntityDataSource ID="edsUsers" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="Users" Include="UserDetail" Where="@Account is null or it.Account like '%'+@Account+'%'" EnableInsert="true" OnInserted="edsUsers_Changed">

後臺事件代碼如下:

1 protected void edsUsers_Changed(object sender, EntityDataSourceChangedEventArgs e)
2 {
3     this.edsUsers.DataBind();
4 }

可以通過InsertParameters爲添加操作提供參數,這種需求一般發生在以非表單的方式提供實體屬性數據的情況下,比如本例中由於密碼不能爲空,而且也不打算在頁面提供直接錄入表單,就可以通過參數爲其設定默認值,如下所示:

1 <InsertParameters>
2     <asp:Parameter Name="Password" DbType="String" DefaultValue="11111111" />
3 </InsertParameters>

運行頁面,實體添加功能測試通過,如下圖所示:

 

圖4 添加實體數據

四、更新實體數據

更新實體數據功能的實現與添加實體數據類似。首先,在ListView控件中加入EditItemTemplate模板項: 

複製代碼
 1 <EditItemTemplate>
 2     <tr>
 3         <td><asp:TextBox ID="tbAccount" runat="server" Text='<%# Bind("Account") %>' /></td>
 4         <td><%# Eval("UserDetail.Name") %></td>
 5         <td><%# Eval("UserDetail.Sex") %></td>
 6         <td><%# Eval("UserDetail.Birthday", "{0:yyyy-MM-dd}")%></td>
 7         <td>
 8             <asp:Button ID="tbnEdit" runat="server" Text="保存" CommandName="Update" ValidationGroup="Update" />
 9             <asp:Button ID="tbnCancel" runat="server" Text="取消" CommandName="Cancel" CausesValidation="false" />
10         </td>
11     </tr>
12 </EditItemTemplate>
複製代碼

然後,還需要在ItemTemplate模板項中加入更新按鈕控件:

複製代碼
 1 <ItemTemplate>
 2     <tr>
 3         <td><a href='Form.aspx?ID=<%# Eval("ID") %>' target="_blank"><%# Eval("Account") %></a></td>
 4         <td><%# Eval("UserDetail.Name") %></td>
 5         <td><%# Eval("UserDetail.Sex") %></td>
 6         <td><%# Eval("UserDetail.Birthday", "{0:yyyy-MM-dd}")%></td>
 7         <td>
 8             <asp:Button ID="btnEdit" runat="server" Text="修改" CommandName="Edit" CommandArgument='<%#Eval("ID")%>'/>
 9         </td>
10     </tr>
11 </ItemTemplate>
複製代碼

然後設置EntityDataSource控件允許更新,以及更新完成後重新綁定數據:

1 <asp:EntityDataSource ID="edsUsers" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="Users" Include="UserDetail" Where="@Account is null or it.Account like '%'+@Account+'%'" EnableInsert="true" EnableUpdate="true" OnInserted="edsUsers_Changed" OnUpdated="edsUsers_Changed">

運行頁面,測試更新實體數據功能通過,如下圖所示:

 

圖5 更新實體數據

五、刪除實體數據

EntityDataSource刪除實體數據非常簡單。首先在ListView控件的ItemTemplate模板項中加入刪除按鈕:

1 <asp:Button ID="ibtnDelete" runat="server" Text="刪除" CommandName="Delete" CommandArgument='<%#Eval("ID")%>' OnClientClick="return confirm('刪除的數據不可恢復,確定要執行刪除操作嗎?');" />

這裏需要設置按鈕的命令名稱屬性CommandName=”Delete”,並且設置命令參數屬性CommandArgument=’<%#Eval(“ID”)%>’。

然後設置EntityDataSource允許刪除,並且在刪除後重新綁定數據:

1 <asp:EntityDataSource ID="edsUsers" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="Users" Include="UserDetail" EnableInsert="true" EnableUpdate="true" EnableDelete="true" OrderBy="it.Account" Where="@Account is null or it.Account like '%'+@Account+'%'" OnInserting="edsUsers_Inserting" OnInserted="edsUsers_Changed" OnUpdated="edsUsers_Changed" OnDeleted="edsUsers_Changed">

運行頁面,測試更新實體數據功能通過,如下圖所示:

 

圖6 刪除實體數據

 

表單

除了列表外,通過表單瀏覽、添加和更新數據也是常見的數據展示方式。下面就結合FormView控件,講解如何使用EntityDataSource進行表單數據綁定。

一、數據顯示

首先,在表單頁面中加入EntityDataSource控件:

1 <asp:EntityDataSource ID="edsUserDetail" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="UserDetails" Where="it.ID = @ID">
2     <WhereParameters>
3         <asp:QueryStringParameter Name="ID" DbType="Guid" QueryStringField="ID" ConvertEmptyStringToNull="true" />
4     </WhereParameters>
5 </asp:EntityDataSource>

然後在表單頁面中加入FormView控件:

複製代碼
 1 <asp:FormView ID="fvUserDetail" runat="server" DataSourceID="edsUserDetail" DefaultMode="ReadOnly">
 2     <ItemTemplate>
 3         <table border="1">
 4             <tbody>
 5                 <tr>
 6                     <th>姓名</th>
 7                     <td><%# Eval("Name") %></td>
 8                 </tr>
 9                 <tr>
10                     <th>性別</th>
11                     <td><%# Eval("Sex") %></td>
12                 </tr>
13                 <tr>
14                     <th>生日</th>
15                     <td><%# Eval("Birthday", "{0:yyyy-MM-dd}")%></td>
16                 </tr>
17             </tbody>
18         </table>
19         <asp:Button ID="btnEdit" runat="server" Text="修改" CommandName="Edit" />
20     </ItemTemplate>
21     <EmptyDataTemplate>
22         沒有滿足條件的數據
23         <asp:Button ID="btnAdd" runat="server" Text="添加" CommandName="Add" />
24     </EmptyDataTemplate>
25 </asp:FormView>
複製代碼

最後,需要在之前的列表頁面中,爲表單頁面添加鏈接:

複製代碼
1 <asp:ListView ID="lvUsers" runat="server" DataSourceID="edsUsers" InsertItemPosition="LastItem">
2 3 <ItemTemplate>
4         <tr>
5             <td><a href='Form.aspx?ID=<%# Eval("ID") %>' target="_blank"><%# Eval("Account") %></a></td>
6 7 </ItemTemplate>
8 9 </asp:ListView>
複製代碼

瀏覽列表頁面,點擊包含詳細信息的帳號鏈接,就可以進入表單頁面了,如下圖所示:

 

圖7 瀏覽視圖

二、添加實體數據

設置ListView的DataKeyNames=”ID”和OnItemCommand=”fvUserDetail_ItemCommand”:

1 <asp:FormView ID="fvUserDetail" runat="server" DataSourceID="edsUserDetail" DataKeyNames="ID" DefaultMode="ReadOnly" OnItemCommand="fvUserDetail_ItemCommand">

在EmptyDataTemplate模板項中加入添加按鈕:

1 <EmptyDataTemplate>
2     沒有滿足條件的數據
3     <asp:Button ID="btnAdd" runat="server" Text="添加" CommandName="Add" />
4 </EmptyDataTemplate>

在頁面後臺的fvUserDetail_ItemCommand事件方法中,切換FormView控件到添加視圖:

1 protected void fvUserDetail_ItemCommand(object sender, FormViewCommandEventArgs e)
2 {
3     if (e.CommandName == "Add")
4         this.fvUserDetail.ChangeMode(FormViewMode.Insert);
5 }

在FormView控件中加入InsertItemTemplate模板項內容:

複製代碼
 1 <InsertItemTemplate>
 2     <table border="1">
 3         <tbody>
 4             <tr>
 5                 <th>姓名</th>
 6                 <td><asp:TextBox ID="tbName" runat="server" Text='<%# Bind("Name") %>' /></td>
 7             </tr>
 8             <tr>
 9                 <th>性別</th>
10                 <td><asp:TextBox ID="tbSex" runat="server" Text='<%# Bind("Sex") %>' /></td>
11             </tr>
12             <tr>
13                 <th>生日</th>
14                 <td><asp:TextBox ID="tbBirthday" runat="server" Text='<%# Bind("Birthday") %>' /></td>
15             </tr>
16         </tbody>
17     </table>
18     <asp:Button ID="btnConfirm" runat="server" Text="確定" CommandName="Insert" />
19     <asp:Button ID="btnCancel" runat="server" Text="取消" CommandName="Cancel" />
20 </InsertItemTemplate>
複製代碼

設置EntityDataSource控件允許插入實體數據,並在插入後重新綁定,以及設置插入參數:

複製代碼
1 <asp:EntityDataSource ID="edsUserDetail" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="UserDetails" Where="it.ID = @ID" EnableInsert="true" OnInserted="edsUserDetail_Changed">
2     <WhereParameters>
3         <asp:QueryStringParameter Name="ID" DbType="Guid" QueryStringField="ID" ConvertEmptyStringToNull="true" />
4     </WhereParameters>
5     <InsertParameters>
6         <asp:QueryStringParameter Name="ID" DbType="Guid" QueryStringField="ID" ConvertEmptyStringToNull="true" />
7     </InsertParameters>
8 </asp:EntityDataSource>
複製代碼

最後,在頁面後臺的edsUserDetail_Changed事件中重新綁定數據:

1 protected void edsUserDetail_Changed(object sender, EntityDataSourceChangedEventArgs e)
2 {
3     this.edsUserDetail.DataBind();
4 }

運行列表頁面,點擊沒有詳細信息的帳號鏈接,就能進入表單頁面的空數據視圖了,如下圖所示:

 

圖8 空數據視圖

點擊“添加”按鈕,可以將頁面切換到添加視圖,如下圖所示:

 

圖9 添加視圖

三、更新實體數據

首先,在FormView控件的ItemTemplate模板項中添加修改按鈕:

1 <ItemTemplate>
2 3     <asp:Button ID="btnEdit" runat="server" Text="修改" CommandName="Edit" />
4 </ItemTemplate>

爲FormView控件加入EditItemTemplate模板項:

複製代碼
 1 <EditItemTemplate>
 2     <table border="1">
 3         <tbody>
 4             <tr>
 5                 <th>姓名</th>
 6                 <td><asp:TextBox ID="tbName" runat="server" Text='<%# Bind("Name") %>' /></td>
 7             </tr>
 8             <tr>
 9                 <th>性別</th>
10                 <td><asp:TextBox ID="tbSex" runat="server" Text='<%# Bind("Sex") %>' /></td>
11             </tr>
12             <tr>
13                 <th>生日</th>
14                 <td><asp:TextBox ID="tbBirthday" runat="server" Text='<%# Bind("Birthday") %>' /></td>
15             </tr>
16         </tbody>
17     </table>
18     <asp:Button ID="btnConfirm" runat="server" Text="確定" CommandName="Update" />
19     <asp:Button ID="btnCancel" runat="server" Text="取消" CommandName="Cancel" />
20 </EditItemTemplate>
複製代碼

然後設置EntityDataSource控件允許更新,並在更新操作後重新綁定數據:

1 <asp:EntityDataSource ID="edsUserDetail" runat="server" ConnectionString="name=Membership" DefaultContainerName="Membership" EntitySetName="UserDetails" EnableInsert="true" EnableUpdate="true" Where="it.ID = @ID" OnInserted="edsUserDetail_Changed" OnUpdated="edsUserDetail_Changed">

瀏覽列表頁面,點擊包含詳細信息的帳號鏈接,進入表單頁面的數據瀏覽視圖,如下圖所示:

 

圖10 帶修改按鈕的瀏覽視圖

點擊“修改”按鈕,就可以進入用戶詳細信息更新視圖了,如下圖所示:

 

圖11 更新視圖

 

總結

本文在簡單分析了ASP.NET數據源控件的技術架構後,通過實例依次實現了EntityDataSource結合ListView控件進行數據增刪改查,以及結合FormView控件進行數據瀏覽、添加和更新的功能,這些功能基本上覆蓋了50%的頁面數據應用場景。

EntityDataSource控件非常強大,但要用好它卻不容易,需要不斷的實踐方能體會它的奇妙之處。另外,你可以在參數控件、事件方法等方面擴展它,使其更強大,更貼近你的項目需求。

下一篇文章將帶領到家領略LINQ to Entities查詢技術與Entity Framework技術雙劍合璧的強大威力

發佈了7 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章