zoukankan      html  css  js  c++  java
  • 实现UniqueAttribute唯一性约束-优化版

    我之前就写过一篇《实现UniqueAttribute唯一性约束》,虽然实现了通过调用IsValid方法可以进行唯一性验证,但有一个缺点,那就是耦合度过高,原因是里面的DB上下文对象是直接写在里面的,如下:

    public override Boolean IsValid(Object value)
            {
                bool validResult = false;
                //TEMSContext 是我项目中的DB上下文类,这里是直接指定的,与TEMSContext 紧耦合,若需要实体与访问分离就会有问题!
                using (TEMSContext context = new TEMSContext())
                {
                   string sqlCmd=string.Format("select count(1) from [{0}] where [{1}]=@p0",tableName,filedName);
                   context.Database.Connection.Open();
                   var cmd=context.Database.Connection.CreateCommand();
                   cmd.CommandText = sqlCmd;
                   var p0 = cmd.CreateParameter();
                   p0.ParameterName = "@p0";
                   p0.Value = value;
                   cmd.Parameters.Add(p0);
                   int result=Convert.ToInt32(cmd.ExecuteScalar());
                    validResult=(result<=0);
                }
                return validResult;
            }
    

    现在为了解决这个问题,我目前采用的是通过属性注入DB上下文类型,然后再采取反射动态创建实例,这样就降低了依赖,完整代码如下:

    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Data.Entity;
    
    namespace Zwj.TEMS.Common
    {
        /// <summary>
        /// 唯一性标识
        /// </summary>
        [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
        public class UniqueAttribute : ValidationAttribute
        {
            protected string tableName;
            protected string filedName;
    
            public Type ContextType { private get; set; }
    
            public UniqueAttribute(string tableName, string filedName)
            {
                this.tableName = tableName;
                this.filedName = filedName;
            }
    
            public override Boolean IsValid(Object value)
            {
                //如果是系统调用,就不会传入ContextType类型,所以此处就直接返回通过
                if (this.ContextType == null)
                {
                    return true;
                }
    
                bool validResult = false;
               using (DbContext context = ContextType.Assembly.CreateInstance(ContextType.FullName) as DbContext)
                {
                    string sqlCmd = string.Format("select count(1) from [{0}] where [{1}]=@p0", tableName, filedName);
                    context.Database.Connection.Open();
                    var cmd = context.Database.Connection.CreateCommand();
                    cmd.CommandText = sqlCmd;
                    var p0 = cmd.CreateParameter();
                    p0.ParameterName = "@p0";
                    p0.Value = value;
                    cmd.Parameters.Add(p0);
                    int result = Convert.ToInt32(cmd.ExecuteScalar());
                    validResult = (result <= 0);
                    context.Database.Connection.Close();
                }
                return validResult;
            }
        }
    }
    

    这样虽然降低了对实际DB上下文的依赖,但新问题又出来了,就是如果通过手动来验证该特性(如下代码)就没有问题,但如是想让EF框架在RUD时能自动验证,则会出现问题,因为没有传入ContextType,所以也就无法进行验证,我想这也是微软之所以没有实现UniqueAttribute唯一性约束的原因吧,不知道哪位高手能指点一下,非常感谢!

    以下是手动来验证该特性:

            public void ValidateEntity(object entity)
            {
                var t = entity.GetType();
                var properties = t.GetProperties();
                foreach (var p in properties)
                {
                    UniqueAttribute[] attrs;
                    if (p.TryGetAttribute<UniqueAttribute>(out attrs))
                    {
                        attrs[0].ContextType=typeof(TEMSContext);
                        bool result = attrs[0].IsValid(p.GetValue(entity, null));
                        Assert.IsTrue(result, "验证不唯一,存在重复值!");
                    }
                }
            }
    

      

  • 相关阅读:
    使用PHP获取用户客户端真实IP的解决方案
    PHP中使用mkdir创建多级目录的方法
    javascript中将字符串转换为json格式的三种方法
    Codeigniter处理用户登录验证后URL跳转
    PHP正则表达式匹配URL中的域名
    开源项目列表
    PG JDBC COPY感谢原作者
    if中return的用法
    读数据库查询的 ResultSet时java.sql.SQLException: 流已被关闭
    一篇讲JAVA JDBC的好文章
  • 原文地址:https://www.cnblogs.com/zuowj/p/4397943.html
Copyright © 2011-2022 走看看