EnterpriseLibraryContainer.Current.GetInstance<Database> is threadsafe?

Topics: Data Access Application Block
Aug 29, 2014 at 2:27 PM
Edited Aug 29, 2014 at 2:37 PM

I have this piece of code. I use it to make asyncronous calls to db using asynccodeactivity. workflows are hosted on IIS

dbConnection = database.CreateConnection();
Is this thread safe? because sporadically, i keep getting below error. Can you please helo me with this? here is the Qn in stackoverflow. this has peice of co


An unhandled exception occurred and the process was terminated.

Exception: System.InvalidOperationException

Message: The operation completed.

StackTrace: at System.Activities.AsyncOperationContext.ShouldComplete() at System.Activities.AsyncOperationContext.CompleteAsyncCodeActivity(CompleteData completeData) at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) at Microsoft.Practices.EnterpriseLibrary.Common.Utility.WrappedAsyncOperation.<>c__DisplayClass2`1.b__0(IAsyncResult ar) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Data.Common.DbAsyncResult.ExecuteCallback(Object asyncResult) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Aug 29, 2014 at 3:59 PM
The code appears to be thread-safe. GetInstance() under the covers performs a Unity Resolve which is thread-safe and CreateConnection just creates a new database connection.

The reason you are crashing the app pool is that you are not handling exceptions for the callback. This results in an unhandled exception which brings down the process. I would recommend adding a catch in the EndExecute method as well as some logging to let you know what exception(s) you are seeing.

I'm wondering if the InvalidOperationException is masking another exception. If you look at the stack trace the UnhandledExceptionFrame method is called right after the EntLib WrappedAsyncOperation method which makes it look like the EndExecute is where the problem is. However, the final exception about the operation being completed is thrown from ShouldComplete.

Randy Levy
Enterprise Library support engineer
Support How-to
Aug 29, 2014 at 4:11 PM
Edited Aug 29, 2014 at 5:11 PM
Thank you Randy,

I sort of had traced the calls by opening entlib code and you're right. InvalidOperationException is being thrown in end execute.
I wanted to understand one thing. does call back call endexecute? or end execute call call back? the reason i'm asking is, Shouldcomplete sporadically has "hascompleted = true" even before end execute has finished.

I'd genuinely appreciate your quick response as this problem is eating me up.

I've added throw in end block and have kicked off workflows. as soon as i get errors, I'll post here.

many thanks again
Aug 30, 2014 at 5:00 AM
Edited Aug 30, 2014 at 5:57 AM
You are amazing Randy,

it does look like it was hiding the exception. here is it. logged in eventlog

An unhandled exception occurred and the process was terminated.

Application ID:

Process ID: 14108

Exception: System.AggregateException

Message: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.

StackTrace: at System.Threading.Tasks.TaskExceptionHolder.Finalize()

InnerException: Microsoft.AnalysisServices.AdomdClient.AdomdErrorResponseException

Message: Server: The operation has been cancelled because there is not enough memory available for the application. If using a 32-bit version of the product, consider upgrading to the 64-bit version or increasing the amount of memory available on the machine.
Internal error: The operation terminated unsuccessfully.

StackTrace: at Microsoft.AnalysisServices.AdomdClient.AdomdDataReader.BeginNewRow()
at Microsoft.AnalysisServices.AdomdClient.AdomdDataReader.InternalRead()
at Microsoft.AnalysisServices.AdomdClient.AdomdDataReader.Read()
at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternal()
at System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServer(Int32 columnCount)
at System.Data.SqlClient.SqlBulkCopy.WriteToServer(IDataReader reader)
at WorkflowActivity.AsyncSqlBulkCopy.WriteToServer(IDataReader reader, DataTable dataTable, String databaseName, SqlBulkCopyOptions copyOptions, String destinationTable, Int32 batchSize, Int32 bulkCopyTimeout, SqlBulkCopyColumnMapping[] columnMappings, CancellationToken cancellationToken)
at WorkflowActivity.AsyncSqlBulkCopy.<>c__DisplayClass1.<

after using asyncreader in the code (the one in stachoverflow,) sqlbulkcopyis called. I always thought error was in asyncexecute function. but in sql bulkcopy, we do use reader as well. Comments Randy?
Aug 30, 2014 at 6:07 AM
I have to handle the tasks results isn't it? task.continuewth or wait. which seems like it's missing.