参考、来源:http://www.cnblogs.com/Terrylee/archive/2006/04/13/374173.html

https://github.com/castleproject/ActiveRecord/blob/master/docs/validation-support.md

https://github.com/castleproject/ActiveRecord
https://github.com/castleproject/ActiveRecord/blob/master/docs/validators.md

主要内容

1.概述

2.使用Validation

3.如何扩展

4.深入分析验证

一.概述

在录入数据时,对数据有效性的验证是必不可少的,很多时候我们在UI层上就会做一层验证,但有时也需要在底层做一些必要的处理,这就要用到ActiveRecord中的数据有效性的验证。ActiveRecord为我们提供了如下几个验证:

1.ValidateEmail

2.ValidateIsUnique

3.ValidateRegExp

4.ValidateNonEmpty

5.ValidateConfirmation

需要引入:using Castle.Components.Validator; 

 

二.如何使用

为了使用上面这些验证,我们必须用ActiveRecordValidationBase来代替ActiveRecordBase,即实体类必须继承于ActiveRecordValidationBase。

[ActiveRecord("Customs")]
public class Custom : ActiveRecordValidationBase{    }

ActiveRecordValidationBase类为我们提供了如下一个方法和属性:

IsValid():返回验证是否通过
ValidationErrorMessages:获取验证错误信息数组

[ActiveRecord("Customs")]
    public class Custom : ActiveRecordValidationBase
    {
        //IsValid():返回验证是否通过
        //ValidationErrorMessages:获取验证错误信息数组
        private int _id;
        private string _name;
        private string _email;
        private string _address;
        private string _post;
        private string _phone;

        [PrimaryKey(PrimaryKeyType.Identity)]
        public int ID
        {
            get { return this._id; }
            set { this._id = value; }
        }

        [Property, ValidateNonEmpty]
        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }

        [Property, ValidateEmail]
        public string Email
        {
            get { return this._email; }
            set { this._email = value; }
        }

        [Property]
        public string Address
        {
            get { return this._address; }
            set { this._address = value; }
        }

        [Property, ValidateRegExp(@"\d{6}")]
        public string Post
        {
            get { return this._post; }
            set { this._post = value; }
        }

        [Property, ValidateRegExp(@"(\(\d{3,4}\)|\d{3,4}-)?\d{8}")]
        public string Phone
        {
            get { return this._phone; }
            set { this._phone = value; }
        }

        public static void DeleteAll()
        {
            ActiveRecordBase.DeleteAll(typeof(Custom));
        }

        public static Custom[] FindAll()
        {
            return ((Custom[])(ActiveRecordBase.FindAll(typeof(Custom))));
        }
    }

  

三.如何扩展

上面这些验证已经能够满足我们绝大多数的需求,但是我们也可以去添加自己的验证。来看看ActiveRecord中的Validation的类结构图(只画出了部分)

需要继承AbstractValidator和继承于AbstractValidationAttribute的类

四.深入分析验证

通过上面的分析我们都知道所有的实体类都继承于ActiveRecordValidationBase基类,那么ActiveRecord是如何通过特性来进行验证的呢?下面我们结合源码进一步分析一下。

我们在属性上加上了验证, Attribute并不做任何实质性的工作,它只是调用验证器进行验证,示例代码:

Model中使用:

using Castle.ActiveRecord;
using Castle.ActiveRecord.Queries;
using NHibernate;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Models
{
    [ActiveRecord("UserInfo")]
    public class UserInfo : ActiveRecordValidationBase<UserInfo>//必须继承ActiveRecordValidationBase
    {
        [Validators.ValidateIsUnique ,Property("Name")]//加入验证特性描述
        public virtual string Name { get; set; }
   } }

  

using System;
using System.Collections;
using Castle.ActiveRecord.Framework.Internal;
using NHibernate;
using NHibernate.Classic;
using NHibernate.Criterion;
using Castle.Components.Validator;//需要添加引用
using Castle.ActiveRecord;

