views:

109

answers:

2

So I'm starting out with EF on my website (C#) and Ive run into a bit of a snag. A user can either create or modify data and they will do that with the selection screen (page 1). If a user selects to create new data, I will perform the following code:

Program newProg = new Program();
using (DatabaseEntities context = new DatabaseEntities())
{
Guid id = new Guid(list.SelectedValue);
var itemString = from item in context.Set where item.Id == id select item;
Item selectedItem = itemString.ToList()[0];
newProg.Items.Add(selectedItem);
context.AddToProgramSet(newProg);
context.Detach(newProg);
}

Pretty much creating a new instance of the 'Program' which will be passed along each user control until the user is ready to submit to the database. At that point the following code will be executed:

   using (DatabaseEntities context = new DatabaseEntities())
   {
        context.AddToProgramSet(this.SummaryControl.SelectedProgram);
        context.SaveChanges();
   }

Unfortunately when I get there, I receive the following message:

The object cannot be added to the ObjectStateManager because it already has an EntityKey. Use ObjectContext.Attach to attach an object that has an existing key.

at this line:

context.AddToProgramSet(this.SummaryControl.SelectedProgram);

Also, when I add the following line prior to the previous:

context.Attach(this.SummaryControl.SelectedProgram);

I get this error:

An object with a null EntityKey value cannot be attached to an object context.

Any help would be greatly appreciated. Thanks.

+1  A: 

The root cause of this error is that you are attempting to add an Entity as a new Entity that already has its primary key set.

At what point do you add the Entities to your SummaryControl? Your first code snippet shows you adding the Entity:

...
newProg.Items.Add(selectedItem);
context.AddToProgramSet(newProg);
context.Detach(newProg);
...

Then you appear to add it again:

using (DatabaseEntities context = new DatabaseEntities())
   {
        context.AddToProgramSet(this.SummaryControl.SelectedProgram);
        context.SaveChanges();
   }

If newProg and this.SummaryControl.SelectedProgram are the same Entity, you've attempted to add it twice. Remove the context.AddToProgramSet(newProg); from the first snippet, do you work on the Entity, then add it to the ProgramSet.

Dave Swersky
Dave, Thank you for responding. I commented out the first AddToProgramSet(newProg) and I receive the same error as before.
dangerisgo
What I'm trying to do is create a new instance of a row (Program in my case) in the Selection page, pass it through the user controls, populating it along the way, then when they reach the final page, it takes the populated row, and pushes it to the db.
dangerisgo
I'm working with DangerIsGo. Could the problem be caused by the fact that we are using a GUID to identify our entity? I have the default constructor set to give the Entity a new GUID for the ID. Could that be causing the problem too?
phsr
@phsr: That is definitely a problem. The EF will assume the identity is coming from the database and will not expect the ID to be set when SaveChanges() is called. If you're using SQL 2005 or greater, set the ID in the table to uniqueidentifier and you should be in good shape.
Dave Swersky
A: 

Dave is right that the root cause is that the entity already has a primary key.

One thing that you do not show in your code is how:

Program newProg = new Program();

Becomes:

this.SummaryControl.SelectedProgram

One way that you could fix it is by saving newProg to the database before you start adding Items to it.

Shiraz Bhaiji