Search code examples
entity-frameworkcascaderelationships

EF Cascade delete from two separate tables


I have the following two entities:

public class Field {
    public int FieldID { get; set; }
    public String Name { get; set; }
    public int LocationID { get; set; }

    public virtual ICollection<FieldPlanning> FieldPlannings { get; set; }
}

public class Timeslot {
    public int TimeslotID { get; set; }
    public DateTime Start { get; set; }
    public int MatchDayID { get; set; }

    public virtual ICollection<FieldPlanning> FieldPlannings { get; set; }
}

Now a combination of these two entities makes up the following entity:

public class FieldPlanning {
    public int FieldPlanningID { get; set; }
    public int TimeslotID { get; set; }
    public int FieldID { get; set; }


    public virtual Timeslot Timeslot { get; set; }
    public virtual Field Field { get; set; }
    public virtual Match Match { get; set; }
}

This entity would then also have a navigation property to the Match entity, but I've left this out for brevity.

When either a Field or a Timeslot is deleted I want it to delete the associated FieldPlanning records as well.

If I run the application I get the error that 'Timeslot_FieldPlanning may cause cycles or multiple cascade paths'. If I then edit the modelcreating like this:

        modelBuilder.Entity<Timeslot>()
            .HasMany(ts => ts.FieldPlannings)
            .WithRequired(fp => fp.Timeslot)
            .HasForeignKey(fp => fp.TimeslotID)
            .WillCascadeOnDelete(false);

If I then delete a Field, the FieldPlanning is deleted with it without problem. If I try to delete a Timeslot, I get the same error as before.

How can I fix it so that I can delete either of Field or Timeslot and for both Entities the CascadeOnDelete can be true?

I read Hans Riesebos' answer here but I couldn't figure out how to apply it to my problem.

EDIT: My Location Entity:

public class Location {
    public int LocationID { get; set; }
    public String Name { get; set; }
    public Address Address { get; set; }
    public int TournamentID { get; set; }

    public virtual Tournament Tournament { get; set; }

    public virtual ICollection<Field> Fields { get; set; }
}

My Match Entity:

public class Match {
    public int MatchID { get; set; }
    public Boolean Forfeited { get; set; }
    public int TeamAID { get; set; }
    public int TeamBID { get; set; }
    public int FieldPlanningID { get; set; }
   

    public virtual Team TeamA { get; set; }
    public virtual Team TeamB { get; set; }
    public virtual FieldPlanning FieldPlanning { get; set; }

    public virtual ICollection<Official> Officials { get; set; }
}

When trying it out, I specifically commented the navigation property to Match, so I could make sure it first worked without Match because I know I have problem in the relationship between FieldPlanning and Match, as this is a 0..1 to 0..1 relationship. But I don't see how this matters in my current problem (so long as I keep the navigation property of Match in FieldPlanning commented).


Solution

  • After searching a little bit more I found this thread which correctly states that SQL Server doesn't allow this. I thought the problem was with the Entity Framework but after trying to recreate he tables in SSMS I noticed it still didn't work.

    The solution is to disable one of the cascading effects and use a trigger (or code) to first delete the child rows.