Cascade delete in entity framework

2019-09-15 18:38发布

问题:

I am having problems setting up relationships in entity framework 6 and making cascade deletion work.

I have the following objects

public class Module {
    public long Id { get; set; };
    public virtual ICollection<Group> Groups { get; set; };
}

public class Group {
    public long Id { get; set; };
    public virtual ICollection<Field> Fields { get; set; };
}

public class Field {
    public long Id { get; set; };
    public virtual FieldLink Link { get; set; };
}

public class FieldLink {
    public long Id { get; set; };
    public virtual Module LinkToModule { get; set; };
}

Now a module has groups, a group has fields, a field MAY have a link. A link will have a LinkToModule, but this can be a different module then the one that the parent field/group belongs too.

I have setup my relationships like so

public ModuleConfig() 
{
    this.ToTable("Module");
}

public FieldGroupConfig() 
{
    this.ToTable("FieldGroup");

    // relationships
    this.HasRequired(e => e.Module)
        .WithMany(e => e.Groups)
        .HasForeignKey(e => e.ModuleId);
}  

public FieldConfig() 
{
    this.ToTable("Field");

    this.HasRequired(e => e.FieldGroup)
        .WithMany(e => e.Fields)
        .HasForeignKey(e => e.FieldGroupId);


    this.HasOptional(e => e.Link)
        .WithRequired(e => e.Field);

}

public FieldLinkConfig() 
{
    this.ToTable("FieldLink");

    this.HasRequired(e => e.LinkToModule)
        .WithMany()
        .HasForeignKey(e => e.LinkToModuleId);
}

Now i am running my tests, and i get the following error

Test method ModuleServiceTests.ModuleService_DeleteAsync_ByEntity threw exception: 

System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.FieldLink_dbo.Field_Id". The conflict occurred in database "TestDb", table "dbo.FieldLink", column 'Id'.

For if i check the relationship, it is between table Field.Id > FieldLink.Id and the DELETE rule is set as NO ACTION. Fine, so i guess i need to update that relationship and use WillCascadeOnDelete(true)

So i updated the code in FieldConfig from

this.HasOptional(e => e.Link)
    .WithRequired(e => e.Field);

to

this.HasOptional(e => e.Link)
    .WithRequired(e => e.Field)
    .WillCascadeOnDelete(true);

But now when i try to run my test, the database isnt even created and i get the error saying

Initialization method Test.TestInitialize threw exception. 
System.Data.SqlClient.SqlException: Introducing FOREIGN KEY constraint 'FK_dbo.FieldLink_dbo.Field_Id' on table 'FieldLink' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

Can someone please help? Have i setup a relationship incorrectly, am i going the wrong way about this?

回答1:

MS SQL Server does not supports cycles in the cascade deletes actions. You need to choose just one of the two directions to cascade deletes or find a workaround like in this answer (example of the trigger is here in Listing 6). This answer also contains some insights.