namespace Models.Validators
{
    [Serializable]
    public class IsUniqueValidator : AbstractValidator
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="IsUniqueValidator"/> class.
        /// </summary>
        public IsUniqueValidator()
        {
        }

        /// <summary>
        /// Perform the check that the property value is unqiue in the table
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="fieldValue"></param>
        /// <returns><c>true</c> if the field is OK</returns>
        public override bool IsValid(object instance, object fieldValue)
        {
            Type instanceType = instance.GetType();//需要验证的属性 所在类
            string name = fieldValue.ToString();//属性值
       //验证逻辑
            if (name == "jay")
            {
                return true;
            }
            return false;

            //ActiveRecordModel model = ActiveRecordBase.GetModel(instance.GetType());

            //while (model != null)
            //{
            //    if (model.PrimaryKey != null)
            //    {
            //        pkModel = model.PrimaryKey;
            //    }

            //    model = model.Parent;
            //}

            //if (pkModel == null)
            //{
            //    throw new ValidationFailure("We couldn't find the primary key for " + instanceType.FullName + " so we can't ensure the uniqueness of any field. Validatior failed");
            //}

            //IsUniqueValidator.fieldValue = fieldValue;

            //SessionScope scope = null;
            //FlushMode? originalMode = null;
            //if (SessionScope.Current == null /*||
            //    SessionScope.Current.ScopeType != SessionScopeType.Transactional*/)
            //{
            //    scope = new SessionScope();
            //}
            //else
            //{
            //    originalMode = ActiveRecordBase.holder.CreateSession(instanceType).FlushMode;
            //    ActiveRecordBase.holder.CreateSession(instanceType).FlushMode = FlushMode.Never;
            //}

            //try
            //{
                //return (bool)ActiveRecordMediator.Execute(instanceType, CheckUniqueness, instance);
            //}
            //finally
            //{
            //    if (scope != null)
            //    {
            //        scope.Dispose();
            //    }

            //    if (originalMode != null)
            //    {
            //        ActiveRecordBase.holder.CreateSession(instanceType).FlushMode = originalMode ?? FlushMode.Commit;
            //    }
            //}
        }

        //private object CheckUniqueness(ISession session, object instance)
        //{
        //    ICriteria criteria = session.CreateCriteria(instance.GetType());

        //    if (Property.Name.Equals(pkModel.Property.Name, StringComparison.InvariantCultureIgnoreCase))
        //    {
        //        // IsUniqueValidator is on the PrimaryKey Property, simplify query
        //        criteria.Add(Expression.Eq(Property.Name, fieldValue));
        //    }
        //    else
        //    {
        //        object id = pkModel.Property.GetValue(instance, new object[0]);
        //        ICriterion pKeyCriteria = (id == null)
        //                                    ? Expression.IsNull(pkModel.Property.Name)
        //                                    : Expression.Eq(pkModel.Property.Name, id);
        //        criteria.Add(Expression.And(Expression.Eq(Property.Name, fieldValue), Expression.Not(pKeyCriteria)));
        //    }
        //    return criteria.List().Count == 0;
        //}

        /// <summary>
        /// Builds the error message when the property value is not unique 构造错误消息
        /// </summary>
        /// <returns></returns>
        protected override string BuildErrorMessage()
        {
            if (!String.IsNullOrEmpty(ErrorMessage))
                return ErrorMessage;
            return String.Format("{0} is currently in use. Please pick up a new {0}.", Property.Name);
        }

        /// <summary>
        /// Gets a value indicating whether this validator supports browser validation. 是否支持客户端验证
        /// </summary>
        /// <value>
        /// <see langword="true"/> if browser validation is supported; otherwise, <see langword="false"/>.
        /// </value>
        public override bool SupportsBrowserValidation
        {
            get { return false; }
        }

        /// <summary>
        /// Applies the browser validation by setting up one or
        /// more input rules on <see cref="IBrowserValidationGenerator"/>.
        /// </summary>
        /// <param name="config">The config.</param>
        /// <param name="inputType">Type of the input.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="attributes">The attributes.</param>
        /// <param name="target">The target.</param>
        public override void ApplyBrowserValidation(BrowserValidationConfiguration config, InputElementType inputType,
                                                    IBrowserValidationGenerator generator, IDictionary attributes, string target)
        {
        }
    }
}

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Castle.ActiveRecord.Framework.Validators;
using Castle.Components.Validator;

