【问题标题】:iterate through datareader/datatable within loop在循环中遍历 datareader/datatable
【发布时间】:2016-09-29 22:55:44
【问题描述】:

我正在根据从数据库中获取的安全权限动态构建导航栏。数据库查找包括页面名称。最初我使用数据读取器并执行以下操作:

SqlDataReader SRmenu = sqlCMD.ExecuteReader();
HtmlGenericControl liToAdd;
if (SRmenu.HasRows)
{
    while (SRmenu.Read())
    {
        liToAdd = new HtmlGenericControl("li");
        MainUL1.Controls.Add(liToAdd);
        HtmlGenericControl addpage = new HtmlGenericControl("a");
        addpage.Attributes.Add("href", Convert.ToString(SRmenu["PageName"]));
        addpage.InnerText = Convert.ToString(SRmenu["Name"]);
        liToAdd.Controls.Add(addpage);
    }
}
SRmenu.Close();
conn.Close();

这工作得非常好,直到我想添加可能的下拉菜单(对于该人可以访问的页面超过一页的部分)。我的更新代码如下

if (SRmenu.HasRows)
            {
                while (SRmenu.Read())
                {
                    LoopCount = LoopCount + 1;
                    Int32 AppCount = Convert.ToInt32(SRmenu["AppCount"]);
                    if (AppCount > 1)
                    {
                        Int32 ApplicationID = Convert.ToInt32(SRmenu["ApplicationID"]);
                        Int32 ApplicationID2 = Convert.ToInt32(SRmenu["ApplicationID"]);
                        liToAdd = new HtmlGenericControl("li");
                        liToAdd.Attributes.Add("class", "dropdown");
                        MainUL1.Controls.Add(liToAdd);

                        HtmlGenericControl addhref = new HtmlGenericControl("a");
                        addhref.Attributes.Add("href", Convert.ToString(SRmenu["PageName"]));
                        addhref.InnerText = Convert.ToString(SRmenu["Name"]);
                        liToAdd.Attributes.Add("class", "dropdown-toggle");
                        addhref.Attributes.Add("data-toggle", "dropdown");
                        liToAdd.Controls.Add(addhref);

                        HtmlGenericControl addspan = new HtmlGenericControl("span");
                        addspan.Attributes.Add("class", "caret");
                        addhref.Controls.Add(addspan);

                        HtmlGenericControl addUL = new HtmlGenericControl("ul");
                        addUL.Attributes.Add("class", "dropdown-menu");
                        liToAdd.Controls.Add(addUL);

                        while (ApplicationID == ApplicationID2)
                        {
                            HtmlGenericControl addDropDown = new HtmlGenericControl("li");
                            addUL.Controls.Add(addDropDown);
                            HtmlGenericControl addpage = new HtmlGenericControl("a");
                            addpage.Attributes.Add("href", Convert.ToString(SRmenu["PageName"]));
                            addpage.InnerText = Convert.ToString(SRmenu["Name"]);
                            addDropDown.Controls.Add(addpage);
                            SRmenu.Read();
                            if (LoopCount < FieldCount)
                            { ApplicationID2 = Convert.ToInt32(SRmenu["ApplicationID"]); }
                            else
                            { ApplicationID2 = 0; }
                            LoopCount = LoopCount + 1;
                        }
                    }
                    else
                    {
                        liToAdd = new HtmlGenericControl("li");
                        MainUL1.Controls.Add(liToAdd);
                        HtmlGenericControl addpage = new HtmlGenericControl("a");
                        addpage.Attributes.Add("href", Convert.ToString(SRmenu["PageName"]));
                        addpage.InnerText = Convert.ToString(SRmenu["Name"]);
                        liToAdd.Controls.Add(addpage);
                    }
                }
            }

我遇到的问题是在 READ() 循环中添加一个循环。目前我正在尝试使用 While (ApplicationID == ApplicationID2) 循环,这让我得到第一个值而不是第二个(目前只有两个页面属于同一个 ApplicationID,它们是我的最后两条记录Read() 循环) - 问题是第二个值永远不会进入下拉列表。

当我在调试中运行它时,它不会经过第二个循环,它会点击“if (SRmenu.HasRows)”它无法找到其他行,因此它存在循环 - 如果我注释掉整个 IF/ELSE并返回到我的原始代码,它确实看到了所有预期的页面,因此数据存在。

我知道如何在经典 ASP 中完成此任务,但我正在努力在 C#/ASP.NET 中找到类似的解决方案。我会在经典中做的是类似于

RSMenu.open
do while not RSMenu.EoF
    if PageCount>1 then
      <code for drop down segment>
      do while count < PageCount
         <LI HTML Code>
         RSMenu.MoveNext
      loop
    else
        <LI HTML Code>
    end if
    RSMenu.MoveNext
loop

编辑

  1. 更新了关于 FOR 循环的评论
  2. 删除了对 FOR 循环的引用。这不是我正在使用的东西,并且在重新阅读后觉得它与我的问题无关。它被列为另一种考虑的方法,但似乎无法解决上述问题。
  3. 看起来像 NextResult();是错误的命令,它循环了一批命令,它不会迭代到该读取集中的下一条记录 - 所以我想弄清楚的是如何做到这一点。
  4. 显然 Read() 迭代到下一条记录。 'HasRows' 方法不能用于测试它是否仍然有行,所以我在循环之前添加了一个 FieldCount,并在其中添加了一个 LoopCount。这很有效。

【问题讨论】:

  • 你最后的“for”循环确实从行中获取每个值(reader.GetValue(i) 获取当前行的第 i 列的值)。
  • @David_001 - 抱歉,我的意思是说它不允许我遍历行。会更新。
  • @David_001 我曾提到 FOR 循环是我考虑过的另一种解决方案,但它的功能似乎与我所做的不同。阅读我的帖子后,我觉得这是不相关的辅助信息(因为我目前没有使用它,也没有尝试/考虑过其他方法)。
  • 我发现了一点我的问题,NextResult();命令不会遍历当前的 READ(),如果您正在执行一批记录,它会转到下一个数据集。所以我的核心问题是如何在不回到循环顶部的情况下迭代读取记录。或者我可以重做我的 HTML 方法以将它们部分移出循环。
  • 与您的问题无关 - 但通常值得拥有基于 POC 的强类型数据模型,而不是直接从 db 获取值到控制树。缓存也很方便(您不需要为每个请求查询 db 导航)。

标签: c# asp.net datareader


【解决方案1】:

我在上面进行了最终编辑以包含但问题是我试图使用 .NEXTRESULT() 用于迭代一批查询。 .READ() 将迭代到下一条记录。

我还发现 .HASROWS 只检查阅读器是否有,而不是是否还有记录。所以我在 read() 开始和循环计数之前添加了一个字段计数。

我觉得有一种更好的方法可以做到这一点,并且可能会看到将 HTML 声明拉到循环之外,然后看看我是否可以从内部正确地添加它们 - 但现在这是可行的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 2010-11-14
    • 2015-12-26
    • 1970-01-01
    • 2021-11-18
    相关资源
    最近更新 更多