Is it possible to stop MassTransit Runtime Services from requiring DTC? - nhibernate

I'm getting started using MassTransit and need to use the RuntimeServices to manage subscriptions and timeouts. The environment I'm installing into is an externally facing network divided up in to segments using firewalls.
Currently the application server where RuntimeServices is to be installed and the SQL Server do not have RPC ports open that would allow Distributed Transaction Coordinator (DTC) to work correctly.
The complete exception I am getting is listed below but the important part looks like it is System.Transactions.TransactionException: The operation is not valid for the state of the transaction.. I don't believe that the transaction is getting off the ground since DTC is not configured.
Although I should be able to ask for the correct ports to be opened I am reluctant to do so as I'm not that concerned about transactions for this purpose. So ideally I'd like to tell MassTransit or perhaps is it nHibernate that I don't require distributed transactions.
BTW my MS Message Queue is non-transactional.
Any help welcome with thanks,
Rob
Full exception stack trace:
MassTransit.Context.ServiceBusReceiveContext-'System.Action'1[[MassTransit.IConsumeContext, MassTransit, Version=2.6.416.0, Culture=neutral, PublicKeyToken=null]]' threw an exception consuming message 'MassTransit.Context.ReceiveContext' NHibernate.Exceptions.GenericADOException: could not execute query
[ select subscripti0_.CorrelationId as Correlat1_1_, subscripti0_.CurrentState as CurrentS2_1_, subscripti0_.ControlUri as ControlUri1_, subscripti0_.DataUri as
DataUri1_ from dbo.SubscriptionClientSaga subscripti0_ where subscripti0_.CurrentState=? ]
Name:p1 - Value:Active (State)
[SQL: select subscripti0_.CorrelationId as Correlat1_1_, subscripti0_.CurrentState as CurrentS2_1_, subscripti0_.ControlUri as ControlUri1_, subscripti0_.DataUri as DataUri1_ from dbo.SubscriptionClientSaga subscripti0_ where subscripti0_.CurrentState=?] ---> System.Transactions.TransactionException: The operation is not valid for the state of the transaction.
at System.Transactions.TransactionState.EnlistVolatile(InternalTransaction tx, IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions, Transaction atomicTransaction)
at System.Transactions.Transaction.EnlistVolatile(IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions)
at NHibernate.Transaction.AdoNetWithDistributedTransactionFactory.EnlistInDis
tributedTransactionIfNeeded(ISessionImplementor session)
at NHibernate.Impl.AbstractSessionImpl.EnlistInAmbientTransactionIfNeeded()
at NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus()
at NHibernate.Impl.SessionImpl.get_Batcher()
at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
--- End of inner exception stack trace ---
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
... (elided for brevity!) ...

Transactions are automatically promoted to DTC in certain cases: http://msdn.microsoft.com/en-us/library/ms131083.aspx
You definitely want to avoid that from happening - it kills the performance, options:
Subscription service is not resource-intensive, host its database
locally.
Evaluate the scope used for message consumption, see if you can reduce it
If using MSMQ, use multicasting instead of subscription service
Consider using RabbitMQ instead - no subscription service required
https://groups.google.com/forum/?fromgroups#!forum/masstransit-discuss is where you can get help with MassTransit quickly.
Cheers,
ET.

Related

SQL Service Broker Severe Error Receiving Messages after DB Blocking

