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?
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.