Ing*_*mar 19 cascading-deletes entity-framework-4 entity-framework-ctp5
我正在使用EF4 CTP 5,CodeFirst.
请先看我的课程:
public class Guest
{
[Key]
public Guid GuestID { get; set; }
public Language PreferredLanguage { get; set; }
public Guid? LanguageID { get; set; }
}
public class Language
{
[Key]
public Guid LanguageID { get; set; }
[Required(ErrorMessage = "Enter language name")]
[StringLength(50, ErrorMessage = "Language name is too long")]
public string LanguageName { get; set; } // in origine language
}
Run Code Online (Sandbox Code Playgroud)
我的目标是为访客语言关系设置一定的"删除规则".删除语言时,我不想删除相应的guest虚拟机(因此无级联删除).相反,我希望客人的LanguageID为"Set NULL".
我希望流利的API在这里支持我.但我找不到任何有用的东西.WillCascadeOnDelete(bool),它不提供我需要的选项.我错过了什么吗?或者这只是在CTP 5中没有实现?
谢谢你的帮助!
Mor*_*avi 35
您正在寻找的是通过在实体和实体之间建立可选关联来实现的:GuestLanguage
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Guest>()
.HasOptional(p => p.PreferredLanguage)
.WithMany()
.HasForeignKey(p => p.LanguageID);
}
Run Code Online (Sandbox Code Playgroud)
using (var context = new Context())
{
var language = new Language()
{
LanguageName = "en"
};
var guest = new Guest()
{
PreferredLanguage = language
};
context.Guests.Add(guest);
context.SaveChanges();
context.Languages.Remove(language);
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
因此,我们最终会guest为LanguageID FK列创建一个DB null值的记录.
首先让我们看看为什么上面的单元测试通过查看SQL事件探查器而成功.下面显示了调用第二个SaveChanges()方法后的跟踪:

正如您所看到的,EF足够聪明,首先通过将其设置LanguageID为null 来更新来宾记录,然后提交删除语句以删除语言记录,这是设置可选关联时的默认EF行为.所以它在EF的应用程序方面得到了解决,当然如果您尝试手动删除SQL Server中的语言记录,您将从DBMS中收到错误,就像您也提到的那样.
但是,这个故事还有更多.考虑以下单元测试:
using (var context = new Context())
{
var language = new Language() { LanguageName = "en" };
var guest = new Guest() { PreferredLanguage = language };
context.Guests.Add(guest);
context.SaveChanges();
}
using (var context = new Context())
{
var language = context.Languages.First();
context.Languages.Remove(language);
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
这个失败,抛出一个SQLException包含您在尝试手动删除记录时从SQL Server获得的确切消息.原因是因为在第二个单元测试中我们没有在上下文中加载相关的guest对象,因此EF不知道它并且不会像在第一个示例中那样提交必要的更新语句.
回到你的问题,遗憾的是EF Code First不允许显式更改关系上的删除/更新规则,但我们总是可以使用SqlCommand方法,因为你在这篇文章中看到了它的一个例子.在您的情况下,我们可以编码:
protected override void Seed(Context context)
{
context.Database.SqlCommand("ALTER TABLE dbo.Guests DROP CONSTRAINT Guest_PreferredLanguage");
context.Database.SqlCommand("ALTER TABLE dbo.Guests ADD CONSTRAINT Guest_PreferredLanguage FOREIGN KEY (LanguageID) REFERENCES dbo.Languages(LanguageID) ON UPDATE NO ACTION ON DELETE SET NULL");
}
Run Code Online (Sandbox Code Playgroud)
这是你在寻找什么.有了上述种子方法,第二次单元测试也将通过.
希望这有帮助,
Morteza