实现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}][email protected]",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}][email protected]", 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, "验证不唯一,存在重复值!");
                }
            }
        }

  

时间: 2024-08-12 14:36:41

实现UniqueAttribute唯一性约束-优化版的相关文章

解决数据库报唯一性约束错误的实践

猿们好,我是honery,今天来给大家唠一唠如何避免数据库报唯一性约束的错误. 一.问题的引出 ??首先抛出一个问题,如何保证数据库表中的某列的值都不一样呢?相信大家很容易想到给该列加上唯一性约束,这样就能保证业务逻辑的正确性了.实际的使用中,尤其高并发场景下,很容易出现插入同一条记录的情况,该情况下数据库会报违反唯一性约束的错误.总不能让数据库一直抛这个错误吧.于是我们想到可以在业务代码中加上该列值是否为空的判断,判断为空时再行插入,于是问题就解决了. ??问题真的解决了吗?说是,你就too

POJ-2533最长上升子序列(DP+二分)(优化版)

Longest Ordered Subsequence Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 41944   Accepted: 18453 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ...

主键约束,唯一性约束,唯一性索引

1)主键列:比如我们在表A中指定ID为主键,Oracle数据库会自动创建一个同名的唯一索引 可以通过 select constraint_name,constraint_type from user_indexes ui where ui.table_name='A'来查看主键上的唯一索引,如果此时我们在给ID列去创建唯一性索引或者非唯一性索引的话,都会报错,当然指定主键之后自动也会生成主键约束,主键就是一种约束 (2)非主键列:我们在非主键列上创建一个唯一性约束,Oracle同样自动创建了一个

MySQL 唯一性约束

唯一性约束要求改列唯一,允许为空,但只能出现一个空值,唯一性可以确保一列或者几列不出现重复值. 语法:字段名  数据类型  UNIQUE

flask 大型教程项目优化版(1):Hello World

Hello World 作者背景 作者是一个使用多种语言开发复杂程序并且拥有十多年经验的软件工程师.作者第一次学习 Python 是在为一个 C++ 库创建绑定的时候. 除了 Python,作者曾经用 PHP, Ruby, Smalltalk 甚至 C++ 写过 web 应用.在所有这些中,Python/Flask 组合是作者认为最为自由的一种. 应用程序简介 作为本教程的一部分–我要开发的应用程序是一个极具特色的微博服务器,我称之为 microblog . 我会随着应用程序的不断地进展将涉及到

优化版的冒泡排序

;优化版的冒泡排序,最好的情况为线性阶 ,最坏的情况为平方阶 ;算法的最好情况,如一个拍好序列的数组那么做排序,那么就会有几行代码不会产生交换的情况 最坏的情况是全部都交换 ;code /* 此冒泡最好情况被优化为线性阶 最坏就是平方阶 */ void bubble(int arr[3],int n) { int bChange=1,i=0,j=0; for(i=0;i<n&&bChange==1;++i)//n次 { bChange=0; for(j=0;j<n;++j)//

ADSafe净网大师3.5.1.910 绿色优化版

国内首款全方位广告智能拦截软件ADSafe,今天,ADSafe净网大师更新v3.5.1.910 正式版,这次修正了长时间运行导致的问题.另外据国外博客获悉口碑不错强大的奶牛V5也再开发阶段中了! 此绿色优化版,由zd423专注持续优化,免后续强制更新,无启动赞助弹窗.无多余按钮及应用推销,干净的感觉真好!ADsafe广告管家是国内最大的广告强力过滤软件,大色块.扁平化.卡片式的操作方式,提供更好交互体验.ADsafe净网大师能过滤不良信息.逛网站无骚扰.看视频不等待,还可保护上网隐私,防止用户信

jq实现点击表格无刷新修改数据,优化版

1 <!-------------------修改密码-------------------------- > 2 $("#pwd").live("click",function(){//① 3 $(this).parents("tr").find("#a_cannel").text("取消"); 4 user=$(this).parents("tr").find("

Oracle之唯一性约束(UNIQUE Constraint)使用方法具体解释

Oracle | PL/SQL唯一索引(Unique Constraint)使用方法 1 目标 用演示样例演示怎样创建.删除.禁用和使用唯一性约束. 2 什么是唯一性约束? 唯一性约束指表中一个字段或者多个字段联合起来可以唯一标识一条记录的约束. 联合字段中,可以包括空值. 注:在Oracle中,唯一性约束最多能够有32列. 唯一性约束能够在创建表时或使用ALTER TABLE语句创建. 3 唯一性约束和主键的差别 主键(Primary Key):全部组成主键的列都不能包括空值. 唯一性约束(U