How to use in my application a SELECT statement that must return more than one record to show multiple values for a certain field (m:m relation)

前端 未结 3 1697
长情又很酷
长情又很酷 2021-01-27 10:50

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           


        
相关标签:
3条回答
  • 2021-01-27 11:08

    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.

    0 讨论(0)
  • 2021-01-27 11:18

    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)

    0 讨论(0)
  • 2021-01-27 11:21

    Ok there are 3 points I can identify with this current problem (I've got a similar thing in my own project).

    Bitwise

    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.

    Formatting for presentation

    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.

    Do it in SQL

    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.

    0 讨论(0)
提交回复
热议问题