Reputation: 2255
Im wanting to use Entity Framework POCO in a disconnected (from context) mode. In my scenario I'm creating a new Parent object and want to attach an existing child object to it and then save it to the db.
The code below undesirably inserts a new Course record when saving a new Student record, when instead I want the existing Course record linked to the new Student record.
How can I do this in Entity Framework where...
This page shows a database diagram that 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;
}
}
Upvotes: 8
Views: 9583
Reputation: 980
I also tried the second option it worked for me. I did like the parent->child relationship happening at an object level first and save to db. Maybe I should just remove all the relationships between the entities that EF generates and manually control this myself.
Upvotes: 0
Reputation: 6403
I believe there are few ways of accomplishing this. You can specify that course entity is unchanged rather than added, along these lines:
ctx.Entry(course).State = EntityState.Unchanged;
Or instruct your context, that you are working with existing entity:
ctx.Courses.Attach(course);
More info here: http://msdn.microsoft.com/en-us/data/jj592676.aspx
EDIT
There are some running samples from my solution, I verified they work as expected. In all cases we have Publisher record in database with ID = 2 and Name = "Addison Wesley" (irrelevant to the example, but just for good measure).
Approach 1 - Setting Entity State
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 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 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 extra property PublisherId, it has to be named according to NavigationPropertyName + 'Id" convention to be picked up by EF auotmatically:
public int PublisherId { get; set; }
public Publisher Publisher { get; set; }
I am using here EF5 Code First, but it is very similar to POCO.
Upvotes: 19
Reputation: 65491
Entity Framework does not allow relationships that cross contexts.
If you place the reading of the course and connecting the course to the student within the same using statement, it would work.
Upvotes: 0