Хорошо, есть 3 пункта, которые я могу идентифицировать с этой текущей проблемой (у меня есть подобная вещь в моем собственном проекте).
побитовое
Вы можете фактически исключить одну из ваших таблиц, используя битовое поле, а не объединяющую таблицу. Например, вместо хранения HasPrivilages вместе с таблицей привилегий .... Вы можете сделать это:
UsedId PrivilegeId
-------- --------------
1 1
1 2
1 3
2 2
2 3
Может равняться:
UsedId PrivilegeId
-------- --------------
1 7 (equivalent of Create, Edit and Delete)
2 6 (equivalent of Create and Delete)
Это потому, что Create = 1, Edit = 2 и Delete = 4. В совокупности они образуют одно целое число. Это можно дифференцировать с помощью побитовых операций, таких как & и | производить комбинации разрешений.
Вы бы объявили свой набор разрешений с атрибутом Flags
, например
[Flags()]
public enum Permissions {
Create = 1,
Edit = 2,
Delete = 4
}
Когда вы прочитаете значение обратно, enum вычислит фактические разрешения для вас, и вы сможете отработать его в своем приложении, выполнив такую операцию, как:
bool canEdit = ((myUser.Permissions & Permissions.Edit) == Permissions.Edit);
Если у вас есть соответствующее перечисление Permissions, выполнение .ToString()
для данного данного экземпляра фактически даст вам необходимые данные о разрешениях. Однако предпочтительно присвоить enum собственный атрибут, чтобы вы могли присвоить каждому значению лучшее имя или даже сделать его независимым от ресурса.
Форматирование для презентации
Вы, конечно, можете придерживаться того, что у вас есть, и использовать пример, который дал Тим. Перебирайте строки и, по существу, предварительно рассчитывайте текст.
Сделайте это в SQL
Иногда просто заставить SQL выполнить эту работу. Я сделал это много. Если вы просто возвращаете DataTables, а не читаете их вручную или используете LINQ, это быстрое решение.
Если вы используете SQL Server 2005 или выше, вы можете использовать код, подобный следующему:
SELECT u.UserId,
u.UserName AS [Name],
(
SELECT DISTINCT Privilege + ', '
FROM Privileges p2
INNER JOIN HasPrivileges j ON j.PrivilegeId = p2.PrivilegeId
WHERE j.UserId = u.UserId
FOR XML PATH ('')
) AS [Privileges]
FROM Users u
INNER JOIN HasPrivileges h ON h.UserId = u.UserId
GROUP BY u.UserId, UserName
Это выводит:
UserId Name Privileges
------- ----- -----------
1 Mike Create, Delete, Edit,
2 Paul Delete, Edit,
Это все еще не идеально. Вам нужно будет загрузить это во временную таблицу и удалить последний символ "," из конца каждого столбца привилегий или сделать это в коде C #.
В любом случае, я подумал, что я предложу несколько альтернатив, Том.