How to get the Update SQL statement out of NHibernate exception?

I am working with some legacy code which breaks when saving an aggregate to the database. The error from SQL server is the famous 'SqlDateTime overflow. Must be between 1/1/1753...etc'

My question is: is it possible to ask the NHibernate Framework what SQL was executed which bubbled up this exception? This way I will have an easy way to find out what POCO I have to find the problem for.

Is it possible to maybe attach a listener to NHibernate IDbCommand or something?

Example stacktrace of such an exception below:

SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM. StackTrace:    at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery()
   at NHibernate.AdoNet.SqlClientBatchingBatcher.DoExecuteBatch(IDbCommand ps)
   at NHibernate.AdoNet.AbstractBatcher.ExecuteBatchWithTiming(IDbCommand ps)
   at NHibernate.AdoNet.AbstractBatcher.ExecuteBatch()
   at NHibernate.AdoNet.AbstractBatcher.PrepareCommand(CommandType type, SqlString sql, SqlType[] parameterTypes)
   at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
   at NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
   at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)
   at NHibernate.Action.EntityUpdateAction.Execute()
   at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
   at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
   at NHibernate.Engine.ActionQueue.ExecuteActions()
   at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
   at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
   at NHibernate.Impl.SessionImpl.Flush()
   at NHibernate.Transaction.AdoTransaction.Commit()
   at Haddock.Business.Services.CommonRepositoryBase`3.SaveOrUpdate(TRootAggregate rootAggregate) in d:Builds4HaddockHaddock.Releases.P44-2014.SLSourcesBusinessHaddock.Business.ServicesCommonRepositoryBase.cs:line 140
...

I am thinking about adding some extra inspecting code to that CommonRepositoryBase class, which is used all over the project.

Here's the code, which is quite understandable actually:

ISession session = GetSession();
        using (ITransaction transaction = session.BeginTransaction())
        {
            try
            {
                session.SaveOrUpdate(rootAggregate);
                transaction.Commit(); // does a flush internally
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
        }

So, what I am aiming for is having some code in that Catch Block, to inspect the session and transaction that is in use and extend that Exception with the SQL statement(s) NHibernate wanted to execute.


You can use SQL Server Profiler in SQL Server Management studio to keep track of the queries that are being ran on your database.

Just start the profiler before replicating your bug, and you can see the executed queries from there.

Aside from query dumps, you can also see more details about the executed query like execution time etc.

链接地址: http://www.djcxy.com/p/26972.html

上一篇: NHibernate Sqldatetime必须介于1/1/1753和12/31/9999之间

下一篇: 如何获取NHibernate异常的更新SQL语句?