バージョン番号としてSQLタイムスタンプ列を使用する楽観的同時実行制御を使用してNHibernateにマップされたエンティティがあります。マッピングは次のようになります。
<class name="Entity" optimistic-lock="version" discriminator-value="0">
<id name="id">
<generator class="native" />
</id>
<version name="Version" column="Version" generated="always" unsaved-value="null" type="System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
...
<subclass name="ChildEntity" discriminator-value="1" />
</class>
私は、データベース内の行のデータがレコードの取得と更新の間で変更されたときに何が起こるかをテストしています。そのために、NHibernateによって更新されているテーブル内のレコードの1つに対して直接updateステートメントを実行しています。この直接更新により、テーブル内のレコードのバージョン番号が変更されます。
予想どおり、NHibernateが管理する更新は特定の行では発生しません(これは適切です)。ただし、コミット中に例外はスローされません。トランザクションをロールバックしてユーザーに通知できるように、トランザクションがコミットされたときにStaleObjectStateExceptionが発生することを期待していました。これは予想される動作ではありませんか?私は何かが足りないのですか?
トランザクションをコミットするための私のコードは次のようになります。
_session.BeginTransaction();
...
// load objects in session
IList<ChildEntity> toChange = _session.Find('some condition');
foreach ( var itemToChange in toChange )
{
itemToChange.Status = Status.Updated;
}
...
_session.Transaction.Commit();
アイテムは同じセッションに属し、すべての作業は1つのトランザクション内で完了します。ChildEntityは、オプティミスティックロックがバージョンに設定されているエンティティ基本クラスのサブクラスです。