118

I am getting this error "The object cannot be deleted because it was not found in the ObjectStateManager."

My code is:

    protected MyEntities sqlEntities;

    public virtual void Delete(TEntity entity)
    {
        System.Type t = typeof(TEntity);
        sqlEntities.DeleteObject(entity);
        sqlEntities.SaveChanges();
    }
Majid
  • 13,853
  • 15
  • 77
  • 113
Sami
  • 3,956
  • 9
  • 37
  • 52
  • 6
    Sorry there was issue in code that different datacontext object were used to fetch and delete record. – Sami Oct 17 '11 at 11:50
  • I had a bug like this: `var entity = new TEntity() { PK_ID = 23 }; sqlEntities.DeleteObject(entity);` I was trying to create a mock entity with its PK set correctly, in hopes that Entity Framework would call DeleteObject based on the PK – C. Tewalt May 27 '14 at 17:19

10 Answers10

161

It means that entity is not attached (it was not loaded by the same context instance). Try this:

protected MyEntities sqlEntities;

public virtual void Delete(TEntity entity)
{
    sqlEntities.Attach(entity);
    sqlEntities.DeleteObject(entity);
    sqlEntities.SaveChanges();
}
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 1
    Thanks Ladislav. This helped me when I had two contexts going on when deleting child data from a parent - which was called from a different context, outside of a TransactionScope. Moved the parent call inside the scope and same context and my problem was solved. – dan richardson Feb 07 '13 at 10:31
  • 1
    @Ladislav: If I use .Attach, I am getting a different error: "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." Does it mean that there are already other object instances alive preventing the delete? – Matt Sep 06 '13 at 08:56
  • 2
    @Matt: No it means that your object is already attached to another context. It cannot be attached to two at the same time. You should use the original context to delete entity. – Ladislav Mrnka Sep 06 '13 at 10:18
  • @Ladislav: Thank you, that helped me looking further - I found this question which seems to answer how to address it: [Is is possible to check if an object is already attached to a data context in Entity Framework?](http://stackoverflow.com/q/1715501/1016343). You are right, this seems to be the issue in my case. Thanks for the quick answer! – Matt Sep 06 '13 at 10:44
  • Thanks for the reminder, I had attached it when just updating a record, but not when I was deleting a record. – pinmonkeyiii May 29 '14 at 23:39
  • It worked. But why? What did attach do? I didn't actually understand _loaded by the same context instance_. – Bugs Happen Aug 25 '15 at 14:32
  • @LadislavMrnka getting error `Attaching an entity of type 'xxx' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.` to attach. – Mahbubur Rahman Jun 16 '19 at 17:18
66

Just a small clarification on the answer by Ladislav Mrnka (which should be the accepted answer).

If like me, you've got code in a format like this:

using (var context = new MyDataContext())
{
    context.MyTableEntity.Remove(EntytyToRemove);
    var nrOfObjectsChanged = context.SaveChanges();
}

..then this what you want to do:

using (var context = new MyDataContext())
{
    // Note: Attatch to the entity:
    context.MyTableEntity.Attach(EntityToRemove);

    context.MyTableEntity.Remove(EntityToRemove);
    var nrOfObjectsChanged = context.SaveChanges();
}

Perhaps this seems obvious, but it was not clear to me initially that it is necessary to specify the entity to attatch to, and not just the context.

Kjartan
  • 18,591
  • 15
  • 71
  • 96
  • 1
    I use this approach and receive exception: "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries." – kat1330 Sep 04 '14 at 18:06
12

Just to propergate on Kjartans explanation:

I had:

public Project DeleteProject(int id)
    {
        using (var context = new Context())
        {
            var p = GetProject(id);
            context.Projects.Remove(p);
            context.SaveChanges();
            return p;
        }
    }

The problem is that I used my own method (GetProject()) to get the entity (hence using another context to load the entity):

public Project GetProject(int id)
    {
        using (var context = new Context())
        {
            var project = context.Projects
                .Include(p => p.Reports.Select(q => q.Issues.Select(r => r.Profession)))
                .Include(p => p.Reports.Select(q => q.Issues.Select(r => r.Room)))
                .SingleOrDefault(x => x.Id == id);
            return project;      
        }
    }

One solution could be to attach the loaded entity as Kjartan states, another could be mine solution, to load the entity within the same context:

public Project DeleteProject(int id)
    {
        using (var context = new Context())
        {
            var p = context.Projects.SingleOrDefault(x => x.Id == id);
            if (p == null)
                return p;

            context.Projects.Remove(p);
            context.SaveChanges();
            return p;
        }
    }
esbenr
  • 1,356
  • 1
  • 11
  • 34
2

You can write this code:

var x=yourquery.FirstOrDefault(); 

sqlEntities.DeleteObject(x);
sqlEntities.SaveChanges();
Nash Carp
  • 169
  • 12
mehdi
  • 31
  • 1
  • 5
2

In case none of the above worked, you may try this solution:

context.Entry(yourObject).State = System.Data.Entity.EntityState.Deleted; context.SaveChanges();

Ala' Alnajjar
  • 788
  • 1
  • 11
  • 23
2

I know this question is quite old but none of the above worked for me since i was deleting registers from more than one class/service and each of of them was instantiating it's own database connection context.

What i did to solve it was to send the first created context to the rest of the classes/services that where going to access the database.

For example, my serviceA was going to delete some of it's registers and call serviceB and serviceC to do the same with their registers.

I would then delete my registers on serviceA and pass as a parameter the context created on the serviceA to serviceB and serviceC.

Ariel
  • 911
  • 1
  • 15
  • 40
0

You should be sure that your object is exist in the list you are trying to remove from , you should put the following condition

if(context.entity.contains(your object))

remove it.

if you have a complicated condition for equality you should override equal method in entity class to put your condition for equality , to get the right way for an extension method "entity.contains"

0

Make sure the model passing into Remove(Entity) is exactly same as the database record.

Some times its possible to pass the model with out some fields like Id or Date. keep those into @html.Hiddenfor if you posting as form.

Best way is to pass the ID and get the entity using Find(Id) method and pass that to Remove(Entity)

Hope this helps someone.

Dheeraj Palagiri
  • 1,829
  • 3
  • 23
  • 46
0

I got this problem and solve it. Just copy below code:

sqlEntities.Attach(entity);
sqlEntities.Remove(entity);
sqlEntities.SaveChanges();
vahid sabet
  • 485
  • 1
  • 6
  • 16
0

In my case there was one context , but I got entity with 'AsNoTracking' option

vborutenko
  • 4,323
  • 5
  • 28
  • 48