1

私は本当に単純なモデルを持っています:

public class Item : DbEntity
{
    public string Name {get;set;}
    public int Quantity {get;set;}
    public virtual Category Category {get;set;}
}

public class Category : DbEntity
{
    public string Name {get;set;}
}

以下の方法を使用して、データベースへの変更を保存してコミットします。

public void SaveEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
    if (entity.Id.Equals(Guid.Empty))
        _context.Set<TEntity>().Add(entity);
    else
        _context.Entry(entity).State = System.Data.EntityState.Modified;

    _context.SaveChanges();
}

public void DeleteEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
     _context.Set<TEntity>().Remove(entity);
     _context.SaveChanges();
}

これらの save メソッドと delete メソッドはリポジトリに存在します。このリポジトリは Ninjected であるため、アプリケーションの存続期間を通じて一定の状態を保持する必要があります。これは試行錯誤された方法であり、私にとっては常にうまくいきました。何らかの理由でこれを行うと:

[HttpPost]
public ActionResult Edit(MenuItemViewModel vm)
{
    if (ModelState.IsValid)
    {
        // TODO: Add ViewModel Logic
        vm.MenuItem.Category = _repository.Categories.FirstOrDefault(x => x.Id.Equals(vm.SelectedCategory));

    try
    {
        // TODO: Add Save Logic
            _repository.SaveEntity(vm.MenuItem);

            TempData["success"] = true;
            TempData["message"] = String.Format("Saved {0} Successfully", vm.MenuItem.Description);
    }
    catch (Exception ex)
    {
             TempData["error"] = true;
             TempData["message"] = "Error Occured";
    }

    return _redirectTo;
    }

    return View("Shape", vm);
}

ビュー パーツは単純で、 と のいくつかのフィールドのみです。NameQuantityすべてCategoryDrop Downカテゴリ名 asTextおよび id asを含むボックスですValue。これはサーバーにポストされ、そこでリポジトリが移動して新しいものを収集Categoryし、エンティティに割り当てます。

なんらかの理由で、これはデータベースへの変更をコミットしません。データベースをチェックした後にブレークしたときに、前後にブレークが指摘されましたが、変更されていませんでした!

更新を妨げているばかげた小さな間違いを誰でも見ることができますか。

編集

このStackOverflow Postを読んでください。最初にアタッチしてから編集するという部分を取り上げましたUnchangedSaveChanges().

これ何か関係あるの!?

更新
さて、いくつかの興味深いニュース、私はSaveEntityメソッドをステップスルーし、ステップを過ぎた後SaveChanges()、コンテキストをもう一度確認します。別のコントローラーとアクションにリダイレクトするという事実は、結果またはテーブルの変更に影響を与える可能性がありますか? 問題はメソッドにあるとは思いませんSaveEntity!!

最新のアップデート

のモデルを変更し、単にをオンに変更するItem行を追加しただけです。試してみると、次のエラーが表示されます。public Guid CategoryId {get;set;}CategoryCascade On DeleteSaveChanges

参照整合性制約違反が発生しました: 参照制約を定義するプロパティ値が、リレーションシップ内のプリンシパル オブジェクトと従属オブジェクトの間で一貫していません。

4

2 に答える 2

0

SaveEntity では、Id が Guid.Empty と等しくない場合、項目をコンテキストに関連付けず、State を Modified に設定するだけです。試す:

public void SaveEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
    if (entity.Id.Equals(Guid.Empty))
    {
        _context.Set<TEntity>().Add(entity); // Automatically sets state to Added
    }
    else 
    {
        _context.Set<TEntity>().Attach(entity);
        _context.Entry(entity).State = System.Data.EntityState.Modified;
    }

    _context.SaveChanges();
}

また、DeleteEntity については、Attach と Remove を試してください。

public void DeleteEntity<TEntity>(TEntity entity) where TEntity : DbEntity
{
    _context.Set<TEntity>().Attach(entity); // Attaches entity with state Unchanged
    _context.Set<TEntity>().Remove(entity); // Changes entity state to Deleted
    _context.SaveChanges();
}

重要なのは、ASP.NET などの切断された環境では、投稿から返されたモデルがコンテキストに関連付けられていないため、処理する前に再関連付けする必要があることです。

テストとして、SaveChanges が呼び出される前に、既存のコード内のエンティティの状態を確認してください。変更されていない可能性が高く、アクションが実行されないことを意味します。

于 2013-06-06T11:28:59.823 に答える