I don\'t know if you got what I mean, but I\'ll try to explain it with an example.
Users Table
UsedId UserName
-------- ----------
1 Mike
2
Ikashef, as Tomalak said, suppressing the repeating name from each of the name/permissions rows is a "presentation-layer" issue, i.e. how you display data to your users.
What you want to do is look at ADO.NET DataTable to get these rows back:
Joe 1
Joe 7
Joe 8
Tom 3
Tom 7
Tom 8
The DataTable has a Rows property, which contains a collection of rows. You can iterate over (i.e. visit in turn) each DataRow in the Rows collection. So read up on ADO.NET DataTable object and on collections classes and on the "for each" syntax.
You have ASP.NET and C# in your tags. Considering that what you intend to do is a presentational issue, do it in the presentation layer (i.e. with C#) and not in the data layer (i.e. with SQL). That's a lot easier, too.
For example, like shown here: Use LINQ to concatenate multiple rows into single row (CSV property)
Ok there are 3 points I can identify with this current problem (I've got a similar thing in my own project).
You can virtually eliminate one of your tables by using a bitfield as opposed to a join table. For example, rather than storing the HasPrivilages along with a privileges table.... You can do this:
UsedId PrivilegeId
-------- --------------
1 1
1 2
1 3
2 2
2 3
Could equate to:
UsedId PrivilegeId
-------- --------------
1 7 (equivalent of Create, Edit and Delete)
2 6 (equivalent of Create and Delete)
This is because Create = 1, Edit = 2 and Delete = 4. Combined, they form a single integer number. This can be differentiated using Bitwise operations, like & and | to produce combinations of permissions.
You'd declare your set of permissions, with the Flags
attribute like
[Flags()]
public enum Permissions {
Create = 1,
Edit = 2,
Delete = 4
}
When you read the value back, the enum will calculate the actual permissions for you, and you can work it out in your application by doing an operation such as:
bool canEdit = ((myUser.Permissions & Permissions.Edit) == Permissions.Edit);
If you have the appropriate Permissions enum, doing a .ToString()
on that given instance will actually give you the permissions data you require. It is however preferable to give the enum an custom attribute so you can give each value a better name, or even make it language independent from a resource.
You can of course stick with what you've got, and use the example Tim has given. Iterate over the rows and essentially precalculate the text.
Sometimes it's just easier to get SQL to do the work. I've done this a lot. If you're just getting DataTables back as opposed to reading them manually or using LINQ, this is a quick fix. If you're using SQL Server 2005 or above, you can use code similar to:
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
This outputs:
UserId Name Privileges
------- ----- -----------
1 Mike Create, Delete, Edit,
2 Paul Delete, Edit,
This still isn't perfect. You'd have to load this into a temp table and strip the final "," char off the end of each Privileges column, or do it within your C# code.
Anyway just thought I'd offer some alternatives, Tom.