Validation in Linq to SQL and ASP.NET

In this article, I will show how to add business rules to Linq to SQL data model default set of schemas.


Introduction

One important aspect of every enterprise application is the validation of business rules. In this article, I will show how to add business rules to Linq to SQL data model default set of schemas. When we define a LINQ to SQL data model, we will automatically have a default set of schema based validation constraints added to our data model classes.  For example, if you try to set a null value for a required column, then the LINQ to SQL data model will raise an error to ensure our database integrity is maintained. Although, it's very common to add additional business rules and application-level validation to our data model classes, and this is the case that I will explain in my article.

Getting started with the solution

For this example, we're going to use the Department entity whose instances' state will be stored in the dbo.Department table in an SQL Server database. The schema for this table is shown in the Listing 1.

CREATE TABLE [dbo].[Department](
          [DeptID] [int] NOT NULL,
          [DeptName] [varchar](50) NOT NULL,
          [Location] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED
(
          [DeptID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

Listing 1

Now, let's see where to implement the business rules of the enterprise application. Adding the business rules in the UI layer of our application means that the rule will be specific to only that one place, and this will not be automatically enforced when we add another UI to update the departments. So, the solution is to place the business logic validation in the SQL data model classes.

In order to illustrate this example, we're going to create a Web site solution in Visual Studio.NET 2008 and then add a Linq to SQL artifact inside it. Finally, drag and drop the Department table inside the Linq to SQL designer (see Figure 1).

1.gif
 
Figure 1

If you look inside the generated code for the Linq to SQL designer, all classes are defined as partial and you can see the code generated for the Department class.  So in order to call validation methods that implement the custom validation logic, we have to override the OnValidate method of the Department partial class.

Now inside the OnValidate method, we have to code the validation logic. Let's suppose in our example that we don't want to have departments from NY. So, the validation code is shown in the Listing 2.

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

/// <summary>
/// Summary description for Department
/// </summary>
public partial class Department
{
    partial void OnValidate(System.Data.Linq.ChangeAction action)
    {
        if (this.Location.Equals("NY"))
        {
            throw new ArgumentException("Location can't be equal to NY");
        }
    }
}

Listing 2

Once we add the above validation code into the OnValidate method of the Department class definition, then the business rule will be enforced anytime we try to modify the database.

Next step is to show the validation error in a friend way to the users. In this case, we're going to use LinqDataSource control's mechanism for such a purpose, so we do not need to-do anything to our UI tier in order for this validation to occur - it will automatically be applied anywhere and everywhere our LINQ to SQL data model is used.

Next step is to go to the Default.aspx page. Let's add an error panel (see Listing 3).

<span id="spErrorPanel">
<asp:Literal id="ltrErrorMessage" runat="server" />
</span>

Listing 3

Next step is to add LinqDataSource control and configure it to the previously created Linq to SQL data model. (see Figure 2).

2.gif
 
Figure 2

You need to active the Enable Update option as well in the LinqDataSource (see Figure 3).

3.gif
 
Figure 3

Finally, let's add a GridView control to the page and link the GridView control to the LinqDataSource control.

By default when a user uses our GridView control to enter a non-valid value, the LINQ to SQL data model classes will raise an exception and the LinqDataSource control will in turn catch this error and provides an event that users can use to handle it. If the error is not handled, then it will be passed up to the Page to handle, and so on to the global Application_Error() event handler in the Global.asax file.

In our application, we're going to manage any update errors by handling the RowUpdated event on our GridView. This event will get fired every time an update is attempted on our LinqDataSource, and we can access the exception error details if the update event fails.

The code for the RowUpdated event is shown in the Listing 4.

protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
    if (e.Exception != null)
    {
        this.ltrErrorMessage.Text = e.Exception.Message;
        e.ExceptionHandled = true;
        e.KeepInEditMode = true;
    }
    else
    {
        this.ltrErrorMessage.Text = "";
    }
}

Listing 4

Conclusion

In this article, I've shown show how to add business rules to Linq to SQL data model default set of schemas. Now you can add your own business rules to your data model.