Reputation: 6022
Let's assume that the below method lives in a WCF service. The UI retrieved an instance of the Status object, and makes a subsequent call to the service using this method. Instead of assigning the status to the user as I would expect, it attempts to insert the status. What am I doing wrong?
void Method(Status status)
{
//not sure if this is even needed, the status never changed
context.Statuses.ApplyChanges(status);
//get the first user from the database
User user = context.Users.Where(u => u.Id = 1).First();
//set user status to some existing status
user.Status = status;
//this throws an exception due to EF trying to insert a new entry
//into the status table, rather than updating the user.StatusId column.
context.SaveChanges();
}
Upvotes: 0
Views: 718
Reputation: 675
Have to write an answer because I can't yet comment on another answer (rep score < 50) [something weirdly not right about that, but I get why it's like that] because I wanted to add some clarity to @Ladislav's answer.
The Status
object coming in from the WCF call did not come from the same context
you are using to find the User
object, so the tracking code is not fixed up with that context. This is why attaching it will allow you to save the assignment without the context
thinking that status
is a new entity requiring an insert into the database.
Upvotes: 0
Reputation: 364249
The problem is that you are working with attached user. When the STE is attached to the context it behaves exactly in the same way as any other entity. More over its self tracking mechanism is not activated. So you must attach the status to the context before you set it to the user or it will be tracked as a new entity which has to be inserted:
void Method(Status status)
{
User user = context.Users.Where(u => u.Id = 1).First();
context.Attach(status);
user.Status = status;
context.SaveChanges();
}
Upvotes: 1
Reputation: 8152
Try this instead:
using (Entities ctx = new Entities())
{
ctx.Statuses.Attach(status);
ObjectStateEntry entry = ctx.ObjectStateManager.GetObjectStateEntry(status);
entry.ChangeState(EntityState.Modified);
//get the first user from the database
User user = ctx.Users.Where(u => u.Id = 1);
//set user status to some existing status
user.StatusID = status.StatusID;
ctx.SaveChanges();
}
Here's a tutorial on CRUD with Entity Framework if you're interested.
Upvotes: 1