什麼你正在尋找可以通過Guest
和Language
實體之間建立一個可選協會來實現:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Guest>()
.HasOptional(p => p.PreferredLanguage)
.WithMany()
.HasForeignKey(p => p.LanguageID);
}
單元測試:
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();
}
其結果是,我們將最終產生一個guest
記錄,其中包含LanguageID FK列的數據庫空值。
更新:
首先讓我們來看看爲什麼上面的單元測試通過查看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();
}
這一次失敗,並拋出的SQLException包含試圖手動刪除記錄,你從SQL Server得到了確切的消息。原因在於,在第二次單元測試中,我們沒有在上下文中加載相關guest對象,因此EF不知道它,並且不會像第一個示例中那樣提交必要的更新語句。
回到你的問題,不幸的是EF代碼第一次不允許明確更改刪除關係/更新的規則,但我們總是可以訴諸的SqlCommand方法,你看到this post它的一個例子。在你的情況下,我們可以編碼:
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");
}
這是你在找什麼。通過採用上述種子方法,第二次單元測試也將通過。
希望這有助於
莫爾塔扎
哇! Excxellent答案!我需要看看你的博客! :-) – 2011-04-03 23:10:06