I recently implemented an API that is heavily used across thousands of concurrent requests.
As this is my first heavily used API, this is the first time I have received this exception: System.InvalidOperationException: Invalid operation. The connection is closed.
Any idea what is causing that? There are a ton of DB requests being made which calls the OrmLiteConnectionFactoryOpenDbConnection() method and I was wondering if this is threadsafe and that each thread/call will get a proper connection?
I have something that looks like this:
public IDbConnection GetOpenConnection(string dbName)
{
try
{
if (Factories.TryGetValue(dbName, out OrmLiteConnectionFactory factory))
{
return factory.OpenDbConnection();
}
return CreateFactory(dbName).OpenDbConnection();
}
catch (Exception ex)
{
Logger.Error(ex, data: dbName);
throw;
}
Which is then used by calls to methods that look like this:
using (var db = GetOpenConnection(dbName))
using (var trans = OpenTransaction(db, IsolationLevel.ReadUncommitted))
{
return ExecuteMany<T, U>(db, expression);
}
The OpenDbConnection() API is ThreadSafe, but like most resources in C#, the DB Connection instance that’s returned isn’t. So they shouldn’t be shared across different threads and each need to call OpenDbConnection() in their own Thread.
The OrmLite API to open a transaction is db.OpenTransaction(...) I’m not sure what API you’re using.
System.InvalidOperationException: Invalid operation. The connection is closed.
at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
at System.Data.SqlClient.TdsParserStateObject.TryReadByteArray(Byte[] buff, Int32 offset, Int32 len, Int32& totalRead)
at System.Data.SqlClient.TdsParser.TrySkipPlpValue(UInt64 cb, TdsParserStateObject stateObj, UInt64& totalBytesSkipped)
at System.Data.SqlClient.SqlDataReader.TryResetBlobState()
at System.Data.SqlClient.SqlDataReader.TryCleanPartialRead()
at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
at System.Data.SqlClient.SqlDataReader.Read()
at ServiceStack.OrmLite.OrmLiteUtils.ConvertToList[T](IDataReader reader, IOrmLiteDialectProvider dialectProvider, HashSet`1 onlyFields) in C:\BuildAgent\work\27e4cc16641be8c0\src\ServiceStack.OrmLite\OrmLiteUtils.cs:line 267
at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.ConvertToList[T](IDbCommand dbCmd, String sql) in C:\BuildAgent\work\27e4cc16641be8c0\src\ServiceStack.OrmLite\OrmLiteResultsFilterExtensions.cs:line 100
at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.SqlList[T](IDbCommand dbCmd, String sql, Dictionary`2 dict) in C:\BuildAgent\work\27e4cc16641be8c0\src\ServiceStack.OrmLite\OrmLiteReadCommandExtensions.cs:line 527
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func`2 filter) in C:\BuildAgent\work\27e4cc16641be8c0\src\ServiceStack.OrmLite\OrmLiteExecFilter.cs:line 64