Re: Question about Validation Rules - Support - .netTiers - CodeSmith Community
Welcome to the CodeSmith Community!

Re: Question about Validation Rules

.netTiers

A description has not yet been added to this group.

Question about Validation Rules

  • rated by 0 users
  • This post has 8 Replies |
  • 4 Followers
  • Hi!

    Suppose you have a web interface (ASP.NET) to enter information about new clients, and that one of the rules you want to implement is that two clients cannot have the same name. Where would you put the validation for this or for similar scenarios? At first, I thought I would simply write a new Validation Rule and add it in my Client.AddValidationRules() method. However, I need to access the database through the Service Layer in order to make sure that the Client Name does not already exist in the DB, and the Validation Rules are in the Entitites namespace, which does not know anything about the database and the Service Layer. Where should such validation be done then? I have many similar cases to implement.

    Cheers!

    JF 

  • velum,
     

    It could be achieved via processors (a logical unit of work) check here for an example http://wiki.nettiers.com/componentlayer

    You would then override any of your methods in the service layer to insert  this process into a business process pipeline like following:

            public override bool Insert(Order entity)
            {
                ProcessorList.Add(new InventoryProcessor(entity));
                Execute();
                return base.Insert(entity);
            }

    velum:

    Hi!

    Suppose you have a web interface (ASP.NET) to enter information about new clients, and that one of the rules you want to implement is that two clients cannot have the same name. Where would you put the validation for this or for similar scenarios? At first, I thought I would simply write a new Validation Rule and add it in my Client.AddValidationRules() method. However, I need to access the database through the Service Layer in order to make sure that the Client Name does not already exist in the DB, and the Validation Rules are in the Entitites namespace, which does not know anything about the database and the Service Layer. Where should such validation be done then? I have many similar cases to implement.

    Cheers!

    JF 

    Mike Shatny
    --------------------------------------------------------------
    Member of the .netTiers team http://www.nettiers.com
    --------------------------------------------------------------

  • Thanks Mike!

    This looks like exactly what I need. It looks simple, but somehow all these things about processors and validators was a bit blurry in my mind.

    Cheers! 

    JF


     

  • Hey velum,

    Yeah, it may sound easy, and it is actually easy once things are clear Big Smile

    Here is another example, of the class that resides in the Service Layer called VerifyCountryProcessor.cs. Its' responsibility to create a broken rule and add it to the BrokenRulesList of the process result if the rule is invalid

    using System;
    using System.Collections.Generic;
    using System.Text;

    using NetTiers.Data;
    using NetTiers.Entities;
    using NetTiers.Services;

    namespace NetTiers.Services.Pipline
    {
        /// <summary>
        /// Processor to verify Country Name if exists in Database
        /// </summary>
        public class VerifyCountryProcessor : ProcessorBase
        {
            private Entities.Country _country;
            private GenericProcessorResult genericProcessorResult;

            /// <summary>
            /// Country Processor
            /// </summary>
            /// <param name="country"></param>
            public VerifyCountryProcessor(Entities.Country country)
            {
                this._country = country;
            }

            /// <summary>
            /// Process the IProcessResult
            /// </summary>
            /// <returns></returns>
            public override IProcessorResult Process()
            {
                _country.AddValidationRuleHandler(ValidateIfCountryExists, "CountryExists");

                //check country
                _country.Validate();

                if (!_country.IsValid)
                    ProcessResult.AddBrokenRulesList(typeof(Entities.Country), _country.BrokenRulesList);

                return ProcessResult;
            }
           
            private bool ValidateIfCountryExists(object target, Entities.Validation.ValidationRuleArgs e)
            {

                CountryService CountryService = new CountryService();

                string Where = string.Format("CountryName = '{0}'", _country.CountryName);
                TList<Country> CountryList = CountryService.Find(Where);

                e.Description = string.Format("The {0} already exists and cannot be added or updated.", _country.CountryName);
               
                if (CountryList.Count > 0 && _country.CountryId == CountryList[0].CountryId)
                {
                    return true;
                }
                else if (CountryList.Count > 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
               
            }

            /// <summary>
            /// ProcessResult
            /// </summary>
            public override IProcessorResult ProcessResult
            {
                get
                {
                    if (genericProcessorResult == null)
                    {
                        genericProcessorResult = new GenericProcessorResult();

                    }
                    return genericProcessorResult;
                }
            }
        }
    }

     

    velum:

    Thanks Mike!

    This looks like exactly what I need. It looks simple, but somehow all these things about processors and validators was a bit blurry in my mind.

    Cheers! 

    JF


     

    Mike Shatny
    --------------------------------------------------------------
    Member of the .netTiers team http://www.nettiers.com
    --------------------------------------------------------------

  •  public override bool Insert(Order entity)
            {
                ProcessorList.Add(new InventoryProcessor(entity));
                Execute();
                return base.Insert(entity);
            }

     

    This code pointless if you actually care about the ServiceResult returned by the InventoryProcessor because your entity will still be saved unless the InventoryProcessor method throws an error?

  • Hi Mike and All!

    I have been using the method suggested by Mike to add validation to entities in my project for quite some time, and it has been working fine. However, I noticed at some point that when an entity is being saved (inserted or updated), it is getting validated multiple times. It is only this week that I had time to investigate this, and I found out that my entities are validated three times when they are saved. This is not necessary and it slows downs my application uselessly, especially when access to the database is required for validation. For example, I have a "ClientCoor" entity in my application. Here is the update method I am using for it:

            public override bool Update(ClientCoor entity)
            {
                    ProcessorList.Add(new ClientCoorProcessor(entity));
                    ServiceResult result = Execute();
                    return base.Update(entity);
            }

    However, the above method calls the ValidateClientCoor() method of the ClientCoorProcessor class three times. It is called twice by the Execute() method. This method eventually calls the Process() method of the ClientCoorProcessor class which calls _clientCoor.Validate() and a few lines below it access the IsValid property which also calls the Validate() method:

                    //check clientCoor
                    _clientCoor.Validate();

                    if (!_clientCoor.IsValid)
                        ProcessResult.AddBrokenRulesList(typeof(Entities.ClientCoor), _clientCoor.BrokenRulesList);

    Then, it is called again when base.Update(entity) is called. This method accesses IsValid, and as mentioned above, the "geter" of this property calles Validate().

    Has anyone ever noticed this? Does anyone have a fix for this problem?

    Cheers!

    JF

  • It really sounds like we need to keep track of when an Entity is valid.  I imagine that the Call to IsValid should only call validation once.  Once a value or something has changed on the Entity, the next time it should know that something changed and call Validate again.  This sounds trivial, but it isn't.  It is easy to do for 1 entity, but when you factor in child collections and what not it gets a little more interesting.

    I will try and look over this.  Maybe the calls to IsValid can be removed.  Not sure.

    jeff

    ----------------------------------------------------------------------
     Member of the .NetTiers team | Visit http://www.nettiers.com
    ----------------------------------------------------------------------

  • Hi Jeff!

    As far as I can see, we would need another property similar to the IsDirty flag, but instead of keeping track of whether the entity has been modified since it has been loaded, we would have to keep track of whehter the entity has been modified since the last validation.

    In your message, you say "Maybe the calls to IsValid can be removed". Which of the references to that property are you considering removing? I was rather wondering whether the call to Validate() could be removed from the IsValid geter. It would then be the responsibility of the developer to issue a call to Validate() at some point in order to set the value of IsValid. Of course, this would not be the best solution. Ideally, a property to keep track of whether the entity has changed since the last validation should be added. IsValid could then call Validate() in the case where the entity would have been modified.

    Cheers!

    JF

  • I was suggesting more to look and see if some could be removed....I haven't looked at removing any of them.

    You are right about the IsDirty way of looking at it.  I think that is the way to fix this.  This wouldn't be too bad to do actually, just have to change where we are setting the dirty flags and set another flag.  Of course, you never know, but not too hard.

    jeff

    ----------------------------------------------------------------------
     Member of the .NetTiers team | Visit http://www.nettiers.com
    ----------------------------------------------------------------------

Page 1 of 1 (9 items)