我之前就写过一篇《实现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-10-16 03:45:56