2

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

3
  • are your entity framework classes also your domain model? or do you have seperate classes? Commented Feb 10, 2011 at 0:39
  • Are you using Entity object's or POCOs? Commented Feb 10, 2011 at 8:46
  • @Ladislav: I'm using EF from Visual Studio 2010 Commented Feb 10, 2011 at 12:30

3 Answers 3

4

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\-\.,@?^=%&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)

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

Sign up to request clarification or add additional context in comments.

3 Comments

Actually, it's ASP.NET MVC that's swallowing the exception, not EF.
Oh? Do you know where, and is it over-ridable?
Ah, I found the article that backs up my answer. IDataErrorInfo is the only way that I can find to expose custom validation error messages in asp.net MVC. sellsbrothers.com/posts/Details/12700. Throwing the exception does work, but you cannot specify the message that the validation helpers expose to the user. Furthermore, you don't have to throw an exception if you implement IDataErrorInfo as it checks that collection when validating the model. Simply adding the error to the dictionary is enough to invalidate the model.
3

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.

4 Comments

@Stephen: I need a separate project as my BLL. Something like a wrapper over EF. Is there any online sample of your suggested approach ?
MSDN on partial classes and methods. I'm not sure why you need your BLL DLL to be separate from the DLL containing EF, since your EF classes are your BLL...
Great answer! +1, now I can do model validation on my EF entities. However, when I am in the partial method, how do I return invalid? The partial method returns void, how do I stop the property from changing when I determine the value is invalid?
I did that, but EF seems to handle the exception somewhere. So even though the property doesn't get set, I don't get immediately notified that an exception was thrown. I ended up making my partial class inherit from IDataErrorInfo. I then added a private dictionary variable that would contain the property name as the key and the error message as the value. The IDataErrorInfo forces you to handle a string property that gets the error by column, which you then pass as the key to the dictionary object and return the message.
2

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

1 Comment

And what if I need to override something ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.