简体   繁体   English

使用StringBuilder和DataTable,当只有一行时,如何在不中断的情况下返回三列中的多行?

[英]Using StringBuilder and a DataTable, How do I return multiple rows in three columns without breaking when there is only one row?

I have a function that returns a list of email addresses from a SQL stored Proc based on an ID called. 我有一个函数,该函数根据调用的ID从SQL存储的Proc返回电子邮件地址列表。 It is using StringBuilder and returns one column. 它使用StringBuilder并返回一列。 For most IDs there are 4 or less email addresses and this format is fine. 对于大多数ID,电子邮件地址为4个或更少,这种格式很好。 However we are now getting more IDs with 10+ email addresses and this is making the page too long. 但是,我们现在获得了更多具有10多个电子邮件地址的ID,这使页面过长。

The function is: 该函数是:

DataTable dt = DAL.ExecStoredProc(DAL.DatabaseName.DB, "storedProc", param);
StringBuilder sb = new StringBuilder();
sb.Append("<br/><br/>");
sb.Append("<table border='0' cellpadding='3'>");
for (int i = 0; i < dt.Rows.Count; i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    sb.Append("</td></tr>");
}
sb.Append("</table>");
return sb.ToString();

I have tried using the following but it breaks when there are too few addresses to return: 我尝试使用以下内容,但是在返回的地址太少时会中断:

DataTable dt = DAL.ExecStoredProc(DAL.DatabaseName.DB, "storedProc", param);
StringBuilder sb = new StringBuilder();
sb.Append("<br/><br/>");
sb.Append("<table border='0' cellpadding='3'>");
for (int i = 0; i < dt.Rows.Count; i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    i++;
    sb.Append("</td>");
    sb.Append("<td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    i++;
    sb.Append("</td>");
    sb.Append("<td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    i++;
    sb.Append("</td></tr>");
}
sb.Append("</table>");
return sb.ToString();

Using Linq's Take function, you could replace the following block of code from your first example: 使用Linq的Take函数,您可以从第一个示例中替换以下代码块:

for (int i = 0; i < dt.Rows.Count; i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    sb.Append("</td></tr>");
}

with this: 有了这个:

foreach (var row in dt.Rows.OfType<DataRow>().Take(3))
{
    sb.Append("<tr><td>");
    sb.Append(row["EMail"].ToString());
    sb.Append("</td></tr>");
}

Since Take returns up to the specified number of elements from the beginning of the sequence, this block of code will be run anywhere from 0 to 3 times. 由于Take从序列的开头最多返回指定数量的元素,因此该代码块将在0到3次之间任意运行。 You'll have 3 addresses displayed at most (even if more are present), and you won't get an IndexOutOfRangeException if you have less than 3. 您最多将显示3个地址(即使存在更多地址),如果少于3个,则不会获得IndexOutOfRangeException


UPDATE: ASP.NET 2.0 Compatible 更新:与ASP.NET 2.0兼容

Since you can't use Linq, this should have the same result: 由于您不能使用Linq,因此结果应相同:

for (int i = 0; i < (dt.Rows.Count > 3 ? 3 : dt.Rows.Count); i++)
{
    sb.Append("<tr><td>");
    sb.Append(dt.Rows[i]["EMail"].ToString());
    sb.Append("</td></tr>");
}

The expression dt.Rows.Count > 3 ? 3 : dt.Rows.Count 表达式dt.Rows.Count > 3 ? 3 : dt.Rows.Count dt.Rows.Count > 3 ? 3 : dt.Rows.Count uses the ? dt.Rows.Count > 3 ? 3 : dt.Rows.Count使用? operator to cause the for loop to iterate over all of the email addresses unless there are more than 3, in which case it will iterate only 3 times. 运算符使for循环遍历所有电子邮件地址,除非有3个以上,否则将仅循环3次。

Instead of building a html table with a string builder have you considered using an asp.net repeater control . 您可以考虑使用asp.net转发器控件,而不是使用字符串生成器构建html表。 You can bind the DataTable directly to the repeater and then control the html from the html design surface. 您可以将DataTable直接绑定到转发器,然后从html设计图面控制html。 It would prove to be much more flexible for what you are trying to do. 对于您想做的事情,它将被证明更加灵活。 This is assuming you're using asp.net. 这是假设您正在使用asp.net。

Also see my post on creating a custom asp.net control as this will give you the most flexibility as well as encapsulate your custom html logic. 另请参阅我关于创建自定义asp.net控件的文章,因为这将为您提供最大的灵活性并封装您的自定义html逻辑。

Enjoy! 请享用!

I think Doug is on the right track, but if you insist on doing it with StringBuilder and a for-loop, try this: 我认为Doug走在正确的轨道上,但是如果您坚持使用StringBuilder和for循环来做到这一点,请尝试以下操作:

DataTable dt = DAL.ExecStoredProc(DAL.DatabaseName.DB, "storedProc", param);

StringBuilder sb = new StringBuilder();
sb.Append("<br/><br/>");
sb.Append("<table border='0' cellpadding='3'>");

string rowFormat = "<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>";

for (int i = 0; i < dt.Rows.Count; i+=3)
{
    string[] rowEmails = { String.Empty, String.Empty, String.Empty };

    for (int j = 0; j < 3; j++)
    {
        if (i+j < dt.Rows.Count) rowEmails[j] = dt.Rows[i+j]["Email"].ToString();
    }

    sb.AppendFormat(rowFormat, rowEmails[0], rowEmails[1], rowEmails[2]);
}

sb.Append("</table>");

return sb.ToString();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当数据具有NULL值时,如何使用SQL Server中的数据透视表将多行转换为多列的一行 - How to convert multiple rows into one row with multiple columns using Pivot in SQL Server when data having NULL values 使用条件遍历 C# 中的行时,如何让数据表检测多列? - How can I have a datatable detect multiple columns when iterating through rows in C# with conditionals? 当多列中的数据匹配时,如何合并DataTable中的行? - How to merge rows in a DataTable when data in multiple columns match? 如何使用For Loop两次查找数据表列和行? - How do I use For Loop twice to find datatable columns and rows? 如何在不使用循环的情况下从数据表中过滤空行? - How do i filter empty rows from a datatable without using a loop? 如何在一行中合并多个数据表(每个数据表返回一行) - How to merge multiple datatables (every datatable return one row) in one row 如何在不使用数据集或数据表的情况下向datagridview添加新行? - How do I Add a new row to a datagridview without using a dataset or datatable? 使用“收益”时如何返回空行? - How do I return an empty row when using “yield”? 如何从DataTable1.Row [i] [j]读取字符串值到DataTable2的数组或多行中 - How to read string value from DataTable1.Row[i][j] into an array or multiple rows of DataTable2 如何从其他数据表的行向数据表添加列 - How do i add columns to datatable from rows from another datatable
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM