我有以下两个实体:
public class Tournament {
public int TournamentID { get; set; }
public String Name { get; set; }
public int? OfficialID { get; set; }
public virtual Official HeadOfficial { get; set; }
public virtual ICollection<Official> Officials { get; set; }
}
public class Official {
public int OfficialID { get; set; }
public String Surname { get; set; }
public String FirstName { get; set; }
public int TournamentID { get; set; }
public virtual Tournament Tournament { get; set; }
}
锦标赛可以有0..N官员和官方HAS来举办锦标赛。第二个关系是锦标赛可能有一个头衔。
为了使EF在制作数据库时正确解释这一点,我有以下内容:
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Tournament>()
.HasOptional(t => t.HeadOfficial)
.WithMany()
.HasForeignKey(t => t.OfficialID);
modelBuilder.Entity<Tournament>()
.HasMany(t => t.Officials)
.WithRequired(o => o.Tournament)
.HasForeignKey(o => o.TournamentID);
}
如果我现在删除锦标赛,那么与该锦标赛相关联的所有官员都将被删除,这就是我想要的。但是,当我删除一个已经在其中一个比赛中成为官方官员的官方时,删除不会通过引用删除语句与Tournaments.OfficialID中的引用约束冲突。
答案 0 :(得分:1)
如果我现在删除一个锦标赛,所有与之相关的官员 比赛被删除,这就是我想要的。但是,当我 删除一名官员已经成为其中一名官员 比赛,删除不通过引用删除 声明与参考约束冲突 Tournaments.OfficialID。
我认为这些情况完全不同。第一种情况是有效的,因为数据库中存在级联删除设置(EF确实在数据库中创建了此规则,因为该关系是必需的,这是默认行为)。
您的第二个关系是可选的,因此默认情况下没有级联删除。更重要的是:我不认为你想要级联删除,因为这意味着删除一名官员也会删除以此官员为首的比赛。
我只能想象,如果官方被删除,您希望将HeadOfficial
引用设置为null
。但是没有自动方式(比如级联删除)。您必须编写此类行为,例如:
using (var ctx = new MyContext())
{
var officialToDelete = ctx.Officials.Single(o => o.OfficialID == 5);
var tournaments = ctx.Tournaments.Where(t => t.OfficialID == 5).ToList();
foreach (var tournament in tournaments)
tournament.OfficialID = null;
ctx.Officials.Remove(officialToDelete);
ctx.SaveChanges();
}
我认为foreach
循环不是必需的,因为EF会在您调用null
时修复关系(=将外键设置为Remove
)。 (基本上EF本身在内部执行此循环。)但是将锦标赛加载到上下文中非常重要,因为EF关心此关系修复(仅适用于附加(=已加载)实体),而不是数据库(与级联删除相反) )。