Вот уже пару дней я ломаю голову и отыскиваю Interwebz для получения информации о том, как вставить данные в таблицы пересечения баз данных с помощью Entity Framework (EF). Я посещал все сайты и блоги основных игроков, и ни один из них не предоставил прямой синтаксис о том, как это сделать. Внезапно ответ пришел ко мне, и я был обязан и решил поделиться этим с как можно большим количеством людей, чтобы уменьшить боль, которую я пережил.
Давайте подготовим почву. Предположим, у нас есть связь с базой данных как таковая:
Студенты (StudentID (PK), StudentName, Gender)
Курсы (CourseID (PK), CourseName, CourseDescription)
Студенческие курсы (StudentID (PK, FK), CourseID (PK, FK))
Для тех из вас, кто достаточно знаком с EF, вы знаете, что когда вышеприведенные отношения преобразуются в модель данных сущностей, таблицы «Студенты» и «Курсы» создаются как сущности, а таблица «Студенты» - нет. Это связано с тем, что таблица StudentsCourses не содержит никаких атрибутов, кроме ключей из двух других таблиц, поэтому EF напрямую отображает отношение «многие ко многим» между студентами и курсами (EF не ограничен в этом отношении реляционными базами данных). .) и вместо сущности переводит таблицу пересечений в AssociationSet. Если вы не знали об этом, ознакомьтесь с приведенными ниже примерами:
http://thedatafarm.com/blog/data-access/inserting-many-to-many-relationships-in-ef-with-or-without-a-join-entity/
http://weblogs.asp.net/zeeshanhirani/archive/2008/08/21/many-to-many-mappings-in-entity-framework.aspx
Теперь давайте предположим, что вы хотите зарегистрировать текущего студента (ID: 123456) для новых курсов в этом семестре (ENGL101, SOC102 и PHY100). В этом случае мы хотим вставить новые записи в таблицу StudentsCourses, используя существующую информацию в таблицах Students и Courses. Работать с данными из любой из этих таблиц легко, поскольку они оба являются сущностью в модели, однако вы не можете напрямую обращаться к таблице StudentsCourses, поскольку она не является сущностью. Ключ к этой дилемме лежит в свойствах навигации каждого объекта. Сущность Student имеет свойство навигации к сущности Course и наоборот. Мы будем использовать их для создания «записей ассоциаций», как я их называю.
Вот пример кода для связи существующего студента с существующими курсами:
using (var context = TheContext())
{
Student st = context.Students.Where(s => s.StudentID == “123456”).First();
st.Courses.Add(context.Courses.Where(c => c.CourseID == “ENGL101”).First());
st.Courses.Add(context.Courses.Where(c => c.CourseID == “SOC102”).First());
st.Courses.Add(context.Courses.Where(c => c.CourseID == “PHY100”).First());
context.Students.AddObject(st);
context.SaveChanges();
}
Поскольку ассоциации идут обоими способами, вполне понятно, что можно извлечь три объекта курса (по CourseID) и связать один и тот же объект Student с каждым, но я сам не проверял это. Я думаю, что это приведет к большему количеству кода, чем это необходимо, и может быть семантически запутанным.
Вот пример кода, который связывает нового учащегося с теми же существующими курсами:
using (var context = TheContext())
{
Student st = new Student({ StudentID = “654321”, StudentName = “Rudolph Reindeer”,
Gender = “Male” });
st.Courses.Add(context.Courses.Where(c => c.CourseID == “ENGL101”).First());
st.Courses.Add(context.Courses.Where(c => c.CourseID == “SOC102”).First());
st.Courses.Add(context.Courses.Where(c => c.CourseID == “PHY100”).First());
context.Students.AddObject(st);
context.SaveChanges();
}
И, наконец, вот код, связывающий нового студента с новыми курсами (для краткости используется «...»):
using (var context = TheContext())
{
Student st = new Student({ ... });
st.Courses.Add(new Course({ ... }));
st.Courses.Add(new Course({ ... }));
st.Courses.Add(new Course({ ... }));
context.Students.AddObject(st);
context.SaveChanges();
}