We use SQL Service Broker queues to notify our application of new records that meet certain criteria being added to a table in another application's database. This is accomplished by having an after insert trigger run a query with for xml against the inserted virtual table and insert any results into a specific service broker queue. We then have a Notifier object that receives from the service broker queue and invokes a callback for each message received. Our code to receive from the Service Broker queue is as follows:
let receiveXmlMessage connection transaction (cancellation: CancellationToken) queueName messageTypeName =
task {
let commandTimeout = if cancellation.IsCancellationRequested then 1 else 0
let receiveQuery =
sprintf """WAITFOR
(
RECEIVE TOP(1)
#message = CONVERT(xml, message_body),
#messageType = message_type_name,
#dialogId = conversation_handle
FROM dbo.[%s]
), TIMEOUT 60000;""" (sanitize queueName)
use receiveCommand =
match transaction with
| Some tx -> new SqlCommand(receiveQuery, connection, tx, CommandTimeout = commandTimeout)
| None -> new SqlCommand(receiveQuery, connection, CommandTimeout = commandTimeout)
receiveCommand.Parameters.AddRange([| SqlParameter("#message", SqlDbType.Xml, Direction = ParameterDirection.Output);
SqlParameter("#messageType", SqlDbType.NVarChar, Direction = ParameterDirection.Output, Size = 256);
SqlParameter("#dialogId", SqlDbType.UniqueIdentifier, Direction = ParameterDirection.Output); |])
try
let! receiveResult = receiveCommand.ExecuteNonQueryAsync(if commandTimeout = 0 then cancellation else CancellationToken.None)
if receiveResult > 0
then let messageType = receiveCommand.Parameters.["#messageType"].Value |> unbox<string>
let dialogId = receiveCommand.Parameters.["#dialogId"].Value |> unbox<Guid>
if messageType = messageTypeName
then do! endConversation connection transaction dialogId
return receiveCommand.Parameters.["#message"].Value |> unbox<string> |> XDocument.Parse
else return XDocument()
else return XDocument()
with | ex ->
log.errorxf ex "Failed to receive message from Service Broker Queue %s" queueName
return! Task.FromException ex
}
This was working fine for several months, processing millions of messages, until a few days ago, when we had another process cause extensive blocking on the database we monitor and our DBAs had to terminate several database sessions to relieve the contention. Ever since this incident, our application has encountered the following error when attempting to receive from the Service Broker queue:
2018-01-11 07:50:27.183-05:00 [31] ERROR - Failed to receive message from Service Broker Queue Notifier_Queue
System.Data.SqlClient.SqlException (0x80131904): A severe error occurred on the current command. The results, if any, should be discarded.
Operation cancelled by user.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.CompleteAsyncExecuteReader()
at System.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult)
at System.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Application.Common.Sql.ServiceBroker.receiveXmlMessage#257-3.Invoke(Unit unitVar0)
at Application.Common.TaskBuilder.tryWith[a](FSharpFunc`2 step, FSharpFunc`2 catch)
New messages are successfully added to the queue, and we are able to receive messages from the same queue using SSMS, or even an F# interactive session running as the same user as the application. It only appears to be our application that is affected, but it does seem to affect all instances of our application, on different servers, as long as they are connected to this specific database. We have tried restarting the application and the SQL Server, and we have tried running an ALTER DATABASE ... SET NEW_BROKER WITH ROLLBACK IMMEDIATE. Nothing we've tried has made a difference, we still end up encountering the same exception, and we have hundreds of thousands of conversations remaining the CONVERSING status, since our code to call END CONVERSATION is only invoked after successfully receiving a message.
Our SQL Service Broker queues are setup to model the monologue pattern as described in this blog post.
How can we diagnose the cause of this rather non-specific exception that our application is returning from SQL Server? Is there anything else we could try to diagnose and/or correct whatever changed between our application and SQL Service Broker when the problem first occurred?
We finally figured out what was causing this error when we tried to receive from the Service Broker queue. As it turns out, the CancellationToken that is passed in to our receiveXmlMessage function was being cancelled by other logic in our application that monitors the number of conversing conversations and attempts to recreate our Notifier object if the number of conversing conversations exceeds a certain threshold and the most recently closed conversation is older than another threshold. Due to a bug in the logic for the age of the most recently closed conversation, effectively only the number of conversing conversations was being used to reset the Notifier, and when the DB blocking occurred last week, over 150,000 conversing conversations accumulated. This caused our application to continually cancel the CancellationToken while we were trying to receive messages from Service Broker. Once we took our application down, cleaned up all the conversing conversations, and fixed the bug in the date math for the last closed conversation, the error stopped occurring.
It may be useful to note, for anyone encountering the message:
A severe error occurred on the current command. The results, if any, should be discarded.
That this can be the result of the CancellationToken passed to the ExecuteNonQueryAsync/ExecuteReaderAsync/ExecuteScalarAsync/ExecuteXmlReaderAsync method on the SqlCommand being cancelled while the method is executing.

RavenDB connection issues

