Set to no deletes for Entity Framework many to many relationship

David Thielen 3,211 Reputation points
2023-04-17T21:30:47.4733333+00:00

This was working and now it's not. Only difference, my model had so many changes I deleted all the migrations and started over having it build the DB from scratch. I thought when there's a many to many relationship in Entity Framework that deleting one of the objects did not delete the many objects it's linked to. That's what I want. When a User or Campaign is deleted, I do not want the many objects it is linked to deleted.

public class User
{
    public int Id { get; private set; }
    public ICollection<Campaign> Campaigns { get; set; }
}

public class Campaign
{
    public int Id { get; private set; }
    public ICollection<User> Followers { get; set; }
}

And the errors I now get running Update-Database are:

Failed executing DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [CampaignUser] (
    [CampaignsId] int NOT NULL,
    [FollowersId] int NOT NULL,
    CONSTRAINT [PK_CampaignUser] PRIMARY KEY ([CampaignsId], [FollowersId]),
    CONSTRAINT [FK_CampaignUser_Campaigns_CampaignsId] FOREIGN KEY ([CampaignsId]) REFERENCES [Campaigns] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_CampaignUser_Users_FollowersId] FOREIGN KEY ([FollowersId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE
);

and

Introducing FOREIGN KEY constraint 'FK_CampaignUser_Users_FollowersId' on table 'CampaignUser' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.

Any idea why this is happening? I do want the join table entry to go away when a Campaign or User object is deleted. But I do not want the associated ICollection of objects to be deleted. I tried fluent commands to explicitly set this, but every command I tried wouldn't compile. So I'm clearly not understanding this at all.

public class CampaignConfiguration : IEntityTypeConfiguration<Campaign>
{
    /// <inheritdoc />
    public void Configure(EntityTypeBuilder<Campaign> builder)
    {
        builder.HasMany(c => c.Followers)
            .WithMany(u => u.Campaigns).OnDelete()
    }
}

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-17T22:00:36.2566667+00:00

    Answer courtesy of ChatGPT. And if someone knows EF well, please let me know if this is a good solution (ChatGPT is good, but nowhere near perfect).

    public class YourDbContext : DbContext
    {
        // Your DbSet properties
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>()
                .HasMany(u => u.Campaigns)
                .WithMany(c => c.Followers)
                .UsingEntity<Dictionary<string, object>>(
                    "CampaignUser",
                    j => j
                        .HasOne<Campaign>()
                        .WithMany()
                        .HasForeignKey("CampaignsId")
                        .OnDelete(DeleteBehavior.Restrict),
                    j => j
                        .HasOne<User>()
                        .WithMany()
                        .HasForeignKey("FollowersId")
                        .OnDelete(DeleteBehavior.Restrict)
                );
    
            // Your other model configurations
        }
    }
    

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.