zoukankan      html  css  js  c++  java
  • Castle ActiveRecord学习(六)数据验证

    参考、来源: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;
    }
    
  • 相关阅读:
    电脑不能连接到热点
    常用网络协议
    HVV面试
    【转载】hacker术语
    渗透测试学习路线
    系统安全——可信计算
    rsync文件同步详解
    rabbitmq集群部署高可用配置
    ansible自动化部署之路笔记
    ELK-elasticsearch-6.3.2部署
  • 原文地址:https://www.cnblogs.com/xsj1989/p/5315351.html
Copyright © 2011-2022 走看看