如何配置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]
属性应用于值类型属性(例如您的示例中的int
,double
等)不会受到伤害,但由于它们不能保存null
值,因此是多余的。对于值类型,requiredness基本上由是否使用可为空的类型控制。因此,[Required]
属性的主要用法是用于string
和参考导航属性。为了完整起见,或者如果您想保持关系的可选性并仍然具有级联删除功能,请执行以下操作:
modelBuilder.Entity<Geofence>()
.HasMany(e => e.Coordinates)
.WithOne()
.OnDelete(DeleteBehavior.Cascade);