Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Entry.state==EntityState.Added的位置设置自定义验证_C#_Asp.net Mvc_Entity Framework_Validation - Fatal编程技术网

C# 如何在Entry.state==EntityState.Added的位置设置自定义验证

C# 如何在Entry.state==EntityState.Added的位置设置自定义验证,c#,asp.net-mvc,entity-framework,validation,C#,Asp.net Mvc,Entity Framework,Validation,如何设置自定义验证,当Entry.state=EntityState.Added为真时,下面的代码可以工作! 自定义验证代码: [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] class UniqueEmailAddress : ValidationAttribute { protected override ValidationResult IsValid(object value, Validati

如何设置自定义验证,当
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);
            }
        }
    }
}
使用:

我需要((不是)EntityState.Added):


我应该从何处携带
Entry.state

您需要获取实体附加到的上下文以查看其状态。ValidationContext可用于向validation属性类中获取额外信息,它在创建大多数IoC容器时都需要IServiceProvdier的实现,大多数IoC容器都为其实现或具有包装器

因此,如果您在具有IoC容器的环境中运行,并且可以控制属性类的创建(例如,通过在MVC中注册DataAnnotationsModelValidator),并且具有创建上下文的规则(例如,每个HTTP请求)您可以访问属性中的当前上下文,并使用它查看正在验证的实体的状态


虽然有很多ifs,但如果不了解更多的上下文、此代码运行的框架以及您试图实现的行为,很难说这是否是一种可行的方法。

在实体类中实现了一种有效的验证方法:

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;
    }
}
逻辑很简单:如果存在属于另一个用户的相同的
电子邮件(
u.UserID!=this.UserID
),验证总是失败。这适用于插入新用户(ID=0)和现有用户


顺便说一句,问题是您是否应该实际使用这里的上下文来访问数据库,但是替代方法,重写对我也没有吸引力,因为这会导致长串代码充满类型转换,每次只需要一个类型转换。这段代码针对每个被验证的实体进行遍历。
Validate
方法id仅在适用时执行。

@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.id可以删除此记录本身。

当该语句为真时,您希望它触发什么,还是仅在它周围时才需要它?有点困惑这个代码在哪里?它在实体中吗?嗯,您希望如何对EF实体执行
ValidationAttribute
验证?好的,所以我在我的DbContext中重写了该方法,仍然不起作用。我在其中设置了一个断点,但它从未被命中,因此validationContext的Items属性仍然为零。回顾了所有事情,没有发现问题所在。。。有什么想法吗?我发现您必须手动调用
DbContext
上的
GetValidationErrors
,以便它按照本文中的说明进行验证。因此,我放弃了此选项,我不希望在几乎所有操作中都需要额外的代码。我将使用自定义验证属性。@FelipeCorrea默认情况下,上下文将在
SaveChanges
上验证其实体。然后我不知道我的情况有什么问题,因为调用了我实体的
validate
方法,并且从未调用
DbContext.ValidateEntity
。这会导致您的推荐失败,因为我在
项目
字典中没有任何键。我意识到发生了什么。在我的操作中,当调用
Model.IsValid
时,它会中间触发实体
Validate
方法(上下文尚未添加到
字典)。然后,当代码到达对
db.SaveChanges
的调用时,调用
ValidateEntity
方法:这里是将上下文添加到
字典中的地方,但是现在它没有用了,因为它是实体
验证
方法中需要的。我认为这个过程不再是通过上下文进行查询所需的验证的解决方案。
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;
    }
}
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry,
                       IDictionary<object, object> items)
{
    items.Add("Context", this);
    return base.ValidateEntity(entityEntry, items);
}
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;
}