1

在尝试使用 EF CodeFirst/Mvc3 为我的数据库实现唯一密钥验证时,我发现了这篇文章http://blogs.msdn.com/b/adonet/archive/2011/05/27/ef-4-1 -validation.aspx举例说明了如何通过使用IValidateObject我的对象模型来做到这一点:

public class Category : IValidatableObject
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public string Description { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var testContext = (TestContext)validationContext.Items["Context"];

        if (testContext.Categories.Any(
            c => c.CategoryName == CategoryName && c.CategoryID != CategoryID))
        {
            yield return new ValidationResult("A category with the same name already exists!", new[] { "CategoryName" });
        }

        yield break;
    }
}

和压倒一切DbEntityValidationResult ValidateEntity

public class TestContext : DbContext
{
    public DbSet<Test.Models.Category> Categories { get; set; }

    protected override DbEntityValidationResult ValidateEntity( DbEntityEntry entityEntry, IDictionary<object, object> items)
    {
        var myItems = new Dictionary<object, object>();
        myItems.Add("Context", this);
        return base.ValidateEntity(entityEntry, myItems);
    }

}

以及控制器上的动作

[HttpPost]
public ActionResult Create(Category category)
{
    if (ModelState.IsValid) {
        categoryRepository.InsertOrUpdate(category);
        categoryRepository.Save();
        return RedirectToAction("Index");
    } else {
        return View();
    }
}

但我得到了错误:"The given key was not present in the dictionary."对于线

var testContext = (TestContext)validationContext.Items["Context"];

似乎正在调用对象上的 Validate,该对象在覆盖 ValidateEntity 代码中设置之前访问“上下文”。

起初我认为它可能是 ModelState.Isvalid 太早触发验证,但事实并非如此。

任何人都知道我在这里缺少什么或我做错了什么?提前致谢。

4

2 回答 2

1

Model.IsValid肯定会过早触发它,也许还有其他原因。IValidatableObject是 MVC 和 EF 都使用的全局接口,但DbContext只有在调用SaveChanges上下文时才会调用您的方法,因此IValidatableObject调用之前的任何使用SaveChanges都会导致异常。如果您想以这种方式验证您的实体,则必须使用另一种方法。例如将上下文存储在HttpContext.Items- 您可以创建自定义操作过滤器并在操作调用之前实例化和存储上下文并在操作调用之后处理它 - 希望它将涵盖所有问题。

于 2011-08-09T08:35:55.363 回答
0

我面临同样的问题......然后经过大量谷歌搜索后,我终于找到了这个:

练习 3:使用 IValidatableObject 自定义验证

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    MusicStoreEntities storeDB = new MusicStoreEntities();

    if (storeDB.Albums.Any(
                       a => a.Title.Trim().ToUpper() == this.Title.Trim().ToUpper() &&
                       a.ArtistId == (int)this.ArtistId))
    {
        yield return new ValidationResult("Existing Album", new string[] { "Title" });
    }
}

正如您在他们的示例中看到的,他们实例化了一个新Context的,因此不需要validationContext.Items["Context"];. 这样做我们将不会再收到此错误。

于 2012-07-02T15:09:53.903 回答