Как использовать в моем приложении оператор SELECT, который должен возвращать более одной записи, чтобы показать несколько значений для определенного поля (отношение m: m) - PullRequest
0 голосов
/ 12 декабря 2010

Не знаю, поняли ли вы, что я имею в виду, но я попытаюсь объяснить это на примере.

Таблица пользователей

UsedId    UserName
--------  ----------
1         Mike
2         Raul

Таблица HasPrivileges

UsedId       PrivilegeId      
--------     --------------
1            1
1            2
1            3
2            2
2            3

Таблица привилегий

PrivilegeId      Privilege
-------------    ------------
1                Create
2                Edit
3                Delete

Теперь это две таблицы пользователей и привилегий, которые имеют отношение «многие ко многим» между ними, поэтому, когда я выбираю всех пользователей, связанных с имеющимися у них привилегиями,Я получаю в этом примере 3 записи или строки в результате для Майка, каждая из которых содержит привилегию, которую он имеет.

Теперь мне нужно в моем приложении отобразить список всех пользователей с их привилегиями, но INDEED я неЯ не хочу, чтобы мои пользователи видели пользователя три раза, чтобы показать все его привилегии или что-то еще, вместо этого я хочу, чтобы он отображал

User Id : 1
Name : Mike
Privileges : Create, Edit, Delete

или что-то похожее на это!ЛЮБЫЕ ИДЕИ ПАРНИ! ??

Ответы [ 3 ]

2 голосов
/ 12 декабря 2010

Ikashef, как сказал Томалак, подавление повторяющегося имени в каждой из строк имени / разрешений - это проблема "уровня представления", то есть как вы отображаете данные для своих пользователей.

То, что вы хотите сделать, это посмотреть на ADO.NET DataTable, чтобы получить эти строки обратно:

       Joe    1
       Joe    7
       Joe    8
       Tom    3
       Tom    7
       Tom    8

DataTable имеет свойство Rows, которое содержит коллекцию строк. Вы можете перебирать (то есть посещать по очереди) каждый DataRow в коллекции Rows. Итак, ознакомьтесь с объектом ADO.NET DataTable, классами коллекций и синтаксисом «для каждого».

2 голосов
/ 12 декабря 2010

Хорошо, есть 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 #.

В любом случае, я подумал, что я предложу несколько альтернатив, Том.

1 голос
/ 12 декабря 2010

В ваших тегах есть ASP.NET и C #.Учитывая, что то, что вы намереваетесь сделать, является проблемой представления, сделайте это на уровне представления (т.е. с помощью C #), а не на уровне данных (то есть с использованием SQL).Это тоже намного проще.

Например, как показано здесь: Использование LINQ для объединения нескольких строк в одну строку (свойство CSV)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...