4

I'm using EF 6.0 and code-first approach. I have problem with create and update data in db via Entity Framework. I'm not sure if I need to make db.Groups.Attach(student.Group) before storing Student. Without this after saving Student I also have new Group with the same Name but other GroupId.

Moreover I can't update student because I'm getting exception: The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

public class Student {
    [Key]
    public int StudentId {get; set;}
    public string Name {get; set;}
    public Group Group {get; set;}
}
public class Group {
    [Key]
    public int GroupId{ get; set;}
    public string Name {get; set;}
    public virtual ICollection<Student> Students {get; set;}
}

.

public class StudentDao {
    public void createStudent(Student student) {
        using (var db = new StorageContext()) {
            // without this also creates new Group.
            db.Groups.Attach(student.Group);    
            db.Students.Add(student);
            db.SaveChanges();
        }
    }

    public void updateStudent(Student student) {
        using (var db = new StorageContext()) {
            var original = db.Students.Find(student.StudentId);
            if (original != null) {
                original.Name = student.Name;
                original.Group =  student.Group;
                db.SaveChanges();   //exception
            }
        }
    }
}
WojciechKo
  • 1,511
  • 18
  • 35

2 Answers2

2

Without this (db.Groups.Attach(student.Group)) after saving Student I also have new Group

That's because Adding an entity to a DbSet marks all adhering entities that are not yet tracked by the context as Added. This is an EF feature, like it or not, so you have to first attach the entities you don't want to re-insert.

Moreover I can't update student because I'm getting exception

For some reason, in the update method the student and its group are still attached to a context. Apparently, there is some other context active in the StudentDao class. You have to make sure this context's lifespan is over when you update the student or else (second best) detach the student and the group from it.

An off-topic advice: if you can, abandon this DAO pattern. EF works much better when you use the DbContext and its DbSets in service-like methods that handle one unit of work. With these DAO's it's impossible to work transactionally and they cause piles of repeated code.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
  • Thanks for reply. What do you mean by "Using DbContext and its DbSets in service-like methods"? Do you mean to have one dbcontext in a class? Can you elaborated to refer to an article? – Amir Nov 01 '16 at 12:40
-1

Been a while since I worked on Entity but from what I remember you can't just change the Group, you have to give it a GroupID field as well, change that instead and then reload/update the Student object from the database so that the Group object gets loaded and assigned from within the same context.

This is just one of the reasons I use NHibernate.

Mark Feldman
  • 15,731
  • 3
  • 31
  • 58