如何设置自定义验证的位置.state == EntityState.Added
本文关键字:位置 state 验证 EntityState Added 自定义 何设置 设置 | 更新日期: 2023-09-27 18:03:37
如何设置自定义验证,当Entry.state
== EntityState.Added
为真时,下面的代码将工作!自定义验证码:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
class UniqueEmailAddress : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
this.email = (string)value;
using (G9EntityDataBaseClass oEntity = new G9EntityDataBaseClass())
{
if (oEntity.User.Where(u => u.email == email).Count() == 0)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult(ErrorMessageString);
}
}
}
}
使用:
[CustomValidation.UniqueEmailAddress]
public string email { set; get; }
i need ((NOT)EntityState.Added):
if (Entry.state != EntityState.Added){
return ValidationResult.Success;
}
我应该把Entry.state
从哪里带来
一个很好的验证方法是在你的实体类中实现IValidatableObject:
public class User: IValidatableObject
在Validate
方法中,您可以通过将实体对象添加到ValidationContext
来访问当时附加的上下文。因此,您的验证可能看起来像:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var context = (G9EntityDataBaseClass)validationContext.Items["Context"];
if (context.User
.Where(u => u.email == email && u.UserID != this.UserID)
.Any())
{
return new ValidationResult(ErrorMessageString);
}
else
{
return ValidationResult.Success;
}
}
您可以通过在DbContext
类中重写此方法将上下文添加到验证上下文:
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry,
IDictionary<object, object> items)
{
items.Add("Context", this);
return base.ValidateEntity(entityEntry, items);
}
逻辑很简单:如果有一个相同的email
属于另一个用户(u.UserID != this.UserID
),则验证总是失败。这既适用于插入新用户(ID = 0),也适用于插入现有用户。
DbContext.ValidateEntity
也不吸引我,因为这会导致长链的代码充满类型强制转换,每次只需要一个。对于验证的每个实体,将遍历此代码。Validate
方法id只在合适的时候执行。
您需要获取实体所附加的上下文以查看其状态。ValidationContext可以用来在验证属性类中获取额外的信息,它在创建时接受iserviceprovider的实现,大多数IoC容器要么实现了这个实现,要么有包装器。
所以,如果你运行在一个环境与IoC容器,可以控制你的属性类的创建(例如,通过注册一个DataAnnotationsModelValidator在MVC中),并有规则创建你的上下文(例如,每HTTP请求),你可能能够访问当前上下文的属性,并使用它来查看实体的状态被验证
如果不了解更多的上下文,这段代码运行在什么框架中,你想要实现什么行为,很难说这是否是一个可行的方法。
@Gert Arnold post是一种方法,如果你想使用属性,你可以通过ObjectInstance属性从ValidationContext中找到对象
var user = validationContext.ObjectInstance as User;
if(user==null) return new ValidationResult("...");
using(var db=new SomeDbContext()){
var has=db.User.Any(x=>x.Id!=user.Id && x.email==value);
if (has) return new ValidationResult("...");
else return ValidationResult.Success;
}
当添加时,id为0,所以在db中,没有id为0的记录,所以如果有1条记录有相同的电子邮件,any()返回true。
更新时,您有一个id,因此x.id!=user。