entity-framework-eliminar-registros

Deleting Data in Entity Framework

  • 3 min

In Entity Framework, deleting records is one of the fundamental CRUD operations, and the last one we have left to cover.

Deleting records involves removing existing entities from the database (obviously,😊). For this, Entity Framework provides the Remove and RemoveRange methods.

As with the other operations, when we delete a record from the DbContext, these do not execute immediately in the database.

Instead, EF marks them for deletion. Changes will take effect in the database when we invoke the SaveChanges method.

Deleting records with Remove

The Remove method is used to delete a single record from the database. This method marks the entity as “deleted” in the context,

DbContext.Remove(entity);

Let’s assume we have a Product entity and we want to delete a specific product from the database:

using (var context = new MyContext())
{
    // Find the product to delete
    var product = context.Products.Find(1); // Let's assume the ID is 1

    if (product != null)
    {
        // Mark the product for deletion
        context.Products.Remove(product);

        // Apply the changes to the database
        context.SaveChanges();
    }
}

In this example:

  1. We look for the product with ID 1 using the Find method.
  2. If the product exists, we mark it for deletion with Remove.
  3. Finally, we call SaveChanges to apply the deletion in the database.

Multiple deletion with RemoveRange

The RemoveRange method is an extension of Remove that allows deleting multiple records at once.

This is useful when we need to delete a collection of entities, as it reduces the number of database operations.

DbContext.RemoveRange(entities);

Let’s assume we want to delete all products that have a price less than 10:

using (var context = new MyContext())
{
    // Find the products to delete
    var cheapProducts = context.Products
                                .Where(p => p.Price < 10)
                                .ToList();

    if (cheapProducts.Any())
    {
        // Mark the products for deletion
        context.Products.RemoveRange(cheapProducts);

        // Apply the changes to the database
        context.SaveChanges();
    }
}

In this example:

  1. We use LINQ to filter products with a price less than 10.
  2. If there are products that meet the condition, we mark them for deletion with RemoveRange.
  3. We call SaveChanges to apply the deletion in the database.

Like AddRange, DeleteRange can reduce the number of queries to the database.

But it is not a bulk operation. That is, performance is still improvable 😅

Common cases

Cascading deletion

Entity Framework supports cascading deletion, which means that if an entity has relationships with other entities, these can also be deleted automatically. This is configured using the Fluent API or Data Annotations.

modelBuilder.Entity<Product>()
            .HasMany(p => p.OrderDetails)
            .WithOne(d => d.Product)
            .OnDelete(DeleteBehavior.Cascade);

For example, if a Product has a 1relationship with OrderDetails, and we configure cascading deletion, when we delete a product, all its order details will also be deleted.

Deletion without loading the entity

In some cases, it is possible to delete a record without loading it into memory first. This is achieved by creating an instance of the entity with only the ID and marking it for deletion.

using (var context = new MyContext())
{
    var product = new Product { Id = 1 }; // We only need the ID
    context.Products.Attach(product);
    context.Products.Remove(product);
    context.SaveChanges();
}

Exception handling

It is important to handle exceptions when performing deletion operations, especially if there are referential integrity constraints in the database.

try
{
    context.SaveChanges();
}
catch (DbUpdateException ex)
{
    Console.WriteLine("Error deleting the record: " + ex.Message);
}

For example, if we try to delete a record that is being referenced by another table, an exception will be thrown.