2012-09-25 68 views
1

模式中的EF5和非空字符串出現了一點神祕感。例如,假設我們有這個簡單的用戶表:EF5附加實體驗證

CREATE TABLE Users 
(
    UserID INT PRIMARY KEY NOT NULL IDENTITY(1,1), 
    UserName VARCHAR(50) NOT NULL, 
    UserFirst VARCHAR(50) NULL, 
    UserLast VARCHAR(50) NULL 
) 

...我創建了一個POCO類來表示它。這一切工作正常。我可以檢索和創建數據,但更新已經造成了一些嚴重的痛苦。說一會兒,我想更新給定的用戶的名字:

User user = new User { UserID = 12345 }; 
context.Users.Attach(user); 
user.FirstName = "SomethingElse"; 
context.SaveChanges(); 

這應該工作。附件後,不可爲空的UserName爲空。哪一個應該沒問題 - 我不想改變它,並且變化檢測表明該值沒有變化。但是,當我撥打SaveChanges時,會引發DB驗證異常,說明UserName無效。

所以,從這個兩個問題:

  1. 我做得過份了?我完全願意相信我對實體框架的理解是有缺陷的。
  2. 爲什麼屬性的變化狀態未在保存時使用?我知道context.Configuration.ValidateOnSaveEnabled,但我不認爲簡單地將驗證關閉是一個有效的答案。我可以依靠另一種類似的選擇嗎?

回答

2

你說你想更新一個用戶,但你的示例代碼是創建一個新的用戶,ID爲12345,然後附加它。你的代碼正在做的是創建一個全新的實體,留下一個不可爲空的字段爲空,並試圖保存到數據庫,從而引發錯誤。

您是否打算檢索現有用戶ID爲12345?然後,而不是創建一個新的實體,您應該從數據庫中獲取該實體,然後更新該屬性。

User user = context.Users.First(u => u.UserID == 12345); 
user.FirstName = "SomethingElse"; 
context.SaveChanges(); 

編輯

在修改名字屬性附加,EF標誌着整個實體爲髒之後,所以它attemps更新的一切發生了什麼事是。

如果你想只更新你需要改變你的代碼(從related SO post, How to update a single column)的姓:

var user = new User { UserID = 12345, FirstName = "SomethingElse" }; 
    using (var db = new MyEfContextName()) 
    { 
    context.Users.Attach(user); 
    context.Entry(user).Property(x => x.FirstName).IsModified = true; 
    context.SaveChanges(); 
    } 
+0

我明白你在說什麼,但我尊重不同意見。從'Attach'的文檔:'...實體被置於Unchanged狀態,就好像它已經從數據庫中讀取一樣。「換句話說,「UserName」爲空的事實應該是無關緊要的,並且通過擴展,驗證應該是屬性而不是對象。 (此外,如果您設置了相同的方案,但在EDMX中將默認值設置爲空字符串,則不需要在保存時設置'UserName',並且空字符串不會被保留。) – Ross

+0

更新了帖子.. –

+0

什麼是「我立即明白爲什麼當實體明確公開「IsModified」時,實體被標記爲髒批發。在我看來,只有'IsModified'字段應該被檢查,並且在我的原始情況下,只有一個字段_was_被修改。然而,在思考它之後,試圖讓上下文足夠聰明以便零碎地保存實體 - 特別是從代碼優先的角度來看 - 將是相當艱鉅的。這是巧妙的模板,但我不確定這是值得這個項目的努力。 – Ross