我使用System.ComponentModel.DataAnnotations
命名空间来验证我的域类。如何创建自定义属性来验证属性的唯一性,而不考虑数据库(例如通过某个接口)?数据注释的唯一约束
6
A
回答
1
如果我正确地理解了你,你应该能够创建一个自定义的ValidationAttribute并通过一个自定义工厂来获取你的仓库的上下文。
验证:
using System.ComponentModel.DataAnnotations;
public class DBUniqueAttribute : ValidationAttribute
{
private IRepository Repository{ get; set;}
public DBUniqueAttribute()
{
this.Repository = MyRepositoryFactory.Create();
}
public override bool IsValid(object value)
{
string stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);
return Repository.IsUnique(stringValue);
}
}
你将不得不与isUnique设置()方法的IRepository接口。 MyRepositoryFactory将有一个名为Create()的静态方法,它将创建数据库所需的具体存储库。如果数据库类型发生更改,则只需更新Factory以为新数据库返回新的存储库。
8
这是我针对这种情况提出的解决方案,它只是检查表中是否有一个具有相同值的待验证属性的记录。它假定你将使用LinqToSQL,并且任何需要这种验证的表都有一个ID列。
我也想在数据库中的基础表上设置一个唯一的约束。该属性允许我在窗体上放置一个很好的错误消息并将其与相应的属性相关联。
public class UniqueAttribute : ValidationAttribute
{
public Func<DataContext> GetDataContext { get; private set; }
public string IDProperty { get; private set; }
public string Message { get; private set; }
public UniqueAttribute(Type dataContextType, string idProperty, string message)
{
IDProperty = idProperty;
Message = message;
GetDataContext =() => (DataContext)Activator.CreateInstance(dataContextType);
}
public UniqueAttribute(Type dataContextType, string idProperty, string message, string connectionString)
{
IDProperty = idProperty;
Message = message;
GetDataContext =() => (DataContext)Activator.CreateInstance(dataContextType, new object[] { connectionString });
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var idProperty = validationContext.ObjectType.GetProperty(IDProperty);
var idType = idProperty.PropertyType;
var id = idProperty.GetValue(validationContext.ObjectInstance, null);
// Unsightly hack due to validationContext.MemberName being null :(
var memberName = validationContext.ObjectType.GetProperties()
.Where(p => p.GetCustomAttributes(false).OfType<DisplayAttribute>().Any(a => a.Name == validationContext.DisplayName))
.Select(p => p.Name)
.FirstOrDefault();
if (string.IsNullOrEmpty(memberName))
{
memberName = validationContext.DisplayName;
}
// End of hack
var validateeProperty = validationContext.ObjectType.GetProperty(memberName);
var validateeType = validateeProperty.PropertyType;
var validatee = validateeProperty.GetValue(validationContext.ObjectInstance, null);
var idParameter = Expression.Constant(id, idType);
var validateeParameter = Expression.Constant(validatee, validateeType);
var objectParameter = Expression.Parameter(validationContext.ObjectType, "o");
var objectIDProperty = Expression.Property(objectParameter, idProperty);
var objectValidateeProperty = Expression.Property(objectParameter, validateeProperty);
var idCheck = Expression.NotEqual(objectIDProperty, idParameter);
var validateeCheck = Expression.Equal(objectValidateeProperty, validateeParameter);
var compositeCheck = Expression.And(idCheck, validateeCheck);
var lambda = Expression.Lambda(compositeCheck, objectParameter);
var countMethod = typeof(Queryable).GetMethods().Single(m => m.Name == "Count" && m.GetParameters().Length == 2);
var genericCountMethod = countMethod.MakeGenericMethod(validationContext.ObjectType);
using (var context = GetDataContext())
{
var table = context.GetTable(validationContext.ObjectType) as IQueryable<Models.Group>;
var count = (int)genericCountMethod.Invoke(null, new object[] { table, lambda });
if (count > 0)
{
return new ValidationResult(Message);
}
}
return null;
}
}
用法示例:
[MetadataType(typeof(UserMetadata))]
public partial class Group : IDatabaseRecord
{
public class UserMetadata
{
[Required(ErrorMessage = "Name is required")]
[StringLength(255, ErrorMessage = "Name must be under 255 characters")]
[Unique(typeof(MyDataContext), "GroupID", "Name must be unique")]
public string Name { get; set; }
}
}
0
我爱 @ daveb的解决方案。不幸的是,三年后,我需要一些非常重大的修改。这是他为EF6更新的解决方案。希望能救一个人一小时左右的摆弄。
public class UniqueAttribute : ValidationAttribute
{
public UniqueAttribute(string idProperty, string message)
{
IdProperty = idProperty;
Message = message;
}
[Inject]
public DataContext DataContext { get; set; }
private string IdProperty { get; set; }
private string Message { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var objectType = validationContext.ObjectType;
if (objectType.Namespace == "System.Data.Entity.DynamicProxies")
{
objectType = objectType.BaseType;
}
var idProperty = objectType.GetProperty(IdProperty);
var idType = idProperty.PropertyType;
var id = idProperty.GetValue(validationContext.ObjectInstance, null);
var memberName = validationContext.MemberName;
var validateeProperty = objectType.GetProperty(memberName);
var validateeType = validateeProperty.PropertyType;
var validatee = validateeProperty.GetValue(validationContext.ObjectInstance, null);
var idParameter = Expression.Constant(id, idType);
var validateeParameter = Expression.Constant(validatee, validateeType);
var objectParameter = Expression.Parameter(objectType, "o");
var objectIdProperty = Expression.Property(objectParameter, idProperty);
var objectValidateeProperty = Expression.Property(objectParameter, validateeProperty);
var idCheck = Expression.NotEqual(objectIdProperty, idParameter);
var validateeCheck = Expression.Equal(objectValidateeProperty, validateeParameter);
var compositeCheck = Expression.And(idCheck, validateeCheck);
var lambda = Expression.Lambda(compositeCheck, objectParameter);
var countMethod = typeof(Queryable).GetMethods().Single(m => m.Name == "Count" && m.GetParameters().Length == 2);
var genericCountMethod = countMethod.MakeGenericMethod(objectType);
var table = DataContext.Set(objectType);
var count = (int)genericCountMethod.Invoke(null, new object[] { table, lambda });
if (count > 0)
{
return new ValidationResult(Message);
}
return null;
}
}
1
只是做这样的事情在你的模型
[StringLength(100)]
[Index("IX_EntidadCodigoHabilitacion", IsUnique = true)]
public string CodigoHabilitacion { get; set; }
相关问题
- 1. 如何应用使用注释的唯一约束条件
- 2. 唯一约束
- 3. 唯一键约束在Spring数据JPA
- 4. 唯一约束(SchemaName.DATA1_PK)
- 5. 唯一约束值
- 6. 唯一约束JayData
- 7. 唯一约束Nhibernate
- 8. DataTable上的唯一约束
- 9. SQLite中的唯一约束
- 10. Grails的唯一约束
- 11. 如何指定列的组合应该是使用注释的唯一约束?
- 12. 指数多列的唯一约束
- 13. 唯一约束vs唯一索引
- 14. Oracle唯一约束和唯一索引
- 15. 唯一约束的命名约定
- 16. hibernate中的约束等价注释?
- 17. PK和唯一约束
- 18. 多列唯一约束
- 19. 复合唯一约束SQL
- 20. 笨ORA-00001:唯一约束
- 21. 冬眠唯一约束
- 22. 在唯一键约束
- 23. 多列唯一约束
- 24. HABTM - 唯一性约束
- 25. DB2 - 唯一约束多列
- 26. 唯一约束异常(SQLIntegrityConstraintViolationException)
- 27. 主键与唯一约束?
- 28. 唯一约束外键列
- 29. JPA唯一约束验证
- 30. 违反唯一键约束