在ServiceStack.OrmLite中使用IDbConnection.BeginTransaction时无法使用事务

时间:2014-11-06 02:51:35

标签: transactions servicestack ormlite-servicestack

我想使用ormlite的事务,但是我没有使用ormlite添加的扩展方法OpenTransaction,我想使用IDbConnection.BeginTransaction,因为我没有在我希望管理事务的项目中引用ormlite。

所以我喜欢:

    using (var dbTrans = db.BeginTransaction())
    {
        // do some work

        dbTrans.Commit();
    }

但这会引发以下异常:

System.InvalidOperationException: ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction.  The Transaction property of the command has not been initialized.
Result StackTrace:  
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at StackExchange.Profiling.Data.ProfiledDbCommand.ExecuteNonQuery() in c:\TeamCity\buildAgent\work\1de24adb938b932d\StackExchange.Profiling\Data\ProfiledDbCommand.cs:line 277
   at ServiceStack.OrmLite.OrmLiteCommand.ExecuteNonQuery()
   at ServiceStack.OrmLite.OrmLiteWriteCommandExtensions.ExecuteSql(IDbCommand dbCmd, String sql)
   at ServiceStack.OrmLite.WriteExpressionCommandExtensions.Update[T](IDbCommand dbCmd, T item, Expression`1 expression)
   at ServiceStack.OrmLite.OrmLiteWriteExpressionsApi.<>c__DisplayClassd`1.<Update>b__c(IDbCommand dbCmd)
   at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func`2 filter)
   at ServiceStack.OrmLite.OrmLiteReadExpressionsApi.Exec[T](IDbConnection dbConn, Func`2 filter)
   at ServiceStack.OrmLite.OrmLiteWriteExpressionsApi.Update[T](IDbConnection dbConn, T item, Expression`1 where)
...

当我调试时,我注意到在事务开始后没有设置db对象的Transaction属性。我查看了源代码OrmLiteConnection.cs#L48,我无法看到是否曾将事务分配给OrmLiteConnection.Transaction。

这是需要在OrmLiteConnection.BeginTransaction中解决的问题,还是我使用BeginTransaction错了?

1 个答案:

答案 0 :(得分:1)

在OrmLite中打开事务的API为db.OpenTransaction(),获得assigned in the OrmLiteTransaction contructor并自动分配给在事务范围内创建的每个db命令。

如果您想使用ADO.NET的原生BeginTransaction() API,您需要自己将其分配给ADO.NET IDbCommand,即:

using (var db = OpenDbConnection())
using (var dbTrans = db.BeginTransaction())
using (var dbCmd = db.CreateCommand())
{
    dbCmd.Transaction = dbTrans;

    // do some work
    dbTrans.Commit();
}