0

よくあるシナリオがあります。標準のADOトランザクションを使用するのは簡単ですが、NH(私が知っている)ではそれほど多くはありません。

更新するテーブルが2つあります。最初の情報にはプロファイル情報(プロファイル)が含まれ、もう1つの情報(作業)には、実行する必要のあるレコードの変更とそれらの変更のステータスが含まれます。プロファイルテーブルが更新されるたびに、ワークテーブルのステータスが更新されます。

  • プロファイルテーブルの更新に失敗した場合は、ワークテーブルのステータスを更新する必要があります。
  • プロファイルテーブルへの更新が成功し、ワークテーブルへの更新が失敗した場合、トランザクションをロールバックする必要があります。

問題は、トランザクションをコミットするまで、プロファイルテーブルの更新が失敗したかどうかわからないことです。プロファイルでフラッシュを実行して例外をキャッチし、ステータスをWorkテーブルに書き込もうとしましたが、プロファイルの更新によって発生した例外でコミットが失敗します。

どうすればこれを処理できますか?通常のADOトランザクションでは、最初の呼び出しがスローされますが、トランザクション内の他のテーブルをキャッチして更新することはできます。

これが私のコードのようなものです-かなり標準的です。これは私の実際のコードではないので、問題に焦点を当ててください。トランザクションを破棄したり、セッションを閉じたりしていないわけではありません;):

try
{
    ITransaction trans = _session.BeginTransaction();

    var work = _repo.GetWork();
    var profile = _repo.GetProfile(work.ProfileId);

    try
    {
        profile.UpdateWithNewValues(work);
        _session.SaveOrUpdate(profile);
        _session.Flush();
        work.Status = "Success";

    }catch{
      work.Status = "Failure";
    }

    _session.SaveOrUpdate(work);
    trans.Commit();

}catch{

    trans.Rollback();

}

Flush()が機能しないことはわかっていますが、他にこれを行う方法がわかりません。

4

2 に答える 2

0

trans.Commitフラッシュの前に問題が発生することはありません。次に例を示します(少し変更したものもあなたのように見えます):

Profile profile;
Work work;
ITransaction tx;

try
{
    session.SaveOrUpdate(profile);  

    work.Status = "Success";    
    session.SaveOrUpdate(work);

    tx.Commit();
}
catch (Exception)   // wroh oh...
{
    try
    {
        work.Status = "Failure";
        session.SaveOrUpdate(work);

        tx.Commit();
    }
    catch (Exception)
    {
        if (!tx.WasRolledBack)
        {
            tx.Rollback();
            session.Clear();
        }

        throw;
    }
}
finally
{
    if (session.IsOpen)
    {
        // Whatever happened, Flush/Persist at the end.
        session.Flush();
    }
}
于 2010-09-14T20:21:23.550 に答える
0

要件に必要ないくつかの説明。

1)>>プロファイルテーブルの更新が成功し、ワークテーブルの更新が失敗した場合、トランザクションをロールバックする必要があります

Workは監査証跡の更新のようなものであり、プロファイルの更新が機能する場合は失敗しないはずだと思いました。この場合、トランザクションをロールバックしないでください。ただし、これを言っても、コードはすでにこの要件に準拠しています。

2)>>プロファイルテーブルの更新に失敗した場合、ワークテーブルのステータスを更新する必要があります。

更新が失敗した場合は、トランザクションをロールバックしているはずです。2つの個別のトランザクション(プロファイルと作業の両方に1つ(現在)、次に作業専用に個別のトランザクション)がない限り、作業テーブルを更新することはできません。これはあなたにとって意味がありますか?

于 2010-09-14T23:14:44.900 に答える