实现UniqueAttribute唯一性约束-优化版
我之前就写过一篇《实现UniqueAttribute唯一性约束》,虽然实现了通过调用IsValid方法可以进行唯一性验证,但有一个缺点,那就是耦合度过高,原因是里面的DB上下文对象是直接写在里面的,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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上下文类型,然后再采取反射动态创建实例,这样就降低了依赖,完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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; <strong> 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; } } } </strong> |
这样虽然降低了对实际DB上下文的依赖,但新问题又出来了,就是如果通过手动来验证该特性(如下代码)就没有问题,但如是想让EF框架在RUD时能自动验证,则会出现问题,因为没有传入ContextType,所以也就无法进行验证,我想这也是微软之所以没有实现UniqueAttribute唯一性约束的原因吧,不知道哪位高手能指点一下,非常感谢!
以下是手动来验证该特性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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, "验证不唯一,存在重复值!" ); } } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步