I am writing a WPF application. So far things have been working well
but I just hit a big problem that has stymied me most of the day
today. In going back and regression testing some code that was
working fine, it is now failing. The best I can figure is that this
is the result of my upgrade from NH 2.1.1 to 2.1.2 a few days back.
I have not had time to revert the upgrade to prove that, but here is
what is happening.
I have some DAL code that, boiled down to its essence looks like this:
<pre>
public void SaveEntries(IEnumerable<MasterFileEntry> entries)
{
var sessionFactory = ((SessionManager)
SessionManager).SessionFactory;
var session = sessionFactory.OpenSession();
global::NHibernate.Context.CurrentSessionContext.Bind(session);
var transaction = session.BeginTransaction();
try
{
foreach (var entry in entries)
session.Save(entry);
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
finally
{
global::NHibernate.Context.CurrentSessionContext.Unbind(session.SessionFactory);
session.Dispose();
}
}
</pre>
In the real code the session, and transaction are created and bound/
unbound higher up the call stack, but I have flattened the code out at
part of testing to simplify things.
Now the call to this code looks like this:
<pre>
private void SaveImportedData(object sender, ExecutedRoutedEventArgs
e)
{
_view.ShowViewAsBusy();
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (x, y) =>
_model.AddEntries(_importedData.Data);
backgroundWorker.RunWorkerCompleted += (x, y) =>
{
_view.ShowViewAsNotBusy();
_dialogService.DisplayMessageBox(
string.Format(IMPORT_SUCCESS_DIALOG_MESSAGE,
_importedData.Data.Rows.Count),
IMPORT_SUCCESS_DIALOG_TITLE);
_shell.CloseViewUnconditionally(_view);
};
backgroundWorker.RunWorkerAsync();
</pre>
When this code executes, I am now getting the following error when
session.Save(entry) is invoked.
System.InvalidOperationException occurred
Message="ExecuteReader requires the command to have a transaction
when the connection assigned to the command is in a pending local
transaction. The Transaction property of the command has not been
initialized."
Source="System.Data"
StackTrace:
at System.Data.SqlClient.SqlCommand.ValidateCommand(String
method, Boolean async)
at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, DbAsyncResult result)
at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method)
at
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior
behavior, String method)
at
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior
behavior)
at
System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand
cmd)
at
NHibernate.Id.IdentityGenerator.InsertSelectDelegate.ExecuteAndExtract(IDbCommand
insert, ISessionImplementor session)
at
NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo
insertSQL, ISessionImplementor session, IBinder binder)
at
NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[]
fields, Boolean[] notNull, SqlCommandInfo sql, Object obj,
ISessionImplementor session)
at
NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[]
fields, Object obj, ISessionImplementor session)
at NHibernate.Action.EntityIdentityInsertAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable
executable)
at
NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object
entity, EntityKey key, IEntityPersister persister, Boolean
useIdentityColumn, Object anything, IEventSource source, Boolean
requiresImmediateIdAccess)
at
NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object
entity, Object id, IEntityPersister persister, Boolean
useIdentityColumn, Object anything, IEventSource source, Boolean
requiresImmediateIdAccess)
at
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object
entity, String entityName, Object anything, IEventSource source,
Boolean requiresImmediateIdAccess)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent
event)
at
NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent
event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent
event)
at
NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent
event)
at
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent
event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent
event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at
SLS.ClaimsProcessing.Backend.DataAccess.MasterFileRepository.SaveEntries(IEnumerable`1
entries) in C:\SVN\SLS\SLS.ClaimsProcessing.Backend\DataAccess
\MasterFileRepository.cs:line 59
InnerException:
In addition to the exception, debugging has shown that the call to
session.BeginTransaction() is returning null.
I have tried both the "call" and "thread_static" settings for
current_session_context_class.
Two interesting points have been discovered while debugging:
1) If I comment out the CurrentSessionContext.Bind() and
CurrentSessionContext.UnBind statements then things work fine.
Session.BeginTransaction() returns an appropriate reference and
session.Save(entity) works correctly. This is not practical solution
in the real code base because the Bind() and Unbind() calls are
occurring higher up in the call chain where it is not known that this
routine is the only one in the current unit of work.
2) If I recode the SaveImportedData() method to not use a background
thread but call the DAL on the UI thread, again everything works fine,
even when CurrentSessionContext.Bind() and
CurrentSessionContext.UnBind() are invoked. Likewise this is not a
viable solution for obvious reasons.
Is anyone else having issues like this? Any suggestions on how to get
around this? Time permitting, next week I will try to revert back to
the prior NH version but I am hoping I can move forward with 2.1.2.
Kind Regards,
--Ken
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en.