开发者

NHibernate: Cross thread lazy loading

I have written an application which is using NHibernate to provide the underlying object persistence model.

The data model consists of an object with several string properties and one HashSet property for storing arbitrary pieces of data. This is represented in NHibernate as a class with a set attached to it.

The core of the application is a business rules engine which is running within a threadpool. Following sucessful execution of a ruleset, I am requesting that NHibernate update the object in the DB.

Because it's multi-threaded, I'm making an .OpenSession() call every time I do a DB access to return a new ISession object to do my work, disposing of it after use.

Unfortunately this means I'm unable to take advantage of lazy loading - as if I do enable it, I get lazy loading exception errors all over the place.

I have experiemented with using a mutex to lock-out a single NHibernate session between threads and turning lazy loading on. This works, but is incredibly slow. Profiling shows huge amounts of time is spent waiting for the mutex - and it spoils the parallelism of the application.

Is there a means to have lazy loading enabled in my situation? I.e. cross thread DB accesses.

Or is there another way to approach this problem? Perhaps not explicitly triggering the update each time a rule execution completes? Although one of my main reasons for doing this is so that if the application fails开发者_如何学C, the DB represents the last state of the data within the application.

Any help/pointers you can give would be appreciated.


Neither NHibernate session are thread safe nor are entities usually thread safe. Transactions are used to solve concurrency issues, so it doesn't make sense to run parallel threads in a single transaction.

I don't know what you are using all these threads for. Normally you have a single thread for a single transaction where you can run as many business operations as you want (one after the other).

Your transactions need to hold everything together that belongs to the atomic operation. It is not an option to split an atomic operation into several transaction. It also doesn't make sense to put several independent operations into one transaction just to reuse the session cache (that's what the second level cache is used for).

Solutions

1. Don't use entities in the rules engine. I assume that you have time consuming calculations and want to split it to use several processors. In this case, you may only do the calculations in threads. When the calculations are finished, they return the result to the transaction thread which modifies the entities.

2. Don't use lazy loading: Turn off lazy loading for entities you need for the rules. This may be specified in the query.

3. Load entity values within the main thread: this is probably the most complicated way. Write a service which is ran in the main thread. It takes lambda expressions as argument which access entity properties. The expressions are queued and executed in the main thread and the result returned to the calling thread.

var myValue = entity.ExecuteInMainThread(x => x.Property);

I can't even say if this would be blocking the threads too much. By the way, you can find out if a collection or proxy is loaded or not using the NHibernate tools, so you only need to go back to the main thread when it is not. Of course, only certain properties require this, but to be consistent every property should be accessed the same way.


The longer I think about the problem, the more I think that it would be nice to have such a feature implemented by the proxies itself. The proxy needs to start a service running in the thread where it had been created in. Then it queues lazy loading in that service instead of executing it itself. This would be completely transparent to the calling code.

In case you would implement "thread safe lazy loading", you could implement it as a separate proxy implementation. This makes it reusable without touching NH's core. It would be a nice contribution to NH.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