Discovered that OleDBConnection doesn't seem to be ThreadSafe. It appears that it attempts to open multiple connections instead.
//doesn't work
using (OleDbConnection oConn = TheDataAccessLayer.GetConnection())
using (OleDbTransaction oTran = oConn.BeginTransaction())
Parallel.ForEach(ORMObjects, (ORMObject, State) =>
{
if (!State.ShouldExitCurrentIteration && !State.IsExceptional)
{
var Error = ORMObject.SomethingThatExecutesANonQuery(oConn,oTran)
if (Error.Number != 0)
State.Stop();
}
});
If I lock the connection for an ExecuteNonQuery the errors go away, but the performance tanks.
//works
using (OleDbConnection oConn = TheDataAccessLayer.GetConnection())
using (OleDbTransaction oTran = oConn.BeginTransaction())
Parallel.ForEach(ORMObjects, (ORMObject, State) =>
{
if (!State.ShouldExitCurrentIteration && !State.IsExceptional)
{
lock(oConn)
{
var Error = ORMObject.SomethingThatExecutesANonQuery(oConn,oTran)
if (Error.Number != 0)
State.Stop();
}
}
});
Assume that
I can't change the nature of the ORM: the SQL cannot be bulked
Business rules require that the interaction be performed within a single transaction
So:
Is there a more better/more efficient way to parallelize OleDb interactions?
If not, is there an alternative to the OleDb client that can take full advantage of parallelism? (Maybe the native MSSQL client?)