Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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# 具有动态数据的自定义高级实体验证_C#_Entity Framework_Validation_Asp.net Dynamic Data - Fatal编程技术网

C# 具有动态数据的自定义高级实体验证

C# 具有动态数据的自定义高级实体验证,c#,entity-framework,validation,asp.net-dynamic-data,C#,Entity Framework,Validation,Asp.net Dynamic Data,我正在寻找一种解决方案,当用户使用实体框架在动态数据屏幕中保存其更改时,可以执行一些自定义实体验证(这需要数据库访问、跨成员验证…) 验证比我对属性所能做的更复杂(它需要访问数据库等) 您能拦截SaveChanges调用吗? 我试图重写DbContext对象中的ValidateEntity,但动态数据似乎没有调用它(可能是因为它使用的是内部ObjectContext,不知道为什么),重写SaveChanges也没有帮助。 我没有看到任何我可以订阅的活动 报告应有助于: 通过重写 OnValida

我正在寻找一种解决方案,当用户使用实体框架在动态数据屏幕中保存其更改时,可以执行一些自定义实体验证(这需要数据库访问、跨成员验证…) 验证比我对属性所能做的更复杂(它需要访问数据库等)

您能拦截SaveChanges调用吗?
我试图重写DbContext对象中的
ValidateEntity
,但动态数据似乎没有调用它(可能是因为它使用的是内部ObjectContext,不知道为什么),重写SaveChanges也没有帮助。
我没有看到任何我可以订阅的活动

报告应有助于:

通过重写 OnValidate方法或处理已调用的验证事件 更改任何数据字段时。这种方法允许您添加验证 以及单个字段的业务逻辑。这种方法更为有效 常规,而不是为单个字段添加验证。这是有用的 当相同的验证逻辑可以应用于多个数据时 领域它还允许您执行涉及以下内容的验证检查: 多个字段

但是我使用的是POCO实体框架6类,因此没有要重写的
OnValidate
方法,从我读到的内容来看,这是针对LinqToSql的,我找不到他们提到的
Validate
事件

我试图在DbContext的构造函数中订阅内部
ObjectContext
SavingChanges
事件,以手动调用
ValidateEntity
,但我不知道如何处理结果。如果我抛出一个
DbEntityValidationException
(或类似于中建议的
ValidationException
),ASPNET会像处理任何异常一样处理它(黄色屏幕)

实现
IValidatableObject
也不起作用

我还尝试实现我自己的
DynamicValidator
来查看发生了什么,但没有成功,它似乎可以处理异常(如果我覆盖
ValidateException
,并放置一个断点,我看到了它),但它仍然会弹出默认错误处理程序并显示一个黄色屏幕。我一定错过了什么


那么,在保存到动态数据/EF之前,您应该如何对实体执行复杂的验证(跨字段、带查询等)?

我认为您尝试执行的逻辑在您的体系结构中不属于这样的级别。让数据库强制执行它应该执行的约束,如外键等,并将您的业务逻辑置于上面一层。例如,在您想要验证的实体上,您可以添加一个
IsValidForAddOrUpdate()
方法,该方法包含您在验证器中输入的逻辑。然后使用新方法:

if (entity.IsValidForAddOrUpdate())
{
    db.Set<Entity>().Add(entity);
    db.SaveChanges()
}
else throw new DbValidationException("Entity failed validation due to rule xyz.");
if(entity.IsValidForAddOrUpdate())
{
db.Set().Add(实体);
db.SaveChanges()
}
否则抛出新的DbValidationException(“由于规则xyz,实体验证失败”);

实现这一点的一种方法是在实体上实现
IDataErrorInfo
接口,如下所示:

public partial class MyEntity : IDataErrorInfo
{
    public MyEntity()
    {
    }

    ...

    #region IDataErrorInfo Members
    public string Error
    {
        get { throw new NotImplementedException(); }
    }
    public string this[string propertyName]
    {
        get
        {
            //Custom Validation logic
            return  MyValidator.ValidateProperty(this, propertyName);
        }
    }
    #endregion  
}
要从IDataErrorInfo方法访问当前DBContext,可以使用。 然后重写上下文的SaveChanges方法:

    public override int SaveChanges()
    {
        this.ObjectContext.DetectChanges();

        // Get all the new and updated objects
        var objectsToValidate =
        ChangeTracker.Entries().Where(x => x.State == EntityState.Modified || x.State == EntityState.Added).
        Select(e => e.Entity);

        // Check each object for errors
        foreach (var obj in objectsToValidate)
        {
            if (obj is IDataErrorInfo)
            {
                // Check each property
                foreach (var property in obj.GetType().GetProperties())
                {
                    var columnError = (obj as IDataErrorInfo)[property.Name];
                    if (columnError != null) {
                    //Handle your validation errors
                    throw new DbEntityValidationException(columnError); }
                }
            }
        }

        return base.SaveChanges();
    }
另请参见以使其与DataAnnotation一起工作

你写道:

如果我抛出DbEntityValidationException(或ValidationException 正如本文所建议的那样),ASPNET可以像处理任何异常一样处理它 (黄色屏幕)

看。调用
SaveChanges
时,需要捕获
DbEntityValidationException
(或
ValidationException
),如果不捕获它们以在控制器内处理它们,则默认错误处理程序将处理它们

或者,您可以使用控件捕获ValidationException:

    <!-- Capture validation exceptions -->
    <asp:DynamicValidator ID="ValidatorID" ControlToValidate="GridView1" 
        runat="server" /> 


请参阅。

我发现了一个我不喜欢的解决方法,但它很有效:

我的上下文仍在执行验证,并在必要时抛出
ValidationException

由于
ListView
似乎无法捕获和处理异常,我自己通过处理
ListView
OnItemUpdated
oniminserted
事件来实现这一点:

protected void ListView1_ItemUpdated(object sender, ListViewUpdatedEventArgs e)
{
    if (e.Exception != null)
    {
        ValidationError.DisplayError(e.Exception.Message);
        e.ExceptionHandled = true;
        e.KeepInEditMode = true;
    }
}
ValidationError
用于将异常消息添加到验证摘要中。它添加了一个“假”,总是在消息中验证失败

public class ValidationError : BaseValidator
{
    private ValidationError(string message)
        : base()
    {
        ErrorMessage = message;
        IsValid = false;
    }

    protected override bool EvaluateIsValid()
    {
        return false;
    }

    public static void DisplayError(string message, string validationGroup)
    {
        var currentPage = HttpContext.Current.Handler as Page;
        currentPage.Validators.Add(new ValidationError(message) { ValidationGroup = validationGroup });
    }
}

我同意这一说法,我还认为业务逻辑不应该与实体frameworkIt的可论证性相耦合。也许域层对象可以进行验证。只要不使用糟糕的“EF前面的存储库层”模式……我同意,但动态数据并没有提供很多验证选项。但问题不在这里,问题是DbValidationException没有被DynamicValidator捕获(尽管我找到的文档和文章说应该这样),所以我得到了一个黄色屏幕。现在我甚至不想拥有一个好的体系结构,只是想拥有一些可以工作的东西:(.是的,我发现了什么,但是DynamicValidator没有捕获异常,我不知道为什么。如果我调试,我看到它进入ValidateException方法,它似乎检测到它并用它做事情(),但异常仍然会出现在默认错误处理程序上。我甚至尝试了Dynamic Data Futures包中的改进的DynamicValidator,但它也不起作用。我无法在控制器中捕获它,因为没有动态数据。我看到了,有趣的问题,如果同时没有得到回答,我将在周四查看它。