如何在asp.net webform中显示来自嵌套ICollection的数据

问题描述:

我想弄清楚如何将使用EF检索到的嵌套集合绑定到Web表单的asp:ListView或asp:Repeater控件中。如何在asp.net webform中显示来自嵌套ICollection的数据

使用EF我创建了以下查询,我选择了一组代理以及他们与其他代理分享的实体列表。

public static ICollection<Agency> GetAllAgencies() 
     { 
      ICollection<Agency> retAgencies = null; 
      try 
      { 
       using (var context = new InformSecurityEntities(string.Empty)) 
       { 
        // retAgencies = context.Agencies.OrderBy(a => a.AgencyName).ToList(); 
        retAgencies = (from a in context.Agencies 
            .Include("SecurityDataShares1") 
            .OrderBy(a => a.AgencyName) 
            select a).ToList(); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception("Exception thrown in UserFactory.GetAllAgencies() : " + ex.InnerException + ex.Message); 
      } 

      return retAgencies; 
     } 

我一直在控制台应用程序中测试它,它工作正常。在控制台我渲染我的结果如下:

private static void showAgencies() 
     { 
      var results = UserFactory.GetAllAgencies(); 
      foreach (var item in results) 
      { 
       Console.WriteLine("Id: {0} || Name: {1}", 
        item.AgencyId, 
        item.AgencyName); 
       foreach (var i in item.SecurityDataShares1) 
       { 
        Console.WriteLine(i.ReceivingAgency.AgencyName); 
        Console.WriteLine(convertEntityToText(i.EntityId)); 
       } 

      } 
      Console.WriteLine("enter..."); 
      Console.ReadLine(); 
     } 

注:SecurityDataShares1是一个ICollection的

我想做什么就能做的是采取结果并将其渲染成类似下面的格式一个WebForm中:

Agency 1 
    Entity 1, Entity 2, Entity 3 ... 
Agency 2 
    Entity 1, Entity 4, Entity 5 ... 

当我收到挂了是在控制台应用程序,我可以访问嵌套收集和遍历它呈现出我的结果。我曾尝试使用带辅助嵌套中继器的中继器控件,并将控件绑定到方法结果。

背后

if (userRole.IsSysAdmin) 
    { 
    var agencyData = UserFactory.GetAllAgencies(); 

    if (agencyData != null || agencyData.Count > 0) 
    { 
     agencyListRepeater.DataSource = agencyData; 
     agencyListRepeater.DataBind(); 
    } 
    else 
    ... 

<asp:Repeater ID="agencyListRepeater" runat="server" OnItemDataBound="mainRepeaterBound"> 
       <ItemTemplate> 
        <div class="itemsRow"> 
        <div class="column-holder"> 
        <asp:Label CssClass="mgmtResultText" ID="lbl_AgencyName" runat="server" Text='<%# Eval("AgencyName") %>' /></div> 
        <br /> 
        <div class="mgmtIndentDiv">Sharing data with the following agencies:</div> 
         <asp:Repeater id="nestedDataShare" runat="server"> 
         <ItemTemplate> 
         <asp:Label runat="server" Text='<%# Eval("SecurityDataShares1.AgencyName") %>' /> 
         <asp:Label runat="server" Text='<%# Eval("SecurityDataShares1.EntityId") %>' /> 
         </ItemTemplate> 

         </asp:Repeater> 
        </div> 
       </ItemTemplate> 
      </asp:Repeater> 

代码然而每当SecurityDataShares1为null,这将失败。

对此有何建议或最佳方法?

在此先感谢。

我从来没有能够获得嵌套的阅读器来呈现数据,而它会编译,总是返回嵌套对象的零(0)结果。因此,我期待着一种替代解决方案。 请记住,这更多的是在UI内渲染数据的原始问题。

不使用数据读取器,我决定尝试使用LiteralControl class直接将html注入到UI中。为了在aspx页面中做到这一点,我添加了一个面板控件。你也可以使用一个div元素与属性ruant =“服务器”,但我决定用<asp:Panel/>控制:

所以ASPX文件中添加以下:

 <asp:Panel ID="agencyList" runat="server" /> 

然后在我的后面的代码我创建了两个参数p = PanelName和a = Collection的方法。

这种方法然后允许我遍历集合并将结果写入到UI中作为html。 记住LiteralControl只允许创建不需要服务器端处理的html元素或字符串。所以,如果你想添加的服务器端控件,你需要使用一个单独的方法用于创建对象的Look here for an example

protected void CreateHtmlResults(System.Web.UI.WebControls.Panel p, ICollection<Agency> a) 
    { 
     var results = a; 
     foreach (var item in results) 
     { 
      p.Controls.Add(new LiteralControl("<p><b>" + item.AgencyName + "</b></p>")); 
      foreach (var i in item.SecurityDataShares1) 
      { 
       p.Controls.Add(new LiteralControl(i.ReceivingAgency.AgencyName + " " + i.EntityId +"<br/>")); 
      } 
     } 
    } 

这是然后在格式称为如:

if (userRole.IsSysAdmin) 
    { 
    //get a list of all agencies 
    agencyData = UserFactory.GetAllAgencies(); 

if (agencyData != null || agencyData.Count > 0) 
{ 
    CreateHtmlResults(agencyList, agencyData);       
} 
else 
{ 
    //notify UI that no agencies exist 
} 
} 

我我仍然欣赏任何其他想法或方法,否则我希望这有助于。

-cheers!

在您的mainRepeaterBound函数中,您可以获得对实体集合的引用。

public void mainRepeaterBound(object sender, RepeaterItemEventArgs e) 
    { 
     if (e.Item.ItemType == ListItemType.Item) 
     { 
      System.Web.UI.WebControls.Repeater nestedDataShare = (System.Web.UI.WebControls.Repeater)e.Item.FindControl("nestedDataShare"); 
      Agency item = (Agency)e.Item.DataItem; 
      nestedDataShare.DataSource = from o in item.SecurityDataShares1 select o; 
      nestedDataShare.DataBind(); 
     } 

    } 

然后你内心的中继器看起来像:

<asp:Repeater id="nestedDataShare" runat="server"> 
        <ItemTemplate> 
        <asp:Label runat="server" Text='<%# Eval("AgencyName") %>' /> 
        <asp:Label runat="server" Text='<%# Eval("EntityId") %>' /> 
        </ItemTemplate> 
    </asp:Repeater> 

所以,现在你不通过的对象可能不是有访问属性。

+0

这似乎非常接近东西仍然缺失,这可能是由于EF调用。关于数据的初始负载GetAllAgencies()我可以看到SecurityDataShares1 Navigable属性中的数据。但是,在上面建议的方法中引用对象时,不存在任何记录。该对象没有被处理,它只是返回零记录。 (而在最初的查询中,我看到9个结果返回 – rlcrews 2012-04-03 14:21:14

Eval语句也可用于设置DataSouce属性。嵌套的中继器将具有在SecurityDataShares1列表中使用的类型的Eval语句。

<asp:Repeater ID="nestedDataShare" 
      runat="server" 
      DataSource='<%# Eval("SecurityDataShares1")'> 

    <ItemTemplate> 
     <asp:Label runat="server" Text='<%# Eval("AgencyName") %>' /> 
     <asp:Label runat="server" Text='<%# Eval("EntityId") %>' /> 
    </ItemTemplate> 

</asp:Repeater> 
+0

我在这里的问题不是绑定,而是数据返回,如果没有值存在,使用EF对象嵌套集合将不会返回。可能为空或计数为零如上所述在UI中绑定字段会导致异常,因为无法找到绑定的属性 – rlcrews 2012-04-03 13:50:51

+0

但是,您指定包含(SecurityDataShares1),那么它应该在内存中。 – 2012-04-03 13:51:58