2

コミットされていない変更についてクエリを実行する必要があり、トランザクションを使用しようとしましたが、例外があると機能しないことがわかりました。

問題を再現するための簡単な例を作成しました。「Tabella」というテーブルが1つしかないデータベースがあり、テーブルには2つのフィールドがあります。「ID」は自動生成された整数で、「Valore」は一意性制約のある整数です。次に、このコードを実行しようとします。

using (TransactionScope scope = new TransactionScope())
{
    Db1Container db1 = new Db1Container();

    try
    {
        db1.AddToTabella(new Tabella()
        {
            Valore = 1
        });
        db1.SaveChanges();
    }
    catch { }

    try
    {
        db1.AddToTabella(new Tabella()
        {
            Valore = 1
        });
        db1.SaveChanges(); //Unique constraint is violated here and an exception is thrown
    }
    catch { }

    try
    {
        db1.AddToTabella(new Tabella()
        {
            Valore = 2
        });
        db1.SaveChanges();
    }
    catch { }

    //scope.Complete(); //NEVER called
}   //here everything should be rolled back

データベースを調べると、トランザクションがロールバックする必要があるため、レコードが含まれていないはずです。代わりに、2つのレコードが見つかります!!!! 1つはValore=1で、もう1つはValore=2です。私は何かが足りないのですか?SaveChangesメソッドへの2回目の呼び出しは、それ自体の変更をロールバックしてトランザクションを「削除」し、次にSaveChangesへの3回目の呼び出しは、1回目と3回目の挿入の変更をコミットするようです(この時点では、トランザクションが存在しないようです)。

また、SaveChanges(false)メソッドを使用しようとしましたが(AcceptAllChangesメソッドを呼び出さなくても)、成功しませんでした。同じ動作をします。

エラーを修正して(たとえば、catchステートメントでのユーザー操作によって)再試行するため、SaveChangesによってトランザクションが自動的にロールバックされることは望ましくありません。

誰かがこれを手伝ってくれますか?それは「バグ」のようで、それは私に本当に大きな頭痛の種を与えています...

4

2 に答える 2

0

それが呼ばれることscope.Complete()はありませんか?catch{}すべての例外が発生した場合、コードは実行を継続し、Completeステートメントに到達します。代わりに、たとえば、例外を伝播させて、より高いレベルでキャッチする必要があります。

于 2009-11-16T10:19:17.477 に答える
0

これは元の質問には少し遅れていますが、おそらく誰かを助けるでしょう.

このコードは、.net/ef 4 および SQL Server 2008 R2 で動作するはずです。

using (TransactionScope scope = new TransactionScope())
{
    Db1Container db1 = new Db1Container();

    try
    {
        db1.AddToTabella(new Tabella()
        {
            Valore = 1
        });
        db1.SaveChanges();

        db1.AddToTabella(new Tabella()
        {
            Valore = 1
        });
        db1.SaveChanges(); //Unique constraint is violated here and an exception is thrown

        //if we get here then there were no errors thrown on previous SaveChanges() 
        //calls and we can complete the transaction with no rollback
        scope.Complete();

    }
    catch (Exception)
    {
        //do nothing
    }

}
于 2011-02-01T16:34:44.163 に答える