We have seen a noticeable uptick in problems related to RavenDB connections. We're using the IIS server connection method.
I've checked the index errors and I don't see anything listed.
This server is replicated with a MySQL server and there is one error related to replication in the log from today. Could the client stack trace errors actually be coming from the replicated server and not Raven?
EDIT
The client in this case is a single job that runs a few hundred times a day...succeeding many of those times but increasing in failures due to these errors.
Sql Replication failure to replication
Here are the partial stack trace errors from the client log:
[WebException: Unable to connect to the remote server]
System.Net.HttpWebRequest.GetRequestStream(TransportContext& context):367
System.Net.HttpWebRequest.GetRequestStream():3
Raven.Abstractions.Connection.HttpRequestHelper.WriteDataToRequest(HttpWebRequest req, String data, Boolean disableCompression):7
Raven.Client.Connection.ServerClient.DirectBatch(IEnumerable`1 commandDatas, String operationUrl):171
Raven.Client.Connection.ReplicationInformer.TryOperation[T](Func`2 operation, String operationUrl, Boolean avoidThrowing, T& result, Boolean& wasTimeout):35
Raven.Client.Connection.ReplicationInformer.ExecuteWithReplication[T](String method, String primaryUrl, Int32 currentRequest, Int32 currentReadStripingBase, Func`2 operation):169
Raven.Client.Connection.ServerClient.ExecuteWithReplication[T](String method, Func`2 operation):33
Raven.Client.Document.DocumentSession.SaveChanges():65
and
[WebException: Unable to connect to the remote server]
System.Net.HttpWebRequest.GetResponse():570
Raven.Client.Connection.HttpJsonRequest.ReadJsonInternal(Func`1 getResponse):45
Raven.Client.Connection.HttpJsonRequest.ReadResponseJson():206
Raven.Client.Connection.ServerClient.DirectGet(String[] ids, String operationUrl, String[] includes, String transformer, Dictionary`2 queryInputs, Boolean metadataOnly):631
Raven.Client.Connection.ServerClient+<>c__DisplayClass77.<Get>b__76(String u):51
Raven.Client.Connection.ReplicationInformer.TryOperation[T](Func`2 operation, String operationUrl, Boolean avoidThrowing, T& result, Boolean& wasTimeout):35
Raven.Client.Connection.ReplicationInformer.ExecuteWithReplication[T](String method, String primaryUrl, Int32 currentRequest, Int32 currentReadStripingBase, Func`2 operation):169
Raven.Client.Connection.ServerClient.ExecuteWithReplication[T](String method, Func`2 operation):33
Raven.Client.Document.HiLoKeyGenerator.GetDocument(IDatabaseCommands databaseCommands):41
Raven.Client.Document.HiLoKeyGenerator.GetNextRange(IDatabaseCommands databaseCommands):109
Raven.Client.Document.HiLoKeyGenerator.NextId(IDatabaseCommands commands):58
Raven.Client.Document.HiLoKeyGenerator.GenerateDocumentKey(IDatabaseCommands databaseCommands, DocumentConvention convention, Object entity):9
Raven.Client.Document.MultiTypeHiLoKeyGenerator.GenerateDocumentKey(IDatabaseCommands databaseCommands, DocumentConvention conventions, Object entity):174
Raven.Client.Document.DocumentStore+<>c__DisplayClass4.<Initialize>b__2(String dbName, IDatabaseCommands databaseCommands, Object entity):20
Raven.Client.Document.DocumentConvention.GenerateDocumentKey(String dbName, IDatabaseCommands databaseCommands, Object entity):164
Raven.Client.Document.GenerateEntityIdOnTheClient.GenerateDocumentKeyForStorage(Object entity):46
Raven.Client.Document.InMemoryDocumentSessionOperations.StoreInternal(Object entity, Etag etag, String id, Boolean forceConcurrencyCheck):79
Raven.Client.Document.InMemoryDocumentSessionOperations.Store(Object entity):23
The error says the client cannot connect to the the server. Maybe the client is offline. Or the server is. Or a firewall is in the way. Or maybe the server is there but blows up before returning a response to the client. If the issue is intermittent, and users arent complaining, it's probably just a connectivity thing that you can ignore. If users are complaining, you should look in server-side logs.

Cannot setup Windows Authentication without a valid commercial license

NServiceBus 3+ uses RavenDB for persistence by default. Several articles (this, this and this) mention that as long as RavenDB is used only to store NServiceBus data (Subscription, Saga, Timeouts), NServiceBus license is enough and separate RavenDB license is not required. However, the current version of RavenDB (Build 2700) doesn't allow the authentication to be setup on the server and throws below error (Cannot setup Windows Authentication without a valid commercial license). Does this mean that we can no longer use RavenDB (at least the latest version) with NServiceBus without a separate license? This works fine at least until build 2380. That is when the version is changed from v2.0 to v2.5. Using persistence without authentication is not an option as while Subscription and Timeouts are NServiceBus specific data, sagas can and do contain sensitive data that cannot be allowed to be accessible via http to everyone (even within LAN). Buying a license for RavenDB is not that big an issue but so far we understood that we only need NServiceBus license as long as RavenDB is not used for anything other than NServiceBus data. It would be great to get a clarification on this from NServiceBus or RavenDB team.
Server Error:
-----------------------------------------
/bulk_docs
Raven.Abstractions.Exceptions.OperationVetoedException: PUT vetoed by Raven.Database.Server.Security.Triggers.WindowsAuthPutTrigger because: Cannot setup Windows Authentication without a valid commercial license.
at Raven.Database.DocumentDatabase.AssertPutOperationNotVetoed(String key, RavenJObject metadata, RavenJObject document, TransactionInformation transactionInformation) in c:\Builds\RavenDB-Stable\Raven.Database\DocumentDatabase.cs:line 931
at Raven.Database.DocumentDatabase.<>c__DisplayClass4b.<Put>b__43(IStorageActionsAccessor actions) in c:\Builds\RavenDB-Stable\Raven.Database\DocumentDatabase.cs:line 779
at Raven.Storage.Esent.TransactionalStorage.Batch(Action`1 action) in c:\Builds\RavenDB-Stable\Raven.Database\Storage\Esent\TransactionalStorage.cs:line 605
at Raven.Database.DocumentDatabase.Put(String key, Etag etag, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) in c:\Builds\RavenDB-Stable\Raven.Database\DocumentDatabase.cs:line 772
at Raven.Database.Extensions.CommandExtensions.Execute(ICommandData self, DocumentDatabase database, BatchResult batchResult) in c:\Builds\RavenDB-Stable\Raven.Database\Extensions\CommandExtensions.cs:line 50
at Raven.Database.Extensions.CommandExtensions.ExecuteBatch(ICommandData self, DocumentDatabase database) in c:\Builds\RavenDB-Stable\Raven.Database\Extensions\CommandExtensions.cs:line 23
at Raven.Database.DocumentDatabase.ProcessBatch(IList`1 commands) in c:\Builds\RavenDB-Stable\Raven.Database\DocumentDatabase.cs:line 2086
at Raven.Database.DocumentDatabase.<>c__DisplayClass107.<Batch>b__103(IStorageActionsAccessor actions) in c:\Builds\RavenDB-Stable\Raven.Database\DocumentDatabase.cs:line 2048
at Raven.Storage.Esent.TransactionalStorage.ExecuteBatch(Action`1 action, EsentTransactionContext transactionContext) in c:\Builds\RavenDB-Stable\Raven.Database\Storage\Esent\TransactionalStorage.cs:line 663
at Raven.Storage.Esent.TransactionalStorage.Batch(Action`1 action) in c:\Builds\RavenDB-Stable\Raven.Database\Storage\Esent\TransactionalStorage.cs:line 615
at Raven.Database.DocumentDatabase.Batch(IList`1 commands) in c:\Builds\RavenDB-Stable\Raven.Database\DocumentDatabase.cs:line 2046
at Raven.Database.Server.Responders.DocumentBatch.Batch(IHttpContext context) in c:\Builds\RavenDB-Stable\Raven.Database\Server\Responders\DocumentBatch.cs:line 124
at Raven.Database.Server.Responders.DocumentBatch.Respond(IHttpContext context) in c:\Builds\RavenDB-Stable\Raven.Database\Server\Responders\DocumentBatch.cs:line 41
at Raven.Database.Server.HttpServer.DispatchRequest(IHttpContext ctx) in c:\Builds\RavenDB-Stable\Raven.Database\Server\HttpServer.cs:line 782
at Raven.Database.Server.HttpServer.HandleActualRequest(IHttpContext ctx) in c:\Builds\RavenDB-Stable\Raven.Database\Server\HttpServer.cs:line 645
-----------------------------------------
at Raven.Studio.Infrastructure.InvocationExtensions.Catch(Task parent, Func`2 func)
at Raven.Studio.Infrastructure.InvocationExtensions.Catch(Task parent, Action`1 action)
at Raven.Studio.Infrastructure.InvocationExtensions.Catch(Task parent)
at Raven.Studio.Infrastructure.Command.Execute(Object parameter)
at System.Windows.Controls.Primitives.ButtonBase.ExecuteCommand()
at System.Windows.Controls.Primitives.ButtonBase.OnClick()
at System.Windows.Controls.Button.OnClick()
at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName, UInt32 flags)
Client side exception:
System.Net.WebException: [HttpWebRequest_WebException_RemoteServer]
Arguments: NotFound
Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=5.1.20125.0&File=System.Windows.dll&Key=HttpWebRequest_WebException_RemoteServer
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Func`2.Invoke(T arg)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise)
Have you contacted NServiceBus support?
We will gladly send you a RavenDB license, just contact us!

How do I configure distributed transactions for NServiceBus

I have the following scenario.
First write something to a db
Send message on bus
I want to execute those like an atomic action, that is, running them in a transaction but can't get it to work when it is really distributed. Everything was working fint on local machine, but as soon as the service was on another machine it stopped working.
My code looks something like this:
using(var ts = new TransactionScope())
{
// Write something to db
_bus.Send(SomeMessage);
ts.Complete();
}
I have done everything I could think of and find information about, like enabling DTC on client, server and db with inbound and outbound enabled, set the port DCOM protocols to 5000-6000. The error I get is:
FailedToSendMessageException: "Failed to send message to address: myserver"
and the stacktrace is:
at NServiceBus.Transports.Msmq.MsmqMessageSender.ThrowFailedToSendException(Address address, Exception ex) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Transports\Msmq\MsmqMessageSender.cs:line 89
at NServiceBus.Transports.Msmq.MsmqMessageSender.Send(TransportMessage message, Address address) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Transports\Msmq\MsmqMessageSender.cs:line 80
at NServiceBus.Unicast.UnicastBus.SendMessage(List`1 addresses, String correlationId, MessageIntentEnum messageIntent, Object[] messages) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Unicast\UnicastBus.cs:line 658
at NServiceBus.Unicast.UnicastBus.SendMessage(Address address, String correlationId, MessageIntentEnum messageIntent, Object[] messages) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Unicast\UnicastBus.cs:line 583
at NServiceBus.Unicast.UnicastBus.NServiceBus.IBus.Send(Object[] messages) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Unicast\UnicastBus.cs:line 480
at Rapporteringsregisteret.Web.Controllers.RapporteringController.Post(OpprettRapportering opprettRapportering) in c:\dev\git\Rapporteringsregisteret\src\Rapporteringsregisteret.Web\Controllers\RapporteringController.cs:line 37
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
Why isn't this working?
When running in a distributed scenario your endpoint mapping needs to explicitely define the machine name where the queue of the receiver is located. When running on the same box this is not necessary. Therefore your mapping should not contain "myserver" but "myserver#machinename". This error is not related to DTC. For future questions always include Nservicebus version number and transport layer

