How to delete a list of objects in EF6 when the object is detached from the context

拜拜、爱过 提交于 2019-12-10 14:24:07

问题


OK I can delete a single item in EF6 like this:

public void DeleteUserGroup(MY_GROUPS ug)
{
    using (var context = new MYConn())
    {
        var entry = context.Entry(ug);
        if (entry.State == EntityState.Detached)
        {
            context.MY_GROUPS.Attach(ug);
        }

        context.MY_GROUPS.Remove(ug);
        context.SaveChanges();
    }
}

If this method changed from passing a single instance of MY_GROUPS to a List<MY_GROUPS> how would I handle the delete?

Would there be a more efficient way then just doing a foreach and setting the state one at a time?

UPDATE: I am already using a similar method as above utilizing the RemoveRange method. However I am getting an error:

The object cannot be deleted because it was not found in the ObjectStateManager.

I'm looking for the best way to attach a list of objects to the context so that I can delete them.


回答1:


To be able to remove records, you need to make sure your ObjectContext is tracking them. Right now you have detached objects, and your context has no knowledge of them so it's impossible to delete them. One way to remove them is to do like you say, Attach all your objects to the context, then delete them. The other way is to fetch the records from the database so you can remove them:

//Find all groups in database with an Id that is in your group collection 'ug'
var groups = context.My_Groups.Where(g => ug.Any(u => u.Id == g.Id));
context.My_Groups.RemoveRange(groups);
context.SaveChanges();

However, note that even while using RemoveRange, a delete command will be send to the database per item you want to remove. The only difference between RemoveRange and Remove is that the first will only call DetectChanges once, which can really improve performance.




回答2:


You can use RemoveRange:

context.MY_GROUPS.RemoveRange(context.MY_GROUPS.Where(x => x.columnName== "Foo"));

You can also use ForEach like this:

context.MY_GROUPS.Where(x => x.columnName == "Foo").ToList().ForEach(context.DeleteObject);
context.SaveChanges();

You could also use ObjectContext.ExecuteStoreCommand Method as an another approach for this purpose.




回答3:


Iterate over your collection and set Deleted state for each

groups.ForEach(group => ctx.Entry(group).State = EntityState.Deleted);
ctx.SaveChanges();



回答4:


EntityFramework 6+ has made this a bit easier with .RemoveRange().

    public void DeleteUserGroup(List<MY_GROUPS> ug)
    {
        using (var context = new MYConn())
        {
            context.MY_GROUPS.RemoveRange(ug);
            context.SaveChanges();
        }
    }



回答5:


By using the solution provided by Alexander Deck where brands is an IEnumerable:

context.Brands.RemoveRange(context.Brands.Where(cb => brands.Any(b => b.Id == cb.Id)));

I got the following error:

Unable to create a constant value of type 'SomeCompany.SomeApp.DB.Entities.Brand'. Only primitive types or enumeration types are supported in this context.

And it was solved by converting the Brands DBSet to IEnumerable with the AsEnumerable() extension method:

context.Brands.RemoveRange(context.Brands.AsEnumerable().Where(cb => brands.Any(b => b.Id == cb.Id)));

That did the trick for me.




回答6:


I found this it worked for me. I did it in a loop before calling save changes. I wanted it to create just the delete sql command and it did.

http://www.entityframeworktutorial.net/entityframework6/delete-disconnected-entity-in-entity-framework.aspx

// disconnected entity to be deleted
var student = new Student(){ StudentId = 1 };

using (var context = new SchoolDBEntities())
{
    context.Entry(student).State = System.Data.Entity.EntityState.Deleted;    

    context.SaveChanges();
}  


来源:https://stackoverflow.com/questions/35868066/how-to-delete-a-list-of-objects-in-ef6-when-the-object-is-detached-from-the-cont

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!