简体   繁体   English

扩展实体框架类

[英]Extending entity framework classes

Even many Q/A on the subject, I didn't find a clear answer for this question: 关于这个问题甚至很多Q / A,我都没有找到这个问题的明确答案:

What's the best design practice for adding business rules (ie, validations) to entity classes. 向业务类添加业务规则(即验证)的最佳设计实践是什么。

I simply want to check some validations before setting the underlying entity value: 我只想在设置基础实体值之前检查一些验证:

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

It doesn't make sense to create a new class from scratch in BLL when all properties are already there in entity class. 当实体类中已经存在所有属性时,在BLL中从头开始创建新类是没有意义的。 On the other hand, entity classes need to be extended with business logic rules. 另一方面,实体类需要使用业务逻辑规则进行扩展。

Using interface need extra work, because a change in DAL (entity) would be reflected in both interface and BLL class. 使用接口需要额外的工作,因为DAL(实体)的更改将反映在接口和BLL类中。

I'm not sure if inheriting from entity class and overriding it's properties and adding extra properties and methods is a good idea or not. 我不确定是否继承实体类并覆盖它的属性并添加额外的属性和方法是一个好主意。

A sample pseudo code in more helpful to me. 一个示例伪代码对我更有帮助。

Thanks 谢谢

I would like to elaborate on Stephen Cleary's answer. 我想详细说明Stephen Cleary的答案。 He is correct in using the partial class/methods to handle business rules in EF. 他使用部分类/方法来处理EF中的业务规则是正确的。 However, he did not go into much detail about what to do within that partial class/method. 但是,他没有详细说明在该部分类/方法中该做什么。 I created a URL shortening service on my blog to use as an example for this. 我在我的博客上创建了一个URL缩短服务,以此作为示例。 My ShortURL entity has only two columns/properties. 我的ShortURL实体只有两列/属性。 Url and ID . UrlID

I wanted to validate that the URL being shortened is a valid URL before it actually stores it in the database through EF. 我想验证缩短的URL是否有效,然后才能通过EF将其实际存储到数据库中。 So I created a partial class and method like so: 所以我创建了一个部分类和方法,如下所示:

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.");
    }
}

This stopped EF from changing the property, leaving it NULL. 这使EF停止更改属性,使其保持为NULL。 But that's all it did. 但就是这样。 It didn't give me an easy way to get at the error message and display it to the user (that I am aware of EDIT: According to http://www.sellsbrothers.com/posts/Details/12700 IDataErrorInfo is the only way to get the error message to display properly in ASP.NET MVC) so I followed another example I found in the dark recesses of the web somewhere and I made my partial class inherit from IDataErrorInfo . 它没有给我一个简单的方法来获取错误消息并将其显示给用户(我知道编辑:根据http://www.sellsbrothers.com/posts/Details/12700 IDataErrorInfo是唯一的获取错误消息以便在ASP.NET MVC中正确显示的方法)所以我按照另一个例子我在网络的黑暗凹槽中找到了,我让我的部分类继承自IDataErrorInfo I then implemented the interface and included a private dictionary object to store error messages in. 然后我实现了接口并包含一个私有字典对象来存储错误消息。

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.
        }
    }
}

Now, I have a fully-functioning way to store, retrieve, and display error messages. 现在,我有一个完整功能的方法来存储,检索和显示错误消息。 Now back in my controller (in MVC) I am able to do if (!ModelState.IsValid) 现在回到我的控制器(在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);
    }

There ya go. 你去吧。 A working example of how to not only extend EF's partial methods, but also how to propagate the validation back to the UI. 一个工作示例,不仅如何扩展EF的部分方法,还包括如何将验证传播回UI。 Let me know if anything needs improving or if there was something I missed. 如果有什么需要改进或者我有什么遗漏,请告诉我。

Check out your EF designer-generated code. 查看EF设计器生成的代码。

Each property Property is actually implemented like this: 每个属性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();

The partial method On-Property-Changing is where you can do single-property validation or business logic. 部分方法On-Property-Changing是您可以执行单属性验证或业务逻辑的地方。

Xaqron, the best way I have found it to use Partial Classes, for example, if you have a class in your EF called PropertyListing you can use a partial class like this: Xaqron,我发现它使用Partial Classes的最好方法,例如,如果你的EF中有一个名为PropertyListing的类,你可以使用这样的局部类:

Partial Public Class PropertyListing
    Inherits EntityObject

    'Do something here

End Class

You can now extend the class as little or as much as you want without much fuss. 现在,您可以根据需要尽可能少地扩展课程,而不必大惊小怪。 The example is in VB but you get the jist of it 这个例子是在VB中,但你得到了它的主旨

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM