如何配置Entity Framework Code First模型,以便在删除父项时级联删除带有ID /外键字符串的集合?

Geofence =>集合在生成的代码中不包含OnDelete(DeleteBehavior.Cascade)。车辆=>行程包含OnDelete(DeleteBehavior.Cascade)。唯一相关的区别是Vehicles的ID是int,而Geofence的ID是字符串。

public class Geofence
{
    [JsonProperty(PropertyName = "id")]
    [Key]
    public string ID { get; set; }

    [JsonProperty(PropertyName = "color")]
    public string Color { get; set; }

    [JsonProperty(PropertyName = "coordinates")]
    [Required]
    public List<Coordinate> Coordinates { get; set; }
}

public class Coordinate
{
    [JsonIgnore]
    [Key]
    public string ID { get; set; }

    [JsonIgnore]
    public string GeofenceID { get; set; }

    [JsonProperty(PropertyName ="lat")]
    [Required]
    public double Latitude { get; set; }

    [JsonProperty(PropertyName = "lng")]
    [Required]
    public double Longitude { get; set; }
}

 public class Vehicle
 {
    [Key]
    public int ID { get; set; }
    public string VehicleName { get; set; }

    public List<Trip> Trips { get; set; }
 }

  public class Trip
 {
    [Key]
    public int ID { get; set; }
    public int VehicleID { get; set; }

    public bool InProgress { get; set; }

    public DateTime Start { get; set; }
 }


生成配置代码:

modelBuilder.Entity("VTWeb.Models.Coordinate", b =>
            {
                b.HasOne("VTWeb.Models.Geofence")
                    .WithMany("Coordinates")
                    .HasForeignKey("GeofenceID");
            });

        modelBuilder.Entity("VTWeb.Models.VehicleViewModels.Trip", b =>
            {
                b.HasOne("VTWeb.Models.VehicleViewModels.Vehicle")
                    .WithMany("Trips")
                    .HasForeignKey("VehicleID")
                    .OnDelete(DeleteBehavior.Cascade);
            });

最佳答案

唯一相关的区别是Vehicles的ID是int,而Geofence的ID是字符串


这是非常明显的区别,因为string是引用类型,因此默认情况下可以为空。因此,在没有附加配置的情况下,该关系被视为optional,并且可选关系的默认删除行为是不级联。

您可以通过多种方式配置级联删除,最明显的是流畅的API。但是,最简单的方法是建立所需的关系。您唯一需要了解的是[Required]属性在应用于集合导航属性时不起作用-必须将其应用于参考导航属性或FK属性。

在您的示例中,没有参考导航属性,因此它必须在FK属性上:

public class Coordinate
{
    // ...
    [JsonIgnore]
    [Required] // <--
    public string GeofenceID { get; set; }
    //..
}


请注意,将[Required]属性应用于值类型属性(例如您的示例中的intdouble等)不会受到伤害,但由于它们不能保存null值,因此是多余的。对于值类型,requiredness基本上由是否使用可为空的类型控制。因此,[Required]属性的主要用法是用于string和参考导航属性。

为了完整起见,或者如果您想保持关系的可选性并仍然具有级联删除功能,请执行以下操作:

modelBuilder.Entity<Geofence>()
    .HasMany(e => e.Coordinates)
    .WithOne()
    .OnDelete(DeleteBehavior.Cascade);

10-06 13:30
查看更多