user2110791
user2110791

Reputation: 11

An object with the same key already exists in the ObjectStateManager

I have a scenario that could not find the solution for it and need some help How can I achieve this, I’d like to get current record for the client modify it and instead of update I’d like to add the new record to table for historical change information

    client c = new client();
    using (DBEntities db = new DBEntities())
    {
        // get current records in the client table for client
        IQueryable<client> co = from p in db.client where p.CUS_NUMBER == scd.cus_number && p.isCurrent == true select p;

        c = co.First();

        //update email and and address
        c.EMAIL = Helper.CleanInput("[email protected]");
        c.ADDRESS = Helper.CleanInput("123 Sheppard");

        //instead of updating current record I'd like to add new record to the table to keep historical changes
        db.AddToclient(c);
        db.SaveChanges();
        //I get error that 
        //An object with the same key already exists in the ObjectStateManager. 
        //The existing object is in the Modified state. An object can only be added to 
        //the ObjectStateManager again if it is in the added state.

Complete error

An object with the same key already exists in the ObjectStateManager. The existing object is in the Modified state. An object can only be added to the ObjectStateManager again if it is in the added state.

Upvotes: 1

Views: 7203

Answers (4)

Jone Polvora
Jone Polvora

Reputation: 2338

In Entity Framework, all objects retrieved from database by default are tracked by ObjectContext instance. Entity Framework internally maps all objects being tracked by his Key. This pattern is called Identity Map. This means that there will be only one instance of an entity per key. So, you don't need to call Add again, since the entity is already on EF map. You just need call SaveChanges to persist modified entities.

In your case you are:

1 - Creating a new instance of EF ObjectContext;
2 - Retrieving entities in your LINQ query;
3 - Changing values of properties of the retrieved entity;
4 - Adding again to the ObjContext; //error!
5 - Calling SaveChanges()

Step 4 is not necessary because the ObjectContext already knows about the retrieved objects.

Upvotes: 0

rhughes
rhughes

Reputation: 9593

The reason db.AddToclient(c); gives the error is because this object is being tracked by the object context, by possibly being in the database.

The best way to accomplish what you are trying to do is something like the following:

var newClient = new client()
{
    EMAIL = Helper.CleanInput("[email protected]"),
    ADDRESS = Helper.CleanInput("123 Sheppard"),
};

db.AddToclient(newClient);
db.SaveChanges();

Upvotes: 0

Rajeev Ranjan
Rajeev Ranjan

Reputation: 1036

It's look like you are adding same row to database and error is coming due to addition of same row again having same primary key which DB will not allow.

Try to add new row and make another table that keeps Historical information of old row and a reference as foreign key. You can add a boolean field that keep information regarding deletion let It is IsDeleted.

Hope It will Help Thanks

Upvotes: 0

Cris
Cris

Reputation: 13351

remove this code db.AddToclient(c); ,rest all is fine,You are already accessing the object by its reference so no need to add it again.It'll get modified when you call savechanges()

or use cloning if you want to add new object c = co.First().Clone();

Upvotes: 1

Related Questions