NHibernate.MappingException - Trouble Shooting Checklist (no persister for)

Here's a starter list:
if hbm is hand generated, is it an embedded resource?
if using FNH, does it pass a PerssistenceSpecification test?
if not using FNH, can you save and then load the persisted class?
use Ayende's "sanity checks"
I'm sure many of you have gotten this one at one point or another. But have you ever gotten it when you knew your mapping was set up correctly?
I started getting this exception after I started using a new repository design, but only in one scenario! PersistenceSpecification tests pass, as do all repository methods (using SQLite).
The scenario that leads to the exception is when legacy projects from a different db are converted to green field system. The legacy system is from a different database and has it's own session factory, which should be irrelevant because the error comes after previously unconverted Projects are retrieved and in memory.
As the routine tries to save these unconverted Projects into the new database, the exception is thrown, full stack trace below.
Any ideas on how to build up the trouble shooting check list and solves this problem?
Cheers,
Berryl
=== the Exception trace =====
failed: NHibernate.MappingException : No persister for: Smack.ConstructionAdmin.Domain.Model.Projects.Project
at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName)
at NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName, Object obj)
at NHibernate.Engine.ForeignKeys.IsTransient(String entityName, Object entity, Nullable`1 assumed, ISessionImplementor session)
at NHibernate.Event.Default.AbstractSaveEventListener.GetEntityState(Object entity, String entityName, EntityEntry entry, ISessionImplementor source)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj)
NHibernate\Repository\FabioNHibRepository.cs(46,0): at Smack.Core.Data.NHibernate.Repository.FabioNHibRepository`1.Add(T item)
LegacyConversion\LegacyBatchUpdater.cs(20,0): at Smack.ConstructionAdmin.Data.LegacyConversion.LegacyBatchUpdater.ConvertOpenLegacyProjects(ILegacyProjectDao legacyProjectDao, IProjectRepository greenProjectRepository)
Data\Brownfield\ProjectBatchUpdate_SQLiteTests.cs(19,0): at Smack.ConstructionAdmin.Tests.Data.Brownfield.ProjectBatchUpdate_SQLiteTests.Test()
The problem here turned out to be that I was inadvertently binding the same session context to both the legacy and greenfield db session factories, first to the greenfield and then the legacy.