Entity Framework: adding an existing child POCO to a new Parent POCO, creating a new child in DB

I want to use Entity Framework POCO in disconnected (out of context) mode. In my scenario, I create a new Parent object and want to bind an existing child object to it and then save it in db.
The code below undesirably inserts a new course record when saving a new Student record, when instead I want the existing course record to be associated with the new Student record.

How to do it in the Entity Framework, where ...

  • objects can be disconnected from the context. (i.e. is requested in one context and then stored in another context).
  • I do not need to re-query the child entry from the database so that I can attach it to the parent when I save the db. I really want to avoid extra trips in db when I already have this as an object in memory.

This page shows a database diagram in which the code below is based on http://entityframeworktutorial.net/EF4_EnvSetup.aspx#.UPMZ4m-UN9Y

class Program { static void Main(string[] args) { //get existing course from db as disconnected object var course = Program.getCourse(); //create new student var stud = new Student(); stud.StudentName = "bob"; //assign existing course to the student stud.Courses.Add(course); //save student to db using (SchoolDBEntities ctx = new SchoolDBEntities()) { ctx.Students.AddObject(stud); ctx.SaveChanges(); } } static Course getCourse() { Course returnCourse = null; using (var ctx = new SchoolDBEntities()) { ctx.ContextOptions.LazyLoadingEnabled = false; returnCourse = (from s in ctx.Courses select s).SingleOrDefault(); } return returnCourse; } } 
+7
source share
3 answers

I believe that there are several ways to do this. You can indicate that the course object does not change, but is not added in the following lines:

 ctx.Entry(course).State = EntityState.Unchanged; 

Or instruct your context that you are working with an existing entity:

 ctx.Courses.Attach(course); 

More details here: http://msdn.microsoft.com/en-us/data/jj592676.aspx

EDIT

There are several test samples in my solution, I checked that they work as expected. In all cases, we have a publisher record in the database with ID = 2 and Name = "Addison Wesley" (not relevant to this example, but only for good measure).

Approach 1 - Setting the state of an entity

 using (var context = new Context()) { var book = new Book(); book.Name = "Service Design Patterns"; book.Publisher = new Publisher() {Id = 2 }; // Only ID is required context.Entry(book.Publisher).State = EntityState.Unchanged; context.Books.Add(book); context.SaveChanges(); } 

Approach 2 - Using the Attach Method

 using (var context = new Context()) { var book = new Book(); book.Name = "Service Design Patterns"; book.Publisher = new Publisher() { Id = 2 }; // Only ID is required context.Publishers.Attach(book.Publisher); context.Books.Add(book); context.SaveChanges(); } 

Approach 3 - Setting a Foreign Key Value

 using (var context = new Context()) { var book = new Book(); book.Name = "Service Design Patterns"; book.PublisherId = 2; context.Books.Add(book); context.SaveChanges(); } 

For this last approach to work, I needed to add an additional property PublisherId, it should be named according to the NavigationPropertyName + 'Id' convention, which should be selected by EF auotmatically:

 public int PublisherId { get; set; } public Publisher Publisher { get; set; } 

I use the EF5 code here first, but it is very similar to POCO.

+17
source

Entity Framework does not allow relationships that cross contexts.

If you put in a course reading and pair the course with the student in the same usage statement, this will work.

0
source

I also tried the second option, which worked for me. I really liked the parent-> child relationship going on at the object level and persisting in db. Perhaps I just need to remove all the relationships between the objects that EF generates and manually manage them myself.

0
source

All Articles