Entity Framework Core 2.1: OnDelete Cascade - multiple cascade paths

346 Views Asked by At

I'm getting the following error in a number of different places when trying to Update-Database.

...may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

The error seems to occur in places where I have multiple One-to-Many relations on an object.

I know other posts have been made on this, but I have yet to find an explanation that really helps me understand this concept. Can you explain how I should be formatting OnModelCreating in my DbContext in the following two examples to allow for the desired functionality?


Example 1

Classes

public class Bin
{
    public int Id { get; set; }

    public int BarnId { get; set; }
    public Barn Barn { get; set; }

    public int GatewayId { get; set; }
    public Gateway Gateway { get; set; }
}

public class Barn
{
    public int Id { get; set; }
    public ICollection<Bin> Bins { get; set; }
}

public class Gateway
{
    public int Id { get; set; }
    public ICollection<Bin> Bins { get; set; }
}


Migration

migrationBuilder.CreateTable(
    name: "Bins",
    columns: table => new
    {
        Id = table.Column<int>(nullable: false)
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)
        BarnId = table.Column<int>(nullable: false),
        GatewayId = table.Column<int>(nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Bins", x => x.Id);
        table.ForeignKey(
            name: "FK_Bins_Barns_BarnId",
            column: x => x.BarnId,
            principalTable: "Barns",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_Bins_Gateways_GatewayId",
            column: x => x.GatewayId,
            principalTable: "Gateways",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
     });

error occurs when trying to create "FK_Bins_Gateways_GatewayId"

Functionality that I want: When a Barn is deleted, the associated Bins are deleted. When a Gateway is deleted, the associated Bins are not deleted


Example 2

Classes

public class Bin
{
    public int Id { get; set; }

    public ICollection<BinFeed> BinFeeds { get; set;}
}

public class Feed
{
    public int Id { get; set; }

    public ICollection<BinFeed> BinFeeds { get; set;}
}

public class BinFeed
{
    public int Id { get; set; }

    public bool Current { get; set;}

    public int BinId { get; set; }
    public Bin Bin { get; set; }

    public int FeedId { get; set; }
    public Feed Feed { get; set; }
}


Migration

migrationBuilder.CreateTable(
            name: "BinFeeds",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
        BinId = table.Column<int>(nullable: false),
        FeedId = table.Column<int>(nullable: false),
        Current = table.Column<bool>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_BinFeeds", x => x.Id);
            table.ForeignKey(
            name: "FK_BinFeeds_Bins_BinId",
            column: x => x.BinId,
            principalTable: "Bins",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_BinFeeds_Feeds_FeedId",
            column: x => x.FeedId,
            principalTable: "Feeds",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
    });

Error occurs when trying to create "FK_BinFeeds_Feeds_FeedId"

Functionality that I want: When Bin is deleted, associated BinFeeds are deleted. When Feed is deleted, associated BinFeeds are deleted.

1

There are 1 best solutions below

0
On

I had similar problem in the past. I figured out if you don't configure the OnModelCreating manually it will find the relationship automaticly and you have no problem(probably it does the same thing in option 2). Also you can set onDelete: ReferentialAction.NoAction if you are not going to delete any data from the tables in this relationship in the future. Other solution is to use triggers with a third party package or by manually configuring with SQL.