4

我有一个 ASP.NET 页面,其中有一个绑定到 EntityDataSource 的 GridView 控件(请参见下面的简化代码)。网格显示Parent项目列表,并包含一列以显示Children此父项的 .Count。我可以让网格正确显示计数,但我无法弄清楚 asp:TemplateField SortExpression 值使用什么才能将排序设置为子项的计数。

这是我的代码的样子(为清楚起见进行了简化)...

<asp:EntityDataSource ID="edsParentList" runat="server" 
     ConnectionString="name=FooEntities" 
     DefaultContainerName="FooEntities" 
     EnableFlattening="False" 
     EntitySetName="Parents" 
     EntityTypeFilter="Parent"
     Include="Children"
     OrderBy="it.Name"
     Where="(it.Name LIKE '%' + @ParentNameLike + '%')
     >
     <WhereParameters>
         <asp:Parameter Name="ParentNameLike" Type="String" DefaultValue="_" />
     </WhereParameters>
 </asp:EntityDataSource>
 <asp:GridView ID="grdParents" runat="server" 
     AllowPaging="True" 
     AllowSorting="True" 
     AutoGenerateColumns="False" 
     DataSourceID="edsParentList"
     PageSize="20" 
     onpageindexchanged="grdParents_PageIndexChanged" onsorted="grdParents_Sorted" >
     <Columns>
         <asp:TemplateField HeaderText="Name" SortExpression="Name">
             <ItemTemplate>
                 <a href="Parent.aspx?id=<%# Eval("ParentID") %>"><%# Eval("Name") %></a>
             </ItemTemplate>
         </asp:TemplateField>
         <asp:BoundField DataField="BirthDate" HeaderText="Birth Date" 
              DataFormatString="{0:yyyy-MM-dd HH:mm}"
              SortExpression = "BirthDate" />
         <asp:TemplateField HeaderText="Children" SortExpression="Children.Count">
             <ItemTemplate>
                 <asp:Label ID="lblChildCount" runat="server" 
                  Text='<%# Eval("Children.Count") %>'></asp:Label>
             </ItemTemplate>
         </asp:TemplateField>
     </Columns>
 </asp:GridView>

这显示网格很好。但是,当我单击 Children 列的标题时,会引发此错误:

“Count”不是“Transient.collection[FooEntities.Child(Nullable=True,DefaultValue=)]”的成员。要提取集合元素的属性,请使用子查询来迭代集合。

我的问题是:如何在包含子对象集合的导航属性的 .Count() 上启用排序?

有没有办法用 SortExpression 指定它,还是我必须分解并手动进行所有分页和排序?(我显然更愿意避免!)

4

2 回答 2

1

在你的位置,由于实体类被声明为部分,我会尝试为父实体创建一个补充部分类代码文件,并添加一个 ChildCount 只读属性。此属性将引用 Children 导航属性。然后我会对此进行排序。

我在这里假设 EntityDataSource 可以使用我将在实体上称为派生属性的东西。我没有测试过这个。

于 2012-04-30T17:27:59.713 回答
1

我已经重现了该错误(在一个更简单的示例中),并且我相信不可能找到任何SortExpression可以对儿童计数进行排序的错误。

我看到了两个重要的附加信息:

  • 单击列标题时引发的异常是EntitySqlException
  • 堆栈跟踪中最后抛出异常的最后一个方法是EntityDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments)

ExecuteSelect是一种被各种特定数据源控件覆盖的abstract方法,以执行从数据存储加载数据的实际工作。DataSourceView如果EntityDataSource相应的视图是EntityDataSourceView并且从抛出的异常中EntitySqlException- 我会得出结论,使用Entity SQLExecuteSelect构建查询。

参数DataSourceSelectArguments包含在 中定义的参数,EntityDateSource并且SortExpression很可能只是您在TemplateField. 这些用于组成 Entity SQL 中的最终查询。

我会假设SortExpression只是作为ORDER BY实体 SQL 语句中的子句传递。这看起来像:

ORDER BY Children.Count

但这是无效的实体 SQL。您可以将虚线路径用于导航引用,但不能Count在 Entity SQL 中使用导航集合的任何“类似 LINQ”的方法或属性(如 )。

可以编写有效的实体 SQL,以便按子项的计数进行排序。根据此示例(在文件中搜索“Order By - Related Entities”),正确的 Entity SQL 语句将是:

"SELECT VALUE p2.p 
 FROM (SELECT p, ANYELEMENT(SELECT VALUE Count(c.ChildId) FROM p.Children AS c)
                 AS childCount
       FROM Parents AS p)
 AS p2
 ORDER BY p2.childCount"

(这太难读了,我什至不知道如何在语义上正确缩进代码。)

我认为这个ANYELEMENT(SELECT...构造是异常正在谈论并希望拥有的“子查询”,以便计算子集合的元素。

显然,如果p2.childCount没有SortExpression定义p2.

我的结论:没有希望找到一个SortExpression为孩子们工作的计数。

也许有一种方法不使用SortExpression- 例如通过捕获标题上的单击事件,然后在事件处理程序中手动构建完整的查询,但我真的不知道,是否以及如何可能。

为什么消费者EntityDataSourceGridView必须自己弄清楚呢?您是否在任何地方看到过记录:“当数据源的类型EntityDataSourceSortExpressionaTemplateField时,aGridView必须是有效的实体 SQL ORDER BY子句。 ”我没有。就像:“TheSortExpression是一个排序表达式。”

不幸的是,因为没有清楚地说明 发生了SortExpression什么,正确的语法是什么以及是否支持哪种表达式,所以这个答案更像是一个猜测而不是一个答案。

于 2012-04-30T20:19:40.130 回答