0

簡単な監査ログ機能のプロトタイプを作成しています。私は中規模のエンティティ モデル (~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);

データベースのログテーブルにはまだ何も表示されません。エラーや例外はありません。

4

1 に答える 1

3

OnPreUpdate メソッドで子セッション currentSession.GetSession(EntityMode.Poco) を作成し、これを log メソッドで使用する必要があります。flushmode の設定によっては、子セッションもフラッシュする必要がある場合があります。

また、独自のソリューションを展開したい特定の理由はありますか? 参考までに、NHibernate Envers は現在、かなり成熟したライブラリです。

于 2014-01-10T09:26:07.343 に答える