扩展实体框架类

发布于 2024-10-17 05:56:44 字数 484 浏览 2 评论 0原文

即使关于这个主题的许多问答,我也没有找到这个问题的明确答案:

向实体类添加业务规则(即验证)的最佳设计实践是什么。

我只是想在设置底层实体值之前检查一些验证:

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

当所有属性都已存在于实体类中时,在 BLL 中从头开始创建新类是没有意义的。另一方面,实体类需要用业务逻辑规则进行扩展。

使用接口需要额外的工作,因为 DAL(实体)的更改会同时反映在接口和 BLL 类中。

我不确定从实体类继承并重写它的属性并添加额外的属性和方法是否是一个好主意。

示例伪代码对我更有帮助。

谢谢

Even many Q/A on the subject, I didn't find a clear answer for this question:

What's the best design practice for adding business rules (i.e, 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. 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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

骄傲 2024-10-24 05:56:44

我想详细阐述斯蒂芬·克利里的回答。他在 EF 中使用分部类/方法处理业务规则是正确的。但是,他没有详细说明在该部分类/方法中要做什么。我在我的博客上创建了一个 URL 缩短服务作为示例。我的 ShortURL 实体只有两列/属性。 UrlID

我想在通过 EF 将缩短的 URL 实际存储到数据库之前验证它是否是有效的 URL。所以我创建了一个分部类和方法,如下所示:

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\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"))
            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。如果有什么需要改进或者我错过了什么,请告诉我。

I would like to elaborate on Stephen Cleary's answer. He is correct in using the partial class/methods to handle business rules in 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. My ShortURL entity has only two columns/properties. Url and ID.

I wanted to validate that the URL being shortened is a valid URL before it actually stores it in the database through 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. 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. 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\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"))
            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)

    [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. Let me know if anything needs improving or if there was something I missed.

忆依然 2024-10-24 05:56:44

查看 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 是您可以执行单个属性验证或业务逻辑的地方。

Check out your EF designer-generated code.

Each property Property is actually implemented like this:

    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.

离线来电— 2024-10-24 05:56:44

Xaqron,我发现它使用部分类的最佳方式,例如,如果您的 EF 中有一个名为 PropertyListing 的类,您可以使用如下所示的部分类:

Partial Public Class PropertyListing
    Inherits EntityObject

    'Do something here

End Class

您现在可以根据需要扩展该类没有太多大惊小怪。该示例是用 VB 编写的,但您可以了解其要点

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:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文