[英]How to apply cascade delete on entities which have several foreign keys with Entity Framework 6?
I have the two entities below: 我有以下两个实体:
[Table("TimeZone")]
public class TimeZone
{
[Required]
[Column("Name"), Index("IX_Name", IsUnique = true)]
[StringLength(50)]
public string Name { get; set; }
[Column("Description")]
[StringLength(100)]
public string Description { get; set; }
[Column("IANAID"), Index("IX_IANAID", IsUnique = true)]
[StringLength(50)]
public string IANAId { get; set; }
public ICollection<ApplicationUser> Users { get; set; }
public TimeZone()
{
Users = new HashSet<ApplicationUser>();
}
}
[Table("User")]
public class ApplicationUser : IdentityUser<string, IdentityUserLogin, ApplicationUserRole, IdentityUserClaim>
{
// [...]
[Column("TimeZoneID"), ForeignKey("TimeZone")]
public string TimeZoneId { get; set; }
[Column("RegionID"), ForeignKey("Region")]
public string RegionId { get; set; }
[Column("ManagerID"), ForeignKey("Manager")]
public string ManagerId { get; set; }
// One-to-One
public virtual TimeZone TimeZone { get; set; }
// One-to-One
public virtual Region Region { get; set; }
// One-to-Many
public virtual ApplicationUser Manager { get; set; }
// One-to-many
public virtual ICollection<Appointment> Appointments { get; set; }
// Many-to-many
public virtual ICollection<OnCallGroup> OnCallGroups { get; set; }
// One-to-many
public virtual ICollection<ApplicationUser> Subordinates { get; set; }
}
When I delete a record from TimeZone
table which is used in the User
table, the related records should be deleted according to the Cascadde Delete convention. 当我从User
表中使用的TimeZone
表中删除一条记录TimeZone
,应根据Cascadde Delete约定删除相关记录。
However since there are other foreign keys, I get the following exception with Entity Framework: 但是,由于还有其他外键,我在实体框架中遇到以下异常:
The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.User_dbo.TimeZone_TimeZoneID". DELETE语句与REFERENCE约束“ FK_dbo.User_dbo.TimeZone_TimeZoneID”冲突。 The conflict occurred in database "APPLICATIONDB_753c3d2ad2634cbf8cb62b098cdc6043", table "dbo.User", column 'TimeZoneID'. 在数据库“ APPLICATIONDB_753c3d2ad2634cbf8cb62b098cdc6043”的表“ dbo.User”的“ TimeZoneID”列中发生了冲突。 The statement has been terminated. 该语句已终止。
Is it normal that even though there is the cascade delete enabled by default on EF6 Code First, deleting a record from TimeZone
does not delete all the related users? 即使默认情况下在EF6 Code First上启用了级联删除,从TimeZone
中删除记录不会删除所有相关用户,这是否正常?
Note: In my ApplicationDbContext I overrided the OnModelCreating
method: 注意:在我的ApplicationDbContext中,我重写了OnModelCreating
方法:
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
base.OnModelCreating(dbModelBuilder);
dbModelBuilder.Conventions.Add<OneToManyCascadeDeleteConvention>();
dbModelBuilder.Conventions.Add<ManyToManyCascadeDeleteConvention>();
dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
// [...]
}
The FK property ( TimeZoneId
) CLR type is string
, which allows null
, and no [Required]
attribute has been applied to the FK or navigation property, thus making the relationship optional , ie ApplicationUser
may exist without TimeZone
. FK属性( TimeZoneId
)CLR类型为string
,允许为null
,并且没有[Required]
属性已应用于FK或Navigation属性,因此使该关系成为可选关系,即ApplicationUser
可能不存在TimeZone
。 And by default convention EF does not turn cascade delete on optional relationships. 并且默认情况下,EF不会对可选关系启用级联删除。
To turn the cascade delete on, you need either to make the relationship required by applying the [Required]
attribute on either TimeZoneId
or TimeZone
property, or use fluent API in case you need to keep it optional by adding the following inside OnModelCreating
override: 要打开级联删除,您需要通过在TimeZoneId
或TimeZone
属性上应用[Required]
属性来建立所需的关系,或者使用fluent API,以防您需要在OnModelCreating
覆盖内添加以下内容来保持可选OnModelCreating
:
modelBuilder.Entity<TimeZone>()
.HasMany(e => e.Users)
.WithOptional(e => e.TimeZone)
.HasForeignKey(e => e.TimeZoneId)
.WillCascadeOnDelete(); // <--
The same applies to other relationships using string
FK properties. 使用string
FK属性的其他关系也是如此。
Update: Actually the second option is not really an option. 更新:实际上,第二个选项实际上不是一个选项。 Even if it sets cascade delete on, EF treats cascade delete on optional relationships differently - when principal entity is deleted, it disassociates the related records by setting FKs to null
rather than deleting them. 即使将级联删除设置为打开,EF也会以不同的方式对待可选关系上的级联删除-删除主体实体时,它通过将FK设置为null
而不是删除它们来取消关联记录。 So you really have to make the relationship required by using the aforementioned attribute or changing the fluent API WithOptional
to WithRequired
. 所以,你的确要好好利用上述属性或改变流畅API所需的关系WithOptional
到WithRequired
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.