私はしばらくNHibernateを使用していますが、最終的に問題が発生しました。答えを見つけることも、他の誰もこの問題を抱えているように見えたことはありません。環境は、履歴保持のためにNHibernate3.3.1.4000およびNHibernate.Envers1.4です。
次の種類のデータベーステーブル/エンティティクラスがあります。
public class ProcedureStep
{
public virtual int Id { get; protected internal set; }
public virtual Procedure ParentObject { get; set; }
public virtual int StepNo { get; set; }
public virtual string Name { get; set; }
}
マッピングあり:
public class ProcedureStepMap : ClassMap<ProcedureStep>
{
public ProcedureStepMap()
{
Table("ProcedureStep");
Id(x => x.Id);
References(x => x.ParentObject).Not.Nullable().UniqueKey("UK_PO_SN");
Map(x => x.StepNo).Not.Nullable().UniqueKey("UK_PO_SN");
Map(x => x.Name).Not.Nullable();
}
}
プロシージャステップのリストを持つ親オブジェクトがあります。これで、ユーザーはさまざまなステップを追加、削除、または変更できます。1つの「変更」は、ボタンを使用してステップのリストで選択した項目を上下に移動する手順ステップの順序の変更です。
具体的な例を見てみましょう。
シナリオは、4つの手順ステップ1〜4のリストです。
(1) Aaaa
(2) Bbbb <--
(3) Cccc
(4) Dddd
ユーザーは2番目の項目「Bbbb」を選択し、「上へ」ボタンを押して、以下を取得します。
(1) Bbbb <--
(2) Aaaa
(3) Cccc
(4) Dddd
コードで私は今、次のようなことをすることを考えました
Begin Transaction
1) Set "Aaaa" to StepNo = 0
2) Set "Bbbb" to StepNo = 1
3) Set "Aaaa" to StepNo = 2
End Transaction
しかし今、NHibernatesが活躍します。NHibernateは、トランザクションをコミットするときにステップ1について何も知らないため、データベースへの2つの更新コマンド(ステップ2および3)のみを処理しようとしていますが、StepNo列の固有の特性のために機能していません。手順1の後にsession.flush()を追加しても、その動作には何も変更されません(トランザクション内にあるため、私には非常に理解できます)。
次のアイデアはsession.CreateQuery("update...").ExecuteUpdate()
、データベースの変更を行うために使用することでした。これは正常に機能していますが、Enversを回避しており、この変更の履歴レコードがないままになっています(SQLが渡されるだけなので、もう一度理解できます)。
しかし、すべてを1つのトランザクションにまとめ、Enversの履歴を持たせることで、この変更を行う正しい方法は何でしょうか。「StepNo」列を一意にしないことが、それを機能させる唯一の方法である可能性がありますか?適切な順序付けを行い、データベースにこれを保証させることが重要であるため、列の固有の特性を失うことは望ましくありません。これは大きな助けになります。
あなたのアイデアを前もってありがとう!
[解決]:
jblとcremorだけが答えを持っているようです。他のいくつかの問題点と合わせて、Enversを完全にスキップし、履歴管理を行うためのより専門的な方法を使用することにしました。Enversがない場合、SQLコマンドを使用した単純な3ステップの更新で問題を解決できます。