2011-02-10 134 views
2

關於這個問題甚至很多Q/A,我沒有找到這個問題的一個明確的答案:擴展實體框架類

什麼是用於添加業務規則(即,驗證),以實體類最佳設計實踐。

我只是想設置底層實體值之前檢查一些驗證:

public Property 
{ 
    get { return base.Property; } 
    set 
    { 
     // Do some validations or other business logic 
     base.Property = value; 
    } 
} 

它沒有意義在BLL從頭開始創建一個新的類時,所有屬性都已經存在於實體類。另一方面,實體類需要用業務邏輯規則進行擴展。

使用接口需要額外的工作,因爲DAL(實體)中的變化會反映在接口和BLL類中。

我不確定是否從實體類繼承並重寫它的屬性並添加額外的屬性和方法是一個好主意或不是。

一個樣本僞代碼對我更有幫助。

謝謝

+0

是你的實體框架類還是你的域模型?或者你有單獨的課程? – RPM1984 2011-02-10 00:39:39

+0

您是使用實體對象還是POCO? – 2011-02-10 08:46:44

+0

@Ladislav:我從Visual Studio 2010使用`EF` – Xaqron 2011-02-10 12:30:45

回答

3

檢查出您的EF設計器生成的代碼。

每個屬性Property實際上是實現這樣的:

public global::System.String Property 
    { 
     get 
     { 
      return _Property; 
     } 
     set 
     { 
      OnPropertyChanging(value); 
      ReportPropertyChanging("Property"); 
      _Property = StructuralObject.SetValidValue(value, false); 
      ReportPropertyChanged("Property"); 
      OnPropertyChanged(); 
     } 
    } 
    private global::System.String _Property; 
    partial void OnPropertyChanging(global::System.String value); 
    partial void OnPropertyChanged(); 

分部方法On-Property-Changing在這裏你可以做單屬性驗證或業務邏輯。

+0

@Stephen:我需要一個單獨的項目作爲我的BLL。就像EF上的包裝一樣。有沒有你的建議方法的在線樣本? – Xaqron 2011-02-10 07:53:29

2

Xaqron,我發現它使用分部類,例如,如果你在你的EF一類叫做PropertyListing您可以使用部分類這樣的最佳方式:

Partial Public Class PropertyListing 
    Inherits EntityObject 

    'Do something here 

End Class 

您現在可以無需大驚小怪就可以儘可能少地擴展班級。這個例子是在VB中,但你得到它的精神

4

我想詳細闡述斯蒂芬克利裏的答案。他在使用部分類/方法處理EF中的業務規則時是正確的。但是,他沒有詳細說明在該部分類/方法中應該做什麼。我在我的博客上創建了一個URL縮短服務,以此作爲示例。我的ShortURL實體只有兩列/屬性。 UrlID

我想驗證縮短的URL是一個有效的URL,然後通過EF實際存儲在數據庫中。所以我創建瞭如下的部分類和方法:

public partial class ShortURL 
{ 
    partial void OnUrlChanging(string url) 
    { 
     if (!Regex.IsMatch(url, @"(^((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)")) 
      throw new Exception("Not a valid URL."); 
    } 
} 

這會停止EF更改屬性,使其保留爲NULL。但這就是它所做的一切。它並沒有給我一個簡單的方法來獲取錯誤信息並將其顯示給用戶(我知道編輯:根據http://www.sellsbrothers.com/posts/Details/12700 IDataErrorInfo是獲取錯誤消息在ASP中正確顯示的唯一方法。 NET MVC),所以我遵循了另一個例子,我在網絡的黑暗凹處找到了某個地方,並且讓我的部分類繼承自IDataErrorInfo。然後我實現了接口幷包含一個專用字典對象來存儲錯誤消息。

public partial class ShortURL : IDataErrorInfo 
{ 
    private Dictionary<string, string> errors = new Dictionary<string, string>(); 

    partial void OnUrlChanging(string url) 
    { 
     if (!Regex.IsMatch(url, @"(^((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)")) 
      errors.Add("Url", "Not a valid URL."); 
    } 

    public string Error 
    { 
     get { return string.Empty; } //I never use this so I just return empty. 
    } 

    public string this[string columnName] 
    { 
     get 
     { 
      if (errors.ContainsKey(columnName)) 
       return errors[columnName]; 
      return string.Empty; //Return empty if no error in dictionary. 
     } 
    } 
} 

現在,我有一個全功能的方式來存儲,檢索和顯示錯誤消息。現在回到我的控制器(在MVC中)我能夠做到if (!ModelState.IsValid)

[HttpPost] 
    public ViewResult URLShortener(ShortURL shortURL) 
    { 
     if (!ModelState.IsValid) 
      return View(); 
     shortURL.Url = shortURL.Url.ToLower().StartsWith("www.") ? "http://" + shortURL.Url : shortURL.Url; 
     shortURLRepository.AddShortURL(shortURL); 
     object model = "http://www.u413.com/" + ShortCodes.LongToShortCode(shortURL.UrlID); 
     //Not related to this answer but I had to cast my string as a generic object because the View() method has a (string, string) constructor that does something totally different. My view actually uses string as the model. I know I know, I could have just used ViewBag. 
     return View("ShowUrl", model); 
    } 

有你去。一個如何擴展EF的部分方法的工作示例,以及如何將驗證傳播回UI。如果有任何需要改進的地方,或者我錯過了某些東西,請告訴我。