Nhibernate with TransactionScope Error - DTC transaction prepre phase failed -- Upgrade to Nhibernate 3.0 - nhibernate

I am getting the following exception when using Nhibernate and ADO.Net operations inside the transaction Scope.Eg. It was fine with Nhibernate 2.1 but now upgraded to 3.0 which throws error.
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
GetmemberId(); --> NHibernate Call
Update(); ADO Call OracleDB
}
Since this acts as ambient transaction, Nhibernate tries to dispose the transaction soon before the outer transaction completes.correct me if I am wrong, Is there any solution because help me , But When I move the Nhibernate call outside TransactionScope everything works fine. The example I have given is sample one, mines involves a more complex one, since I have keep both the calls inside TransactionScope and the error Iam getting is as following,
ERROR 13 NHibernate.Impl.AbstractSessionImpl - DTC transaction prepre
phase failed System.ObjectDisposedException: Cannot access a disposed
object. Object name: 'Transaction'. at
System.Transactions.Transaction.DependentClone(DependentCloneOption
cloneOption) at
System.Transactions.TransactionScope.SetCurrent(Transaction
newCurrent) at System.Transactions.TransactionScope.PushScope()
at System.Transactions.TransactionScope.Initialize(Transaction
transactionToUse, TimeSpan scopeTimeout, Boolean interopModeSpecified)
at System.Transactions.TransactionScope..ctor(Transaction
transactionToUse) at
NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.DistributedTransactionContext.System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment
preparingEnlistment) 2011-02-08 13:41:46,033 ERROR 13
NHibernate.Impl.AbstractSessionImpl - DTC transaction prepre phase
failed System.ObjectDisposedException: Cannot access a disposed
object. Object name: 'Transaction'. at
System.Transactions.Transaction.DependentClone(DependentCloneOption
cloneOption) at
System.Transactions.TransactionScope.SetCurrent(Transaction
newCurrent) at System.Transactions.TransactionScope.PushScope()
at System.Transactions.TransactionScope.Initialize(Transaction
transactionToUse, TimeSpan scopeTimeout, Boolean interopModeSpecified)
at System.Transactions.TransactionScope..ctor(Transaction
transactionToUse) at
NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.DistributedTransactionContext.System.Transactions.IEnlistmentNotification.Prepare(PreparingEnlistment
preparingEnlistment)

Try
Configuration.SetProperty(Environment.TransactionStrategy,"NHibernate.Transaction.AdoNetTransactionFactory")
Or in nhibernate config
<property name="transaction.factory_class">
NHibernate.Transaction.AdoNetTransactionFactory
</property>
It worked for me =)

We ran into this same error, and it was caused by the way we used sessions and transactions in our Web Api with NHibernate.
We should have been using session-per-request. (This can be a web request or the execution of a NServiceBus handler.) When a request starts, you should open a session and start a transaction.
We were not doing that. In our repositories, we created a new session and transaction for every database request. This meant that rather than having a single session/transaction for a request, we had many.
The root cause of the bug for us was that we were loading an entity (domain model object) in one session, modifying it, and saving it using a different session. By the time NHibernate executed the update call, the loading session/transaction had already been committed, flushed, and closed.
Solution was to pull our session/transaction creation out of the repositories and up to the Controller layer (doable using a HttpModule for REST calls and/or with aspect oriented programming using dependency injection). This one session/transaction then lives for the lifetime of the REST call or NServiceBus handler execution and is used for all database access during that call. When that call ends, it will be committed or rolled back as appropriate.
The answer given above setting the config property simply turns off DTC and reverts to the older way of doing NHibernate transactions. That may solve the problem for you if you never have to scale up your Web Api to multiple instances, but if you do, this will cause you problems.

Related

Is it bad not to dispose ISession

