Entity Framework技术系列之6:数据绑定

来源:互联网 发布:全球网络医院裸体艺术 编辑:程序博客网 时间:2024/06/03 22:43

前言

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技术双剑合璧的强大威力

原创粉丝点击