簡単な監査ログ機能のプロトタイプを作成しています。私は中規模のエンティティ モデル (~50 エンティティ) を持っており、監査ログを約 5 または 6 に実装したいと考えています。最終的には、これを挿入と削除でも機能させたいと考えていますが、今のところアップデートを中心に。
問題は、EventListener 内から auditLog テーブルに session.Save (または SaveOrUpdate) を実行すると、元のオブジェクトは正しく保持 (更新) されますが、AuditLog オブジェクトが挿入されないことです。
セッションがまだ使用されているために、NHibernate セーブ ライフ サイクルの後半に呼び出されるイベント リスナーPre
とイベント リスナーの両方に問題があると思います。Post
//in my ISessionFactory Build method
nHibernateConfiguration.EventListeners.PreUpdateEventListeners =
new IPreUpdateEventListener[]{new AuditLogListener()};
//in my AuditLogListener
public class AuditLogListener : IPreUpdateEventListener
{
public bool OnPreUpdate(PreUpdateEvent @event)
{
string message = //code to look at @event.Entity & build message - this works
if (!string.IsNullOrEmpty(message))
AuditLogHelper.Log(message, @event.Session); //Session is an IEventSource
return false; //Don't veto the change
}
}
//In my helper
public static void Log(string message, IEventSource session)
{
var user = session.QueryOver<User>()
.Where(x => x.Name == "John")
.SingleOrDefault();
//have confirmed a valid user is found
var logItem = new AdministrationAuditLog
{
LogDate = DateTime.Now,
Message = message,
User = user
};
(session as ISession).SaveOrUpdate(logItem);
}
最後のメソッドで session.SaveOrUpdate() にヒットすると、エラーは発生しません。例外はスローされません。それは成功したようで、先に進みます。しかし、何も起こりません。監査ログ エントリがデータベースに表示されることはありません。
これを機能させてこのメソッド内に完全に新しいセッションとトランザクションを作成することができた唯一の方法ですが、コードがリスナーメソッドから戻ってセッションにヒットするため、これは実際には理想的ではありません.Transactionメインアプリで .Commit() を実行し、そのトランザクションが失敗した場合、監査テーブルに孤立したログメッセージがあり、決して起こらなかったことを示しています。
私が間違っている可能性のあるポインタはありますか?
編集
また、このスレッドのいくつかのコメントに基づいて、イベントの子セッションを使用して LogItem を SaveOrUpdate しようとしました。http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener
var childSession = session.GetSession(EntityMode.Poco);
var logItem = new AdministrationAuditLog
{
LogDate = DateTime.Now,
Message = message,
User = databaseLogin.User
};
childSession.SaveOrUpdate(logItem);
データベースのログテーブルにはまだ何も表示されません。エラーや例外はありません。