Intercepting NHibernate persistence operations on ICollection's properties (many associations)

馋奶兔 提交于 2019-12-09 23:50:35

问题


I would like to intercept persistence operations over collection properties, decide by myself if it can be synchronized with database, and call a procedure when a persistence is decided to occur over all collection at once and not by each element.

How to do that ?

These collection properties are usually mapped with one-to-many or many-to-many associations. So, when we have something like this:

myEntity.List.Add(new Item());
myEntity.List.Add(new Item());
...
session.Save(myEntity);

For a mapping having two classes (entities) and an unidirectional many-to-many association, I would like to have only two sql statements occurring: INSERT INTO, and a PROCEDURE CALL which expects to receive a list of values comma-separated that is the key values from the List collection above. The collection of keys can only be saved on this system calling a procedure with a list of values (csv).

This kind of customizing is possible to be done ?


回答1:


Well, I adopted a solution implementing NHibernate Listeners, so I have a listener like that:

public class CustomSaveUpdateEventListener : IPostInsertEventListener, IPostUpdateEventListener {

    private void ScheduleToCommit(AbstractPostDatabaseOperationEvent @event) {
        // Some filter
        if (@event.Entity.GetType().FullName.Equals(MY_ENTITY_TO_INTERCEPTS) {
            object o = @event.Entity;

            // Some logic...
            // ...
            // ...

            IQuery namedQuery = @event.Session.GetNamedSQLQuery(MY_NAMED_QUERY);
            //namedQuery.SetParameter(...); // <== You can set parameters
            //namedQuery.ExecuteUpdate(); // <== DO NOT EXCEUTE HERE, this launches more events recursively and can generate stackoverflow

            @event.Session.ActionQueue.RegisterProcess(new MyActionBeforeCommit(@event, namedQuery).SaveValuesOperation);
            }
        }
    }

    public void OnPostInsert(PostInsertEvent @event) {
        ScheduleToCommit(@event);
    }


    public void OnPostUpdate(PostUpdateEvent @event) {
        ScheduleToCommit(@event);
    }
}

And my object MyActionBeforeCommit() is scheduled to run only when and if a transaction is commited. So, in my "future action" I have:

public class MyActionBeforeCommit {
    private AbstractPostDatabaseOperationEvent e;

    private IQuery query;

    public MyActionBeforeCommit(AbstractPostDatabaseOperationEvent e, IQuery query) {
        this.e = e;
        this.query = query;
    }

    public void SaveValuesOperation() {
        // Here your query will be executed only when a transation is commited, if 
        // it's rolledback this won't be executed
        query.ExecuteUpdate(); 
    }
}

And finally we need to register the new listener on NHibernate configuration, like that:

Configuration.SetListener(ListenerType.PostInsert, new    CustomSaveUpdateEventListener());
Configuration.SetListener(ListenerType.PostUpdate, new CustomSaveUpdateEventListener());

And It works very well. This is a very nice NHibernate feature, very powerful.




回答2:


I've waited a while to respond, because I know a possible approach, but never did it myself.

It sounds like you need to write a custom NHibernate "Dialect". There is are some guidelines here and here how to do it.

You don't mention the database system you use, but your starting point would obviously be to take the the dialect for that system and find the places where you should put your customizations.

Overriding Dialects is fully supported by NHibernate. If this does not work for you, you may even have to look at a custom AbstractEntityPersister, but I don't know how to that with configuration file entries.

You can find NHibernate 3.2 sources here.

A completely different approach could be to use standard NHibernate persistence to a local database, e.g. sql-server CE, and execute a synchronization script for the "real" persistence.



来源:https://stackoverflow.com/questions/9199078/intercepting-nhibernate-persistence-operations-on-icollections-properties-many

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!