30

What is the best way to remove multiple records in one go with LINQ?

  • 1
    If you need to do something like `DELETE FROM table WHERE ...` then consider using SQL. LINQ may not be the best tool for this job. – Myster Jun 11 '14 at 21:36
  • The following is more for LINQ to Entities, but it may help: [https://stackoverflow.com/questions/869209/bulk-deleting-via-linq](https://stackoverflow.com/questions/869209/bulk-deleting-via-linq) – Jagd May 15 '09 at 18:51
  • LINQ doesn't delete, it only queries. Deleting records with a LINQ-based ORM is never done by a LINQ statement. All of the answers so far ignore that. Besides that, the term "in one go" is vague. None of the common LINQ-based ORMs will bulk-delete in one SQL statement. Therefore, IMO there is no "best" way, because "best" should at least be "good". LINQ-based ORMs don't even offer a "good" way to do bulk delete. – Gert Arnold Jun 01 '22 at 13:44

9 Answers9

32

To delete records with Linq2Sql

CustomerDataContext ctx = new CustomerDataContext("connection string");
var customers = ctx.Customers.Where(c => c.Name == "david");

ctx.Customers.DeleteAllOnSubmit(customers);
ctx.SubmitChanges();
David
  • 15,150
  • 15
  • 61
  • 83
  • 4
    This is one of the easiest ways but i would not say is the most efficient. There actually is not any optimization being performed. The generated SQL enumerates all objects that match your query, then manually iterates over them to delete them. See this post - http://stackoverflow.com/questions/869209/bulk-deleting-via-linq – David May 15 '09 at 18:56
  • Cannot implicitly convert type 'System.Linq.IQueryable' to 'RajrangData.tblRelatedProduct'. An explicit conversion exists (are you missing a cast? – rahularyansharma Apr 01 '13 at 13:11
  • Surely you can't store multiple `Customer` objects in one `Customer` reference... maybe you want something like: `List customers = ctx.Customers.Where(c => c.Name == "david").ToList();` – Sheridan May 10 '13 at 10:19
7

Using entity framework 6

using (EntitiesContext db = new EntitiesContext(connString))
        {
            // Retrieve all records from database for deletion
            IEnumerable<entity> entityList = db.entity.where(x => x.id == id).toList();

            // Use Remove Range function to delete all records at once
            db.entity.RemoveRange(entityList);

            // Save changes
            db.SaveChanges();
        }
Asad Ullah
  • 2,257
  • 2
  • 24
  • 23
5

Here is How I solved the problem :

try
{
    List<MaterialPartSerialNumber> list = db.MaterialPartSerialNumbers.Where(s => s.PartId == PartId && s.InventoryLocationId == NewInventoryLocationId && s.LocationId == LocationId).ToList();
    db.MaterialPartSerialNumbers.RemoveRange(list);
    db.SaveChanges();
}
catch(Exception ex)
{
    string error = ex.Message;
}

First, you can find a list of the items you want to delete.

Then, you can use the function RemoveRange(**list_of_item_to_delete**) so that it removes each instance in the list present in the database.

According to the MSDN, the method removes a range of elements from the List.

For more information, check it here https://msdn.microsoft.com/en-us/library/y33yd2b5(v=vs.110).aspx

General Grievance
  • 4,555
  • 31
  • 31
  • 45
4

The good old SPROCs.....

You can drag the SPROC to your DBML file and it will generate a rich method in your databasecontext class.

Khurram Aziz
  • 1,480
  • 5
  • 15
  • 24
3

Removing many records based on single where clause

context.EntityModel
            .RemoveAll(r => r.property == "propertyEntered");

But you could also Remove records from the database that don't exist in List<ListOfBadRecords>

context.EntityModel
            .Where(w => w.propertyID == ID).ToList()
            .RemoveAll(r => !ListOfBadRecords.Any(a => a.anyID == r.propertyID ));

Edit:

Unsure wich is quicker but you could do the 2nd query with this also

.RemoveAll(r => !ListOfBadRecords.Select(s=>s.propertyID ).Contains(w.propertyID ))

Edit2: don't forget context.SaveChanges(); as i did in the first draft

Don Thomas Boyle
  • 3,055
  • 3
  • 32
  • 54
1

This is what I used, first create an IENumerable object of the table where are the records to be removed are, then just use RemoveRange, and finally just save changes to database. Let's say you want to remove all products from one specific supplier ID on the Products table, this is how you could do that.

IEnumerable<Products> ProductsToRemove= db.Products.Where(x => x.SupplierId== Supplierid);
db.Products.RemoveRange(ProductsToRemove);
db.SaveChanges();
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Cesar Duran
  • 377
  • 3
  • 8
0

I agree with Khurram, it's much more efficient to do this with a simple stored procedure with LINQ (provided you have sufficient permissions in SQL to do this). I'll augment this with an example.

The stored procedure:

CREATE PROCEDURE [dbo].[RemovePermissionsFromRole] 
(
    @ROLE_ID int
)
AS
BEGIN
    SET NOCOUNT ON;

    DELETE FROM [RolePermissions] WHERE [RoleID] = @ROLE_ID;
END

Drag the stored procedure from the database explorer onto the methods pane in your DBML file. Save the file. And in code:

if (Request.QueryString["RoleID"] != null) {
    int roleID = Convert.ToInt32(Request.QueryString["RoleID"]);

    SETSDataContext context = new SETSDataContext();
    context.RemovePermissionsFromRole(roleID);
}
Brandon Ward
  • 143
  • 3
  • 7
0

maybe its litle late for this answer but today I ran into this demand myself I and I came up with this solution

CustomerDataContext ctx = new CustomerDataContext("connection string");

ctx.Customers.DeleteAllOnSubmit(ctx.Customers.Where(c => c.Name == "david"));

ctx.SubmitChanges();
Jonuz
  • 139
  • 8
  • 4
    Surely you can't claim to have 'come up' with that solution when all you did was move the declaration of `cust` from the most popular answer to the `DeleteAllOnSubmit` method. – Sheridan Jul 18 '12 at 13:54
0

With just Entity Framework I found this to be the tightest code.

db.PreperProperties.RemoveRange(db.PreperProperties.Where(c => c.preperFk == prpr.id));
db.SaveChanges();
pat capozzi
  • 1,412
  • 1
  • 20
  • 16