Aspen – part 7 of X – Entity Validations

Dag König and I had a meeting today about the Aspen project. We talked most of the time about validations and how we should implement it. I decided to post about the current decision made.

Validation on Entity level


Sometimes it feels important to add validation to an entity, for example a FirstName can’t have a size greater than X characters etc. But is it important? The main reason why such validation may be of interest is based on the limitation set on the data source. The column FirstName in the database is set to nvarhcar(XX). But should we really add a validation like the following to the entity because of that?

public class Member
{
    private string _firstName;
        
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (string.IsNullOrEmpty(value))
                 throw new ArgumentNullException("FirstName");

             if (value.Length > 20)
                 throw new ArgumentOutOfRangeException("FirstName", 
                                  "FirstName can not have more than 20 chars");

              _firstName = value;
         }
    }
}

In real life a company will probably not lose any business because of the length of the FirstName, so the domain model in that case shouldn’t really care about doing the validation, or?! The only reason the validation is there now is because of the constraint added to the data source, but it’s not a constraint for the business. In this case I think that kind of length validation is not important to have in the entity at all, it’s irrelevant for the business. I prefer to not have that kind of logic into my entities, instead I will let the data source throw an exception if the chars exceeds XX numbers of chars. In this case the data source will do the validation. Some of you may say “But by adding the validation to the entity, there will not be any database access, and that will increase performance”. That is true. But how often will the FirstName really exceed the XX numbers of chars? If we use a sophisticated ORM, we can also specify in the mapping between the domain model and database schema, the length of the field etc, and let the ORM do the validation before it tries to persist the model. nHibernate will do it for us, but I haven’t seen a way of doing it with Entity Framework 4 code-only and I’m against adding attributes to my entities. Will not make them a pure POCO. One benefit by adding validation to the entity, would be to prevent a developers for using the entity in a wrong way. He/she will be notified early if the FirstName exceeds 20 chars. But I don’t think it’s up to the domain model to care about performing validation based on a data source constraint.

I will only add the above validation if that is really a business rule.


Note: The empty string validation in the code is important, if we don’t have a FirstName we can lose business.

Should we always let the database handle the validation based on exceptions?

If we skip the length validation in our FirstName property, the validation will take place by the database. It will throw an exception if the FirstName exceeds the length of the specified ncharchar(XX). So stupid, why should we do the data access in the first place and waste some resources others action can use instead? The answer is, we can do the validation, but not on the entity level, more about that later under the topic “User Interface Validation”. If we use a sophisticated ORM, we can let it perform a validation before the entity is persisted.


Rule based validation

There can be a problem by adding validations to the entity or even to other parts of the domain model, for example to the Repositories. Some specific validations can be based on a specific business case or the context the entity is in. If we add validation to the entity, the validation will always take place but in one specific context that kind of validation isn’t important and can stop us for performing a specific business case. So instead of adding validations to the Entity, we perform validations based on the context the entity is in. The validation can for example take place in service/application layer. This can be done in several ways, for example in a simple method where the method will validate the entity’s values. This is the approach we are going to use. The following methods will do different kind of validations of the member entity based on its context.

ValidateMemberBeforeRegisterTheMember(member);

ValidateMemberBeforeUpdatingTheMember(member);



User Interface Validation


WCF RIA Services supports annotation validations, so we can on our DTO for example add validation attributes to properties. WCF RIA Services together with Silverlight binding validation can perform validations on the client-side, WCF RIA Services will also do the validation on the server-side. So instead of adding validation such as length validations to an entity, it can instead be added to the Presentation layer and the Service layer. The following is an example where the WCF RIA Services annotation validation is used:

public class MemberDto
{
    [Key]
    public int ID { get; set; }

    [Required]
    [StringLength(20)]
    public string FirstName { get; set; }

    ...
}


Is someone succeeds to by pass the DomainService and try to add entity, the database will throw an exception if the length of the the FirstName exceeds for example 20 chars. How often will that happen. Well probably never, and if it does, the database will to the last validation.

Based on our business case, we decide to not add length or other kind of constraints for our entities. I would really like to have your comments about this and what solution you prefer to use.



If you want to know when I add a new blog post, please follow me on twitter: http://www.twitter.com/fredrikn

14 Comments

  • Hello Frederick

    How do you configure the Factory Classes that holds Database Adapter configuration ( I mean the factory Classess) for Entity Data Models. Do you maintain 3 rd party tools for this or you create own.? If you explain or publish an article on Database Adapter Configuration, it will be of great help as it might open chance to think about Multiple Database Scenarios. Please reply

    Best Regards
    Dhinesh Kumar

  • Hello

    To be more precise, i would like to know about Entity Client provider implementation using factory classes.If you are capturing in your ASPEN project, please share.

    regards
    Dhinesh Kumar

  • Hello Frederick and Dag Konig

    It is nice to see your ASPEN Project available in Code plex today. I would like to know about the EDMX file being disappearing in the aspen project but the Entities and Entity Mappings are present in it. Is it purposely removed from Solution after the Domain Models being created, please explain. For N tier apps, is it a practise not to have the Domain Models as diagram

    Regards
    Dhinesh Kumar

  • Sorry My question was wrong. I understood now that the app is built based on code- only EF. Hence please ignore my post.

    regards
    Dhinesh Kumar

  • Hello All

    There was error when i try to build the aspen solution. I had just configured the web.config for database setting as below



    When i open Fdd.Aspen.ClientTestPage.aspx in view browser, im getting the following error

    Microsoft JScript runtime error: Unhandled Error in Silverlight 2 Application Load operation failed for query 'GetMembers'.

    Resolution of the dependency failed, type = 'Fdd.Aspen.Services.Web.MemberDomainService', name = ''.

    Exception message is:


    The current build operation (build key Build Key[Fdd.Aspen.Services.Web.MemberDomainService, null]) failed:

    The parameter

    membershipRepository could not be resolved when attempting to call constructor Fdd.Aspen.Services.Web.MemberDomainService

    (Fdd.Aspen.DomainModel.Repositories.IMemberRepository membershipRepository,

    Fdd.Aspen.DomainModel.Repositories.IGatheringRepository gatheringRepository).

    (Strategy type BuildPlanStrategy, index 3) at

    Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
    at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name)
    at Microsoft.Practices.Unity.UnityContainerBase.Resolve(Type t)
    at WcfRiaServices.Extensions.UnityDomainServiceFactory.CreateDomainService(Type domainServiceType, DomainServiceContext

    context) in N:MyProjectsVS2010WCF_RIA_SamplesFREDERICK NORMANaspen-

    40251Fdd.AspenWcfRiaServices.ExtensionsUnityDomainServisceFactory.cs:line 26
    at System.Web.Ria.Services.DomainOperationInvoker.GetDomainService(Object instance)

    Please help.

    regards
    Dhinesh Kumar


  • @Dhinesh Kumar:
    The source code is far from done, it shouldn't be available at all yet, but we had to publish the Aspen projet. There is no GUI implemented and some changes will be made.. now it's still only on a testing level to setup the infrastructure correct etc.

  • Hi Fredrik, first, thanks to share your experience with us.
    Now, you decided to not put validation attributes on your entities because you want your model to be clean, why not.
    But personally, I prefer to have all "business rules" at the same place (even if you don't think length validation is a business rule, I don't really agree with you) and applying some rules using attributes and other using methods.

    Why I think length validation or required field validation are business rule os because it implies that user do something.

    So my prefered solution is to create validator depending on the context and put these validators on the domain.

    Best regards.


  • @Sylvain:
    If your bunsiess case require lenght validation and required field to not lose any business, it should be part of the domain model.The problem with attribute is that attribute only hold informations, so if you want to write a unit test to test your business case, you need tools to execute the validation rules. So you can't just write: myObject.MyProppery = null; and get the Required attribute to be executed by it self.

  • First thanks to share your experience with us.
    Concerning where technical validation (required field, field length, ...) must be done, I prefer to put it in the same place as other validations (say business rules).
    1) I don't really like to have to search in different places to see all rules, I'm lazy.
    2) Because user will have to do something to correct this matter, I first consider technical as RULES and so will put it in the same place as other : domain
    3) Where would you put a rule like this ? "If member is a women, the maiden name must be filled". Personnally, in domain. If using your way to do it, some people would probably put it in application service layer using an attribute.


  • Sorry to post twice...


  • @Sylvain:
    3) It depends ;) I would probably put it in the domain model. There is no direct answer on this one.. maybe my midel is created in a way where I have two kind of members, women and men.. both are two seperated objects.. in that case Women specific validations can the then be put into the Women class..  In some cases the logic maybe don't fit the entity, and in that case is would be added to the domain service etc.

  • And what do you think about using something like Contract.Requires method instead of the attributes?


  • @Sylvain:
    Contract is to make sure the user uses the code in a correct way, it shouldn't be used as a way to handle busniness validations.

  • Ok but in fact, as the attibutes you acually use.
    And as you said the difference is that Contract.Requires will be used also during unit tests.

    Personaly, I used to use the "AssertUtils class" of Spring .Net instead of "normal Assert" which are disabled in release mode.

Comments have been disabled for this content.