Ну, я могу помочь с циклической структурой. Это не совсем соответствует тому, что вы делаете (оно оставляет таблицу нетронутой и просто строит большую строку, а также предполагает, что таблица отсортирована определенным образом), но оно продемонстрирует классическую обработку прерывания управления с использованием ваших реальных данных. Для этого таблица должна быть отсортирована по пользователю, а затем по роли.
Dim i As Integer = 0
Dim CurUser As String = ""
Dim CurRole As String = ""
Dim result As new StringBuilder()
Dim r as DataRowCollection = ds.Tables(0).Rows
While i < r.Count
'Next User:'
CurUser = r(i)("UserName")
result.AppendFormat("<h2>{0}</h2>", CurUser).AppendLine()
result.AppendLine("<table>")
While i < r.Count AndAlso CurUser = r(i)("UserName")
'Next Role:'
CurRole = r(i)("roleName")
result.AppendFormat("<tr><td>{0}</td></tr>", CurRole).AppendLine()
While i < r.Count AndAlso CurUser = r(i)("UserName") AndAlso CurRole = r(i)("roleName")
i += 1 'Next Record: same user, role '
End While
'Finished this role'
End While
'Finished this user:'
result.AppendLine("</table>").AppendLine()
End While
Это имеет 3 вложенных циклов, а не только ваши два. Тем не менее, он по-прежнему получает линейную производительность: он будет перебирать каждую запись только один раз. Это работает, потому что все циклы имеют один и тот же счетчик, который увеличивается только во внутреннем цикле, и все они имеют одинаковое условие базового конца.