這裏的情景:建議在POCO驗證與ASP.NET MVC /實體框架
- ASP.NET MVC2 Web應用程序
- 實體框架4(純POCO的,自定義數據上下文)
- 庫模式工作模式
- 依賴注入的
- 單位
- 服務層中介控制器 - >庫
所以基本上,所有的酷東西。 :)
事件流動的基本UI操作( 「添加郵報」):
- 控制器調用添加(POST)在服務層方法
- 服務層調用添加(T )上儲存庫
- 庫調用ADDOBJECT(T)自定義數據上下文
- 控制器調用通訊它()在工作單位
現在,我試圖找出我可以把我的驗證。
在這個階段,我需要兩種類型的驗證:
- 簡單,獨立的POCO驗證,如「後必須有一個標題」。這似乎是POCO上的Data Annotations的自然選擇。
- 複雜的業務驗證,例如「無法將註釋添加到鎖定的帖子」。這不能通過數據註釋完成。現在
,我一直在讀「編程實體框架,第二版」,由朱莉·勒曼(這是極好的BTW),並一直在尋找到鉤住SavingChanges事件,以便進行「最後一分鐘」驗證。這將是一個很好的方法來確保驗證總是每當我做「某事」(添加,修改,刪除)時發生,但它也有點遲了國際海事組織(因爲項目已經在狀態管理器) - 所以我能如果驗證失敗,請刪除它們?
我當然可以讓我的POCO實現一個接口(稱爲「IValidatable」),並在此事件期間在此接口上調用一個方法。
但是,這似乎「爲時已晚」的業務驗證 - 這是共識嗎?
我基本上在這裏尋找指導,我試圖設計一個可複用的,複雜的業務邏輯的智能驗證方案,鑑於我的上述架構。如你所知,POCO的EF意味着POCO具有DB上的所有屬性 - 所以我可能有一個「PostID」屬性,帶有get/set訪問器(因爲EF需要獲取/設置這些屬性)。
但問題是,「PostID」是一個身份列,所以我如何保護該領域從明確設置?例如,如果我(出於某種原因)執行以下操作:
var post = service.FindSingle(10);
post.PostId = 10;
unitOfWork.Commit();
這將拋出SqlException。我怎樣才能防止這個?我不能「隱藏」這個屬性(因爲它是私有的,甚至是內部的),因爲POCO正在與Repository進行單獨的彙編。
有關驗證的說明 - 我打算創建自定義異常(從異常派生)。所以當驗證失敗時,我需要拋出這些異常。
這樣的話,我可以在我的控制器上的代碼是這樣的:
[HttpPost]
public ActionResult AddPost(Post post)
{
try
{
IUnitOfWork uow = new UnitOfWork();
postService.Add(post);
uow.Commit();
}
catch(InvalidPostOperation ipo)
{
// add error to viewmodel
}
}
我將不得不手工做服務層每次我做一個添加驗證?那我該如何處理保存? (因爲這是工作單元而不是服務層)。
因此,爲了防止這種從一個「所有的地方」的問題,這裏是我的問題:
- 簡單的POCO驗證 - 這應該與數據註釋做了什麼?優點/缺點/陷阱?
- 在什麼情況下(如果有的話)我們是否應該掛鉤EF Data上下文的SavingChanges事件以提供驗證?
- 我應該在哪裏進行復雜的業務驗證?在服務明確,或在POCO的(我可以從服務呼叫)的方法。我如何創建一個智能/可重用計劃?
- 我們怎樣才能「隱藏」POCO自動生成的屬性被篡改?
任何想法將不勝感激。
道歉,如果這篇文章「太長」,但它是一個重要的問題,可以通過很多方式解決,所以我想提供所有信息,以獲得最佳答案。
謝謝。
編輯
下面的答案是有幫助的,但我還是比較理想的狀況尋找更多的想法。還有誰?
其中一個問題太多,但關於#3,請記住驗證是上下文敏感的(或基於任務的)。在'Post'上創建一個'IsValid'屬性是很有誘惑力的,但是你需要一個'IsValidForDraft'來保存缺少某些信息的草稿。當然,POCO不應該意識到「草案出版」的概念。 :) – bzlm 2010-10-07 06:25:37
唉來吧,爲什麼要結束投票?我意識到它是一個「長」的問題。但這就是爲什麼我最終得到了4個問題。僅僅因爲我問了4件事情,並不意味着這個Q值得投票結束,因爲「太模糊」。所有4個q都涉及到一個主題。 – RPM1984 2010-10-07 06:41:52
@bzlm - 是的,明白了你的觀點。 :) – RPM1984 2010-10-07 06:42:51