victorswhisky
victorswhisky

Reputation: 1

EF Core does not allow Cascade Delete on 2 foreign keys, but Blazor sample web app does this just fine

I have seen countless posts advising that EF Core with SQL Server blocks multiple foreign keys which have "OnDelete Cascade" (due to cycles and multiple delete paths). However I see in the sample Blazor web app (in VS2022) which installed a default user management database that this is done and works fine without throwing any errors (snippet further below).

My own classes are as right below - just a sample to test this out

EDIT: simplified the example by removing an not necessary Name class. Now this just has the 3 entities in question. Same error reproduced

namespace BlazorSampleEFCore.EFCoreTrial
{
    public class Company
    {
        [Key]
        public int DbKey { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public List<Employee> Employees { get; set; }
        public List<Group> Groups { get; set; }
    }

    public class Employee
    {
        [Key]
        public int DbKey { get; set; }
        public DateTime dob { get; set; }
        public string email { get; set; }

        [ForeignKey("CompanyId")]
        public int CompanyId { get; set; }
        
        public Company Company { get; set; }

        [ForeignKey("GroupId")]
        public int GroupID { get; set; }
        
        public Group Group { get; set; }
    }

    public class Group
    {
        [Key]
        public int DbKey { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public List<Employee> Employees { get; set;}    
        public int CompanyId { get; set; }
    }
}

This below is from the initial migration from the sample database which has user management db schema already built in. It has 2 foreign keys on 2 non-nullable columns, pointing to two different principal tables and both with "OnDelete cascade".

migrationBuilder.CreateTable(
    name: "AspNetUserRoles",
    columns: table => new
    {
        UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
        RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
        table.ForeignKey(
            name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
            column: x => x.RoleId,
            principalTable: "AspNetRoles",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_AspNetUserRoles_AspNetUsers_UserId",
            column: x => x.UserId,
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    });

How does this pass through Update-Database and get all tables and keys created, but a similar table (see below) added by me refuses to pass through Update-Database:

migrationBuilder.CreateTable(
    name: "Employee",
    columns: table => new
    {
        DbKey = table.Column<int>(type: "int", nullable: false)
            .Annotation("SqlServer:Identity", "1, 1"),
        dob = table.Column<DateTime>(type: "datetime2", nullable: false),
        email = table.Column<string>(type: "nvarchar(max)", nullable: false),
        CompanyId = table.Column<int>(type: "int", nullable: false),
        GroupID = table.Column<int>(type: "int", nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Employee", x => x.DbKey);
        table.ForeignKey(
            name: "FK_Employee_Companies_CompanyId",
            column: x => x.CompanyId,
            principalTable: "Companies",
            principalColumn: "DbKey",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_Employee_Group_GroupID",
            column: x => x.GroupID,
            principalTable: "Group",
            principalColumn: "DbKey",
            onDelete: ReferentialAction.Cascade);
    });

On running Update-Database, I get this error:

fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [Employee] (
[DbKey] int NOT NULL IDENTITY,
[NameDbKey] int NOT NULL,
[dob] datetime2 NOT NULL,
[email] nvarchar(max) NOT NULL,
[companyDbKey] int NOT NULL,
[GroupDbKey] int NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY ([DbKey]),
CONSTRAINT [FK_Employee_Companies_companyDbKey] FOREIGN KEY ([companyDbKey]) REFERENCES [Companies] ([DbKey]) ON DELETE CASCADE,
CONSTRAINT [FK_Employee_Group_GroupDbKey] FOREIGN KEY ([GroupDbKey]) REFERENCES [Group] ([DbKey]) ON DELETE CASCADE,
CONSTRAINT [FK_Employee_Name_NameDbKey] FOREIGN KEY ([NameDbKey]) REFERENCES [Name] ([DbKey]) ON DELETE CASCADE
);

Failed executing DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] CREATE TABLE [Employee] ( [DbKey] int NOT NULL IDENTITY, [NameDbKey] int NOT NULL, [dob] datetime2 NOT NULL, [email] nvarchar(max) NOT NULL, [companyDbKey] int NOT NULL, [GroupDbKey] int NOT NULL, CONSTRAINT [PK_Employee] PRIMARY KEY ([DbKey]), CONSTRAINT [FK_Employee_Companies_companyDbKey] FOREIGN KEY ([companyDbKey]) REFERENCES [Companies] ([DbKey]) ON DELETE CASCADE, CONSTRAINT [FK_Employee_Group_GroupDbKey] FOREIGN KEY ([GroupDbKey]) REFERENCES [Group] ([DbKey]) ON DELETE CASCADE, CONSTRAINT [FK_Employee_Name_NameDbKey] FOREIGN KEY ([NameDbKey]) REFERENCES [Name] ([DbKey]) ON DELETE CASCADE );

Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_Employee_Group_GroupDbKey' on table 'Employee' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

Upvotes: 0

Views: 40

Answers (0)

Related Questions