namespace Models.Validators
{
    /// <summary>
    /// Validate that the property's value is unique in the database when saved
    /// </summary>
    [Serializable]
    public class ValidateIsUniqueAttribute : AbstractValidationAttribute
    {
        private readonly IValidator validator;

        /// <summary>
        /// Initializes a new instance of the <see cref="ValidateIsUniqueAttribute"/> class.
        /// </summary>
        public ValidateIsUniqueAttribute()
        {
            validator = new IsUniqueValidator();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ValidateIsUniqueAttribute"/> class.
        /// </summary>
        /// <param name="errorMessage">The error message.</param>
        public ValidateIsUniqueAttribute(String errorMessage)
            : base(errorMessage)
        {
            validator = new IsUniqueValidator();
        }

        /// <summary>
        /// Constructs and configures an <see cref="IValidator"/>
        /// instance based on the properties set on the attribute instance.
        /// </summary>
        /// <returns></returns>
        public override IValidator Build()
        {
            ConfigureValidatorMessage(validator);
            return validator;
        }
    }
}

  

前台使用:

protected void Button6_Click(object sender, EventArgs e)
        {
            Models.UserInfo tui = new Models.UserInfo();
            tui.Name = TextBox2.Text;
            if (tui.IsValid())
            {
                ltlMsg.Text = "验证通过";
            }
            else
            {
                ltlMsg.Text = "验证失败";
            }
        }

  

五、启动程序时,可以初始化数据、根据模型生成数据表、运行指定的Sql文件创建数据库:

 protected void Application_Start(object sender, EventArgs e)
        {
            // 在应用程序启动时运行的代码
            //AuthConfig.RegisterOpenAuth();
            //RouteConfig.RegisterRoutes(RouteTable.Routes);
            InitActiveRecord();
        }

        //Castle Record Register Model
        private void InitActiveRecord()
        {
            try
            {
                //加载配置文件
                string NHibernateFilePath = Server.MapPath("~/NHibernate.config");
                XmlConfigurationSource source = new XmlConfigurationSource(NHibernateFilePath);
                //注册数据模型
                ActiveRecordStarter.Initialize(source, typeof(Models.LogInfo), typeof(Models.UserInfo), typeof(Models.ThemeInfo), typeof(Models.CommentInfo), typeof(Models.CategoryInfo));
                //根据模型生成数据库
                //ActiveRecordStarter.CreateSchema();
                //运行指定的数据库脚本生成数据库等
                //ActiveRecordStarter.CreateSchemaFromFile("MySqlScript.sql");
            }
            catch (Exception)
            {
                throw;
            }
        }

  

六.使用空属类型

在进行数据库操作时,有时候需要进行空值的处理,在ActiveRecord中给我们提供了一组空属类型,可以方便的进行处理,比如可以这样写属性:

[Property("CreateDate")]
public virtual Nullable<DateTime> CreateDate { get; set; }

 

七.使用枚举类型

定义:
        public enum StatusType
        {
            Editing = 0,
            Published = 1,
            Archived = 2
        }
        [Property("status_id")]
        public virtual StatusType Status { get; set; }

使用:
        Models.UserInfo userinfo = new Models.UserInfo();
        userinfo.Status = Models.UserInfo.StatusType.Archived;        

  

八.Hooks
有时候我们会在保存,加载,删除等操作时做一些必需的处理,这时可以通过重载以下三个方法来实现:

BeforeSave(IDictionary state)
BeforeLoad(IDictionary state)
BeforeDelete(IDictionary state)

比如说我们想在保存的时候设置创建时间为当前时间,可以这样去写:

protected override bool BeforeSave(IDictionary state)
{
    state["Created"] = DateTime.Now;
    return true;
}

 

posted on 2016-03-24 14:16  邢帅杰  阅读(326)  评论(0编辑  收藏  举报