How do I tell Entity Framework to not cascade delete children of a 1:many?

David Thielen 3,211 Reputation points
2023-04-19T02:57:55.1+00:00

When I delete a User record, if that User is the Event.Owner, I do not want to delete the Event. Instead I will assign Event.Owner to an existing User that is not being deleted. What fluent should I write so that EF knows that any User being deleted is not assigned to any Event.Owner and that User.Events will always be empty. And therefore it does not need to cascade deletes of User.Events?

public class User
{
  public int Id { get; private set; }
  public ICollection<Event> Events { get; set; }
}

public class Event
  {
  public int Id { get; private set; }
  public required User Owner { get; set; }
}

??? - thanks - dave

Developer technologies .NET Entity Framework Core
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. David Thielen 3,211 Reputation points
    2023-04-19T02:59:57.3866667+00:00

    Answer courtesy of ChatGPT (and verified by me).

    To achieve this behavior in Entity Framework Core, you'll need to disable the cascade delete behavior for the relationship between User and Event entities and implement your custom logic for reassigning the Event.Owner property.

    You can configure the relationship using the Fluent API in your DbContext subclass. Override the OnModelCreating method and use the HasOne and WithMany methods to configure the relationship and set the DeleteBehavior to Restrict:

    using Microsoft.EntityFrameworkCore;
    
    public class MyDbContext : DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Event> Events { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Event>()
                .HasOne(e => e.Owner)
                .WithMany(u => u.Events)
                .OnDelete(DeleteBehavior.Restrict);
        }
    }
    

    Now, when you delete a User, EF Core won't try to cascade delete the related Event records. To reassign the Event.Owner property, you can create a method that reassigns the events to another user before deleting the original user:

    public async Task DeleteUserAndReassignEventsAsync(int userId, int newOwnerId)
    {
        using var context = new MyDbContext();
        var user = await context.Users.FindAsync(userId);
        var newOwner = await context.Users.FindAsync(newOwnerId);
    
        if (user != null && newOwner != null)
        {
            var events = await context.Events.Where(e => e.Owner.Id == user.Id).ToListAsync();
            foreach (var event in events)
            {
                event.Owner = newOwner;
            }
    
            context.Users.Remove(user);
            await context.SaveChangesAsync();
        }
    }
    

    Call this method to delete a user and reassign their events to another user:

    await DeleteUserAndReassignEventsAsync(userIdToDelete, newOwnerId);
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.