Связь "много ко многим" с таблицей соединений в Entity Framework?


Я пытаюсь создать отношение "многие ко многим" в Entity Framework (сначала код), согласно следующему сообщению: Проектирование базы данных для ограниченного числа вариантов в MVC и Entity Framework?

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

Введите описание изображения здесь

Суть таблицы переходов в том, что мне нужно иметь дополнительное свойство Level в Таблице переходов. отношения, поэтому я не могу просто пойти на прямые отношения между консультантом и программой. Я добавил сущность ConsultantProgramLink вручную в конструкторе, а затем добавил ассоциации к программе и консультанту соответственно, выбрав добавить FK для каждого, а затем сделал их оба первичными ключами. Но когда я делаю это так, это не работает, как я ожидал:

Если бы я провел прямую ассоциацию между консультантом и программой, я мог бы ссылаться, скажем, на консультанта.Программы в мой код. Но теперь это не работает с соединительным столом. Есть ли какой-либо способ исправить это, или я всегда должен проходить через свойство соединения (консультант.Консультантпрограммлинк.Программы)? В любом случае, даже если я попытаюсь пройти через свойство перехода, это не поможет. Я могу быть консультантом.ConsultantProgramLink в моем коде, но другая точка не дает мне навигационного свойства программы (которая почему-то тоже стала просто программой, почему? Могу ли я просто переименовать их, если я в конечном итоге получу доступ к ним вообще?).

Так что же я делаю не так? Почему я не могу получить доступ к свойствам через точечные обозначения в моем коде?

1 7

1 ответ:

Как только вы моделируете таблицу соединений как сущность, вы действительно теряете прямое отношение "многие ко многим" между Consultant и Program. Вот как это работает. У вас будет либо прямое отношение "многие ко многим", либо дополнительные свойства в таблице соединений. Только не оба. Если вы хотите оба, вы можете попробовать создать пользовательское СВОЙСТВО Programs на Consultant и использовать запрос linq для получения связанных программ:

public IEnumerable<Program> Programs
{
    get
    {
        return this.ConsultantProgramLinks.Select(l => l.Program);   
    }
}
Этот пример также является объяснением вашей последней проблемы. Вы не можете иметь свойство Program на ConsultantProgramLink, потому что это совокупность связанных сущностей, а не одна сущность (ее следует называть ConsultantProgramLinks). Свойство в сущности ConsultantProgramLink называется просто Program, потому что оно представляет собой единичную сущность, а не коллекцию.

Правка:

Если вам нужно, чтобы каждый Program был автоматически связан с каждым Consultant, вы должны применить его, когда собираетесь создать новый Program. Наличие таблицы соединений, выставленной как отдельная сущность, вероятно, позволит вам легко достичь ее:

var program = new Program();
...
context.Programs.AddObject(program);

var ids = from c in context.Consultants
          select c.Id;

foreach (var id in ids)
{
    var link = new ConsultantProgramLink
        {
            ConsultantId = id,
            Program = program
        };
    context.ConsultantProgramLinks.AddObject(link);
}

context.SaveChanges();

Если вы добавите новый Consultant, вам придется создавайте ссылки на все программы одним и тем же способом.

Недостатком является то, что если у вас есть, например, 1000 консультантов, эта конструкция создаст 1001 вставку базы данных, где каждая вставка будет выполняться в отдельном цикле к базе данных. Чтобы избежать этого, единственный вариант-использовать хранимую процедуру или триггер в таблице программ.