2011-02-10 161 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。如果有任何需要改进的地方,或者我错过了某些东西,请告诉我。