Прежде всего, я предполагаю, что вы знаете, что классная комната уже существует в базе данных. Самый простой подход - сначала запросить его. Причина, по которой вы фактически вставили новую запись ClassRoom
, заключается в том, что вы используете ctx.AddToClassRooms(classRoomEntry)
. Это присоединяет сущность к контексту и устанавливает EntityState
в Added
.
private void UpdateClassRoom(ClassRoomDto classRoomDto)
{
using (var ctx = new TrainingContext())
{
ClassRoom classRoomEntity = ctx.
ClassRooms.
Include("Students").
Single(c => c.ClassID == classRoomDto.ClassId);
classRoomEntity.ClassName = classRoomDto.ClassName;
foreach (var studentDto in classRoomDto.Students)
{
if (studentDto.StudentId == 0)
{
// it's a new student add it to the classroom
Student student = new Student
{
StudentID = studentDto.StudentId,
StudentName = studentDto.StudentName
};
classRoomEntity.Students.Add(student);
}
else
{
// Student exists in the DB, but you don't know whether it's
// already part of the student collection for the classroom
Student student = classRoomEntity.
Students.
FirstOrDefault(s => s.StudentID == studentDto.StudentId);
if (student == null)
{
// this student is not in the class, fetch it from the DB
// and add to the classroom
student = ctx.
Students.
SingleOrDefault(s => s.StudentID == studentDto.StudentId)
classRoomEntity.Students.Add(student);
}
// Update name
student.StudentName = studentDto.StudentName;
// Since student is now part of the classroom student collection
// and classroom IS attached => student is also attached
}
}
ctx.SaveChanges();
}
}
Чтобы удалить ученика из класса, вам нужно просто удалить его из коллекции (но НЕ звоните ctx.DeleteObject()
, так как это удалит ученика из БД. В этом случае приведенный выше код не позаботится об этом, поскольку он только добавляет новых студентов. Вместо того, чтобы сопоставлять всех студентов, которые есть в базе данных, но не в вашем DTO, вы можете использовать более простой подход. Сначала очистите список, а затем добавить студентов:
private void UpdateClassRoom(ClassRoomDto classRoomDto)
{
using (var ctx = new TrainingContext())
{
ClassRoom classRoomEntity = ctx.
ClassRooms.
Include("Students").
Single(c => c.ClassID == classRoomDto.ClassId);
classRoomEntity.ClassName = classRoomDto.ClassName;
classRoomEntity.Students.Clear();
foreach (var studentDto in classRoomDto.Students)
{
Student student;
if (studentDto.StudentId == 0)
{
// it's a new student add it to the classroom
student = new Student
{
StudentID = studentDto.StudentId,
StudentName = studentDto.StudentName
};
}
else
{
student = ctx.
Students.
SingleOrDefault(s => s.StudentID == studentDto.StudentId)
// Update name
student.StudentName = studentDto.StudentName;
}
classRoomEntity.Students.Add(student);
}
ctx.SaveChanges();
}
}
Это, вероятно, подход, который вы ищете. Я специально написал первый фрагмент кода, чтобы показать вам различные случаи того, как обращаться с новыми и существующими сущностями, но это второй (более простой) подход, который является более правильным. Надеюсь, это поможет.