Entity framework Data Validation

So it’s been a while since I posted something on my blog.
The main reason is because I was on holiday. But know I’m back, I just need to write something 🙂

I’m still experimenting with Entity Framework for a project I’m doing.
And today I want to share a basis concept about data validation.
Again I’ll keep it very straight forwarded. In my search to learn about EF, I find a lot but mostly the examples I find are to difficult or to big for me.

I wanted two things important things. The give a warning when a user wants to add something with an ID that already exists and to give a warning when he didn’t filled in a field that is necessary.
First I was thinking to change the border of the textbox to red the visualize an error. This is quite simple. But than I wanted to add a tooltip to show the error message.
I learned that adding tooltips programmely in WPF isn’t that logical. After some searching I fixed it, but I couldn’t change the duration of the tooltip. It just won’t listen…

So I gave up on that and founded the lovely world of data validation. It’s can be achieved in many ways. But I’m going to use the IDataErrorInfo interface.
If you add this interface you have to implement two properties: public string Error and string this[string columnName]

The first property is to say if there is something wrong with the entire object. We won’t need this one.
The second is to say if there is something wrong with a property of the object, just what I need because ID and Naam (the property that is necessary) are both properties!

How does it work:

partial class Klant : IDataErrorInfo
{
    public string Error
    {
        get
        {
            return "";
        }
    }

    public string this[string columnName]
    {
        get
        {
            string result = null;

            switch (columnName)
            {
                case "Naam":
                {
                    if (String.IsNullOrWhiteSpace(Naam))
                        result = "Naam is obligatory!!!";
                    else if (Naam.Length > 50)
                        result = "Naam has a max length of 50 characters!";
                    break;
                }
             }

             return result;

        }
    }
}

So first, I use DB first in Entity Framework. So I can’t change my model classes inside the file. Because the changes would be overwritten every time EF has to rebuild the files (when I changed something in the database).
But no worries the class that EF generates is partial. So that means that you can edit that class in another file.
Just make another .cs file use the same name for the class (in my example “Klant”) put partial before it and done. This is how you change a class in an another file!

You add the interface and click implement interface. The needed properties will automatically added and done. I left the Error property for what is was.
The other one I changed to my demands.
First you check what the name if of the column that changed. You can replace the word column in my previous sentance with property.
If the columnName is Naam, I know something changed to the “Naam” of the “Klant”. First I check if the new value is empty or only exists out of white-spaces. If this is the case I put the error I want in the string result.
If this wasn’t the case I check for the length (SQL varchar has a max amount of chars) if this is to long, i’ll put another error message in result.
At the end you simply return this value!

And done! Now you have to change your XAML to show errors.

<TextBox Grid.Row="1" Margin="0,10,0,0" Grid.Column="1" Text="{Binding Naam, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True}></TextBox>

This is my textbox. Note the ValidatesOnDataErrors and NotifyOnValidationError! The first one I’ll need to show the error. The other one I’ll explain later.
If you added this you should get something like this:

Simple Error

Still no error message, only a red border!…
You could add a tooltip with the correct message in XAML. But I wanted something more 🙂
I founded this: http://stackoverflow.com/a/7437765/2961887
I really liked that error message. So I added it to my project.
I removed the Multibinding and the Converter (I didn’t need the animation when you hovers over the small triangle) and added the style in App.xaml so I could use it every where!
Finally I used a setter in my resources to add this to every textbox on my Window/Usercontrol:







<Style TargetType="{x:Type TextBox}>
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource errorTemplateSilverlightStyle}">
</Style>






Now I have this:

Blog2

The next problem was that I want an error when you choose an ID that already is in use (ID is my primary key).
But I didn’t have my collection of al the clients (Klanten) in my model class Klant. So I couldn’t check for unicity!
I tried a lot but nothing I did was satisfying. I searched a lot but every answer was to difficult for me (I really need to check out MVVM). So this is my solution on the question: How to check if primary key is unique in your model

I had an idea to add a Entity class en load all the clients in my model. But I feared that this was going to take a while and as consequence the app would feel slow.
But because I was desperate, I tried it. And it works better than I imagined. It works immediately! So my guess is that EF caches the data somewhere.
So in code:

case "ID":
{
    DataEntities entity = new DataEntities();
    if ((entity.Klanten.Any(k => k.ID == ID)))
    {
        result = "ID is already in use";
    }
}
break;

So know we have the collections of all the clients (Klanten) and with a simple LINQ query I was able to determine if the ID already exists!
Primary Key Unicity Error

A next thing I would like to say, is conversion errors. If you bind an integer to a textbox there should come an error if you type in a string!
In fact this goes automatically without the need to add any code (except add “ValidatesOnDataErrors” to the textbox).
Here an example:

Blog4

The text in English = Value ErazerBrecht couldn’t be converted

Check if there are errors!?

Now as last I want to share how I disabled the save button when there are validation errors. My first idea was to add a bool in my model class (Klant) that become true when there are errors.
Not so difficult just add the correct logic in the “public string this[string columnName]” part. And than bind the IsEnabled to that bool.
This works fine if you don’t need the conversion errors. Because they don’t happen in that interface the bool will never be set.
To solve this I just add an event to my grid. This event is called the Validation.Error event.

<Grid Name="GridInformation" Validation.Error="GridInformation_Error">
int _numberofErrors = 0;
private void GridInformation_Error(object sender, ValidationErrorEventArgs e)
{
    if (e.Action.ToString() == "Added")
    {
        ButtonSave.IsEnabled = false;
        _numberofErrors++;
    }
    else
    {
        _numberofErrors--;
        if (_numberofErrors < 1)
            ButtonSave.IsEnabled = true;
    }
}

As far as I know there is no parameter that gets the amount of errors. So made something myself. The code is quite self-explanatory.
So know you can’t save a new client if there are errors in the grid!

Endresult DataValidation

Mission successful!

If someone know better solutions for my problems please share them in the comments.
As I once said, it’s the first time I use EF. And I try to search for solutions that are not that difficult!
I hope you enjoyed reading!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s