I m using EF4 and having problems with many to many update and delete of item. I am happy with the insert but update and delete cannot figure it out.
Suppose I have 3 tables and 3 dto classes that matches
ClassRoom Table
ClassID-ClassName
Student Table
StudentID-StudentName
StudentClass Table
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();
}
}
But I have 2 scenarios that cannot figure out what to do.
Delete a student from class.
How do I do it?
This is my attempt on update:
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
}
}
First of all, I assume that you know that the classroom already exists in the database. The simplest approach is to query for it first. The reason you actually get a new ClassRoom
entry inserted is that you use ctx.AddToClassRooms(classRoomEntry)
. This attaches the entity to the context and sets the EntityState
to 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();
}
}
In order to delete a student from thr class, you need to simply remove it from the collection (but DON'T call ctx.DeleteObject()
, since that will remove the student from the DB. In your case, the code above will not take care of this, since it only adds new students. Instead of matching all the students that are in the database, but not in your DTO, you could take a simpler approach. Clear the list first and then add the students:
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();
}
}
This is probably the approach you are looking for. I specifically wrote up the first code snippet to show you the different cases of how to deal with new and existing entities, but it's the second one (simpler) approach that is more correct. Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With