Удалить / обновить многие для многих Entity Framework.Не могу заставить его работать - PullRequest
6 голосов
/ 23 ноября 2010

Я использую EF4 и у меня проблемы со многими для многих обновления и удаления элемента. Я доволен вставкой, но обновить и удалить не могу понять.

Предположим, у меня есть 3 таблицы и 3 класса dto, которые соответствуют

  1. Таблица ClassRoom

       ClassID-ClassName 
    
  2. Стол ученический

       StudentID-StudentName
    
  3. Стол ученического класса

       StudentID-ClassID
    
    
    ///Happy all works I am using existing students to populate the class. Fine.
    private void InsertClassRoom(ClassRoomDto classRoomDto)
    {
        using (var ctx = new TrainingContext())
        {
            //Convert dto to Entity
            var classRoomEntity = new ClassRoom { ClassID = classRoomDto.ClassId, ClassName = classRoomDto.ClassName };
            foreach (var studentInClass in classRoomDto.Students)
            {
                Student student = ctx.Students.Where(x => x.StudentID == studentInClass.StudentId).SingleOrDefault();
                classRoomEntity.Students.Add(student);
            }
            ctx.AddToClassRooms(classRoomEntity);
            ctx.SaveChanges();
        }
    }
    

Но у меня есть 2 сценария, которые не могут понять, что делать.

  1. Обновление названия класса
  2. Добавить 1 ученика
  3. Обновить имя на 1 ученика

Удалить ученика из класса.
Как мне это сделать?

Это моя попытка обновления:

private void UpdateClassRoom(ClassRoomDto classRoomDto)
{
    using (var ctx = new TrainingContext())
    {
        var classRoomEntity = new ClassRoom { ClassID = classRoomDto.ClassId, 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
            {
                //Alter name of the student
                Student student = ctx.Students.Where(x => x.StudentID == studentDto.StudentId).SingleOrDefault();
                //update name
                student.StudentName = studentDto.StudentName;
                //? what do I do finish this attach or ???
           }
        }
        ctx.AddToClassRooms(classRoomEntity);
        ctx.SaveChanges();
    }
}

public void DeleteStudent(ClassRoomDto classRoomDto)
{
    using (var ctx = new TrainingContext())
    {
        //lost on how to delete a student in  many to many 
    }
}

1 Ответ

11 голосов
/ 24 ноября 2010

Прежде всего, я предполагаю, что вы знаете, что классная комната уже существует в базе данных. Самый простой подход - сначала запросить его. Причина, по которой вы фактически вставили новую запись 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();
    }
}

Это, вероятно, подход, который вы ищете. Я специально написал первый фрагмент кода, чтобы показать вам различные случаи того, как обращаться с новыми и существующими сущностями, но это второй (более простой) подход, который является более правильным. Надеюсь, это поможет.

...