Linq to SQL, многие ко многим дизайн - PullRequest
1 голос
/ 01 марта 2011

Я пытаюсь взять объект и спроектировать таблицу SQL для его хранения. У объекта есть член с именем «Roles», который является перечислением, имеющим 4 значения. Каждый объект может иметь несколько разных ролей.

Прямо сейчас я взял перечисление и создал из него таблицу с одноименным именем SQL и добавил в нее 4 роли. Сейчас я пытаюсь создать таблицу объектов и не могу понять, как заставить отношения многих ко многим работать на нее. Я также хотел бы, чтобы он хорошо работал с Linq-to-SQL. Было бы неплохо сохранить перечисление, но если бы не массив строк, он также мог бы работать.

Короче говоря, мне нужна таблица, которая имеет множество-множество между ролями и Object.Roles (или Object.Roles [])

Спасибо!

Ответы [ 2 ]

9 голосов
/ 01 марта 2011

Как правило, отношения «многие ко многим» в Linq2SQL (и Entity Framework) создаются путем введения таблицы ассоциации , содержащей только первичные ключи из двух таблиц, которые вы хотите связать, и места каждой строки. соответствует ассоциации.

Поскольку ваши Role и Object.Role могут быть трудно разделить в попытке объяснить это, я приведу другой пример: в школе у ​​каждого учителя может быть много учеников, и у каждого ученика может быть много учителей. , Структура таблицы для представления этого будет тогда

Teachers                    Students                     StudentTeacherRelations
********                    ********                     ***********************
TeacherId                   StudentId                    TeacherId
FirstName                   FirstName                    StudentId
etc...                      etc...

Теперь Linq2SQL и EF достаточно умны, чтобы распознавать это как отношение «многие ко многим» и вводить навигационные свойства в вашей модели. POCO с соответствующими свойствами для объекта Student может выглядеть следующим образом:

public class Student
{
    public int StudentId { get; set; }
    public string FirstName { get; set; }
    // etc
    public IEnumerable<Teacher> Teachers { get; }
}

Если это настроено правильно, преобразователь O / R автоматически заполнит свойство Teachers.

Обновление: В ответ на комментарии, вот как я структурировал бы остальную часть базы данных, если бы я хотел включить сценарий, в котором каждый учитель может дать некоторым ученикам домашнюю работу, состоящую из ряда вопросов. :

HomeworkAssignments          Questions                      Answers
*******************          *********                      *******
HomeworkAssignmentId (pk)    QuestionId (pk)                AnswerId (pk)
...                          HomeworkAssignmentId (fk)      QuestionId (fk)
                             ...                            StudentId (fk)
                                                            ...

StudentHomeworkAssignmentRelations    TeacherHomeworkAssignmentRelations
**********************************    **********************************
StudentId (fk)                        Teacherid (fk)
HomeworkAssignmentId (fk)             HomeworkAssignmentId (fk)

Как видите, здесь довольно много таблиц. Однако эта структура позволяет каждому учителю создавать множество домашних заданий, а затем раздавать каждое задание нескольким студентам. У вас будет навигационное свойство Student.HomeworkAssignments типа IEnumerable<HomeworkAssignment>, с помощью которого вы сможете найти все вопросы, на которые должен ответить студент. Для каждого опубликованного ответа вы сохраняете строку в таблице Answers, которая связана как с вопросами, так и со студентами отношениями «один ко многим» - каждый ответ может принадлежать только одному вопросу и предоставляться только одним студентом.

Ключевым моментом здесь является то, что вам не нужно иметь доступ к каждому ответу, предоставленному студентом напрямую - и в Linq2SQL, и в EF можно запрашивать данные из многих таблиц одновременно различными способами. Одним из таких способов является

var answersToTheLastExam = context.Students
                  .SelectMany(s => s.HomeworkAssignments)
                  .OrderBy(ha => ha.Date) // this might need modifying to get the last one first
                  .First(ha => ha.Questions.Count() > 0)
                  .SelectMany(ha => ha.Questions)
                  .SelectMany(q => q.Answers)
                  .Where(a => a.StudentId == myId)

Обратите внимание, что этот код не проверен и может работать не так, как я говорю. Я просто стараюсь изо всех сил с моей головы здесь =)

0 голосов
/ 18 января 2019

Роли Идентификатор ПК

ObjectRoles Идентификатор ПК

ObjectRoleRoles RolesId Pk & FK ObjectRolesId PK & FK

           var result = (from orr in _context.ObjectRoleRoles
                         inner join r in _context.Roles on orr.RolesId equals r.Id
                         inner join or in _context.ObjectRoles on orr.ObjectRolesId equals or.Id
                         where orr.RolesId equals 1
                         select r).ToList();

Поля в ObjectRoleRoles должны быть как PK, так и FK.

...