私はnHibernateを学んでいて、おそらく解決するのが簡単な問題に出くわしました。
これまでのところ、nHibernateトランザクションを相互にネストすることはできない/すべきではないことがわかりました。私の場合、スコープが別のルーチンに移動し、新しいトランザクションを開始したときにこれを理解しました。
だから私は次のことをすべきですか?
using (ITransaction transaction = session.BeginTransaction())
{
NHibernateMembership mQuery =
session.QueryOver<NHibernateMembership>()
.Where(x => x.Username == username)
.And(x => x.ApplicationName == ApplicationName)
.SingleOrDefault();
if (mQuery != null)
{
mQuery.PasswordQuestion = newPwdQuestion;
mQuery.PasswordAnswer = EncodePassword(newPwdAnswer);
session.Update(mQuery);
transaction.Commit();
passwordQuestionUpdated = true;
}
}
// Assume this is in another routine elsewhere but being
// called right after the first in the same request
using (ITransaction transaction = session.BeginTransaction())
{
NHibernateMembership mQuery =
session.QueryOver<NHibernateMembership>()
.Where(x => x.Username == username)
.And(x => x.ApplicationName == ApplicationName)
.SingleOrDefault();
if (mQuery != null)
{
mQuery.PasswordQuestion = newPwdQuestion;
mQuery.PasswordAnswer = EncodePassword(newPwdAnswer);
session.Update(mQuery);
transaction.Commit();
passwordQuestionUpdated = true;
}
}
注:私はそれらが単なるコピーであることを知っています、私は私の質問を示しているだけです
最初の質問 これは、実行することが重要な方法ですか?操作ごとのトランザクション?
2番目の質問 transaction.Commit();を呼び出す必要がありますか。毎回または最後のセットでのみ?
3番目の質問 これを行うための自動または手動のより良い方法はありますか?
3番目の質問 session.Transaction.IsActiveを使用して、「現在のセッション」がすでにトランザクションの一部であるかどうかを判断できますか?この場合、「トランザクションラップ」を最高レベルで作成できます。たとえば、Webフォームコードとその中でルーチンを呼び出し、最後にすべての作業をコミットします。これは欠陥のある方法ですか?
私は本当にこれを打ち負かしたいので、私は続けるつもりで始めます。すべてを変更する必要があるという点で、数千行のコードを見つけたくありません。
前もって感謝します。
編集:
そのため、問題を正確に説明するコードをいくつか作成しました。
private void CallingRoutine()
{
using(ISession session = Helper.GetCurrentSession)
{
using (ITransaction transaction = session.BeginTransaction())
{
// RUN nHIbernate QUERY to get an OBJECT-1
// DO WORK on OBJECT
// Need to CALL an EXTERNAL ROUTINE to finish work
ExternalRoutine();
// DO WORK on OBJECT-1 again
// *** At this point ADO exception triggers
}
}
}
private bool ExternalRoutine()
{
using(ISession session = Helper.GetCurrentSession)
{
using (ITransaction transaction = session.BeginTransaction())
{
// RUN nHIbernate QUERY to get an OBJECT-2
// DO WORK on OBJECT
// Determine result
if(Data)
{
return true;
}
return false;
}
}
}
うまくいけば、これは問題を示しています。これは私がトランザクションを書くことを理解した方法ですが、ADO例外がどのように発生するかに注意してください。私は明らかに何か間違ったことをしています。これらのルーチンをどのように書くつもりですか?
たとえば、あるプロバイダーのヘルパーオブジェクトを作成し、公開された各ルーチン内にnHibernateクエリの実行がある場合、トランザクションに関して、呼び出し元の関数とデータについて何も知らないと仮定して、これらのルーチンをどのように作成しますか?仕事は、nHibernateを効果的かつ効率的に操作し、結果を返すことです。
これは、ExternalRoutine()でトランザクションを記述したときに想定したものです。これは、nHibernateの唯一の使用であると想定し、トランザクションを明示的に作成するためです。