I have NHibernate hooked up in my asp.net mvc application
The ISession is injected into the repository.
I can not use the session per request pattern because i need a session per conversation aproach.
The NHibernate ISession is used across multiple http requests. The object graph is big and i don't want to load the entire graph in every request. That's why the ISession is stored in the users HttpSession.
The lifecycle of the ISession is configured with StructureMap:
For<ISession>().LifecycleIs(new HttpSessionLifecycle()).Use(x =>
{
var sessionSource = x.GetInstance<ISessionSource>();
return sessionSource.CreateSession();
});
At the end of the conversation i call
Session.Clear()
to clear the ISession.
When the user creates a new conversation, StructureMap creates a new ISession.
I did not found a way of disposing the ISession.
So is it bad not to dispose it?
Is this holding connections to the database?
In general NHibernate won't keep open connection to DB longer then it needs to. It uses SQL Server connection pool to get connections quickly and return them. So in terms of open connection its not a problem not to dispose a session.
But session also keeps track of all changes in entities and flushes them in DB on dispose/commit transaction, just keep in mind that this feature is there and might chase you
Also be aware about following issue:
https://nhibernate.jira.com/browse/NH-3046
In some scenarios (if you don't use transactions or if you often perform rollback of transactions) long-living sessions can "eat" a lot of memory. But all allocated memory will be released when session is disposed and collected by GC.

Castle ActiveRecord SessionScopeWebModule exception handling

I have a Web app with SessionScopeWebModule enabled, and I wonder how
to best handle business exceptions (not Hibernate / DB exceptions).
I believe AR 2.0 SessionScopeWebModule implicitly implements
transaction - if an exception occurs during the request, changes made
during the session will be discarded / rolled back.
For my Web app, the business layer will be chatty with the DB, issuing
several CRUDs, say
Create entity A
Create entity B
Say entity A has been created. However upon creating entity B some
business rules were not observed and the business layer throws a
business exception.
From the UI perspective, it's best to 'handle' the business exception
and display a friendly message back to the user. This is where the
problem lies. If the exception is already handled,
SessionScopeWebModule goes along thinking everything is fine at the
end of the request and commits the entity A into database, without
entity B.
What is the best practice to handle exceptions in this case? I'm
thinking of a session variable that will be reset for each new
request. If an exception occurs, the variable will be marked dirty.
When the request ends, the SessionScopeWebModule will first check the
session to see if any exception has occured. If so, it will invoke a
FailSession.
Is this the way to go? And would FailSession do the job of discarding
changes to a session?
Thanks!
Boyan
on the website http://www.summerofnhibernate.com/ I have sean a web-chast about this topic (it's part 13), but with NHibernate directly (without ActiveRecord). I explains how and why the Session saves/flushes and how to stop it from doing that. Perhaps the informations from that video can help you.
Greetings
Juy Juka

WCF Custom Message Writing With Transaction Support

I'm using a custom message that inherits the System.Servicemodel.Channels.Message.
My custom message get IEnumerable collection which pulled from a database.
The WCF service is transactional (which is already tested).
MS-DTC is enabled.
Problem is, that when the protected override void OnWriteBodyContents(XmlDictionaryWriter writer) method is executed at the custom message, there is no transaction.
The System.Transactions.Transaction.Current is null. while executing the service the transaction flow is works fine, but when the message is written by WCF mechanism, it's seems like it's out of a transaction which cause the DB command (of pulling the data) to be executed without transaction.
Please note, that if I'm passing simple array instead of IEnumerable the DB action is executed under transaction, but I want it to be executed parallelly with the response writing.
Any ideas please, why the transaction is missing and what can be done to activate it?
many thanks!
Tamir.
Transaction are generally attached to your current thread or calling context. So if you are initiating transaction on different thread and message serialization is happing on another thread then transaction won't be available on that thread. You should look at TransactionScope and DependentTransaction for supporting such scenarios.

Castle Windsor Interceptor and Unit Of Work

Is Castle Windsor's Inteceptor mechanism considered to be a good/effective way of implementing the Unit of Work pattern?
My project involves Castle Windsor, the NHibernate Facility and of course NHibernate - all used in self-hosted WCF services.
Each service method normally requests from the Windsor container an instance of a helper class into which the WCF call is delegated. The helper class has an ISessionManager constructor argument which Windsor resolves via the NHibernate Facility.
The trouble is, the helper class is doing too much work. It has both logic and data access intermingled which means its difficult (virtually impossible) to test and difficult to read.
What I want is to re-arrange responsibilities
I don't want the WCF helper to know anything about transactions or sessions, so no ISessionManager constructor arg, no references to transactions and no ISession.
In order for the WCF helper to do data access, its going to have to rely on a new helper, dare I call it a DAO? or God forbid a repository, on which will be methods for fetching, querying, and possibly saving domain objects.
The problem with returning NHibernate proxied objects from a DAO is that if the session is closed before the entity is returned, any subsequent attempt to access collections on the domain object from the client code will result in an exception as the session is no longer there to be used to lazily fetch the required data. It's obvious really, but everyone new to NHibernate must hit this issue.
So if DAOs and Repos cant close the session, what does?
What I need is one NHibernate session per WCF service operation call, where several DAOs or Respositories can call OpenSession as much as they like, but they all get the same session, and ideally, any attempt to dispose the session would be ignored unless its the last Dispose. Not sure about the last bit, but maybe DAOs and repos just call ISessionManager.OpenSession and leave it to something else to flush and dispose the session.
I thought maybe I could use an interceptor which takes an ISessionManager, opens a session and starts a transaction, forwards the invocation, then if no exception occurs, commits the transaction and disposes the session, otherwise rolls back the transaction if any exception occurs.
Any thoughts?
So if DAOs and Repos cant close the
session, what does?session, what does?
Services own units of work, not DAOs. They demark units of work.
Spring manages transactions using AOP, so interceptors sound like a good bet for transaction management to me.
As far as sessions go, those are UI concepts, so it ought to be the web or desktop UI controller that opens the session, marshals services to fulfill use cases, and closes the session when it's complete.
Castle.Service.Transactions also ties well together with the rest of the castle stack and allow you to use AOP to handle transactions.
Have a look at v3!
https://github.com/haf/Castle.Services.Transaction
And the wiki there!
I also created a new NHibernate Facility:
https://github.com/haf/Castle.Facilities.NHibernate/wiki/NHibernate-Facility---Quick-Start

How do I tell if enteties changed in the current transaction with nhibernate?

I have a web service that uses nhibernate, calls to the web service go to a simple method that opens the session, begins a transaction and then calls code I don't control that sometimes modifies entities, after that code returns the transaction is commited.
I need to add some extra processing inside the transaction that only happens if entities actually changed, I don't control the code that is called from the web service and I can't change it or make it return any additional information.
That code may even flush the nhibernate session.
How can I tell if any entity changed in the current transaction?
Thanks
ISession has .IsDirty() that would indicate that upon flush, something would be written to the database.