69

モーダル ウィンドウを使用して階層オブジェクトのプロパティを設定するデスクトップ クライアント アプリケーションがあります。これはクライアント アプリケーションであり、DbContext へのアクセスはスレッド化されていないため、モーダルな子に渡されるメイン フォームで実行時間の長いコンテキストを使用します。

これらのモーダル ウィンドウは、PropertyGrid を使用してエンティティ プロパティを表示し、キャンセル ボタンも備えています。データが変更され、キャンセル ボタンが押された場合、変更は親フォームに反映されます (ここでは を破棄できませんDbContext object)。

DbContext.SaveChanges()メソッドが呼び出されていない場合に行われた変更を破棄する方法はありますか?

更新:エンティティ フレームワーク バージョン 4.4。

4

9 に答える 9

18

単一のエンティティのプロパティに加えられた変更をキャンセルする単純なケースでは、現在の値を元の値に設定できます。

context.Entry(myEntity).CurrentValues.SetValues(context.Entry(myEntity).OriginalValues);
//you may also need to set back to unmodified -
//I'm unsure if EF will do this automatically
context.Entry(myEntity).State = EntityState.UnModified;

または代わりにリロードします(ただし、データベースヒットになります)

context.Entry(myEntity).Reload();

于 2013-05-08T22:38:31.913 に答える
13

トランザクションでラップするのはどうですか?

    using(var scope = new TransactionScope(TransactionScopeOption.Required,
        new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted })){

        // Do something 
        context.SaveChanges();
        // Do something else
        context.SaveChanges();

        scope.Complete();
}
于 2013-05-08T09:37:57.610 に答える
5

このようなものを手動で試してみてください..これがあなたのシナリオでうまくいくかどうかはわかりませんが、試してみることができます:

public void UndoAll(DbContext context)
    {
        //detect all changes (probably not required if AutoDetectChanges is set to true)
        context.ChangeTracker.DetectChanges();

        //get all entries that are changed
        var entries = context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged).ToList();

        //somehow try to discard changes on every entry
        foreach (var dbEntityEntry in entries)
        {
            var entity = dbEntityEntry.Entity;

            if (entity == null) continue;

            if (dbEntityEntry.State == EntityState.Added)
            {
                //if entity is in Added state, remove it. (there will be problems with Set methods if entity is of proxy type, in that case you need entity base type
                var set = context.Set(entity.GeType());
                set.Remove(entity);
            }
            else if (dbEntityEntry.State == EntityState.Modified)
            {
                //entity is modified... you can set it to Unchanged or Reload it form Db??
                dbEntityEntry.Reload();
            }
            else if (dbEntityEntry.State == EntityState.Deleted)
                //entity is deleted... not sure what would be the right thing to do with it... set it to Modifed or Unchanged
                dbEntityEntry.State = EntityState.Modified;                
        }
    }
于 2013-05-08T10:21:33.093 に答える
5

これを適用できます:

context.Entry(TEntity).Reload();

私はそれを試してみましたが、うまくいきました。

注: このメソッド ( Reload ) は、データベースからの値でプロパティ値を上書きして、データベースからエンティティを再読み込みします。このメソッドを呼び出した後、エンティティは Unchanged 状態になります。

于 2013-11-16T01:55:37.957 に答える