1

EF CodeFirst / Mvc3を使用してデータベースに一意のキー検証を実装しようとしているときに、この投稿に出くわしましたhttp://blogs.msdn.com/b/adonet/archive/2011/05/27/ef-4-1 -validation.aspxIValidateObjectは、オブジェクトモデルに使用してそれを行う方法の例を示しています。

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"];

オーバーライドValidateEntityコードで設定される前に、「Context」にアクセスするオブジェクトのValidateが呼び出されているようです。

最初は、ModelState.Isvalidトリガーの検証が早すぎる可能性があると思いましたが、そうではありませんでした。

私がここで何が欠けているのか、何が間違っているのか誰かが知っていますか?前もって感謝します。

4

2 に答える 2

1

Model.IsValid間違いなくそれを早すぎて、おそらく何か他のものを引き起こします。IValidatableObjectはMVCとEFの両方で使用されるグローバルインターフェイスですが、inのメソッドはコンテキストDbContextを呼び出すときにのみ呼び出されるため、呼び出す前にを使用すると例外が発生します。この方法でエンティティを検証する場合は、別のアプローチを使用する必要があります。たとえば、コンテキストをに保存します-カスタムアクションフィルターを作成し、操作呼び出しの前にコンテキストをインスタンス化して保存し、操作呼び出しの後に破棄できます-うまくいけば、すべての問題をカバーします。SaveChangesIValidatableObjectSaveChangesHttpContext.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 に答える