ServiceStack Ormlite交易坏了吗?

时间:2014-11-25 19:38:40

标签: sql-server transactions ormlite-servicestack

我正在使用ServiceStack.Ormlite for SQL Server,刚刚从3.9.71更新到4.0.33.0,现在直接命令的事务失败了。我可以让ORMlite事务工作或直接命令,但不能同时使用。

复杂的是我正在做一些非常复杂的数据库命令,并且由于Sql.In()对于大量的GUID列表非常慢,我有一个使用db.CreateCommand()的解决方法,然后将GUID列表作为一个传递给自定义表类型。

因此,我需要一个事务来跨越ORMLite命令和直接db命令。以下代码用于工作,现在它失败了。

例如以下代码用于工作。我现在得到错误,说CreateCommand()应该使用该事务。当我直接尝试然后我得到指示的cast exception

            using (var db = DB.Connection.OpenDbConnection())
            {
                using (var transaction = db.OpenTransaction())
                {
                    // Some ORMLite code
                    db.Delete<SomeType>();

                    using (var command = db.CreateCommand())
                    {
                        // Direct DB command
                        command.CommandText = "Delete from SomeTable where ...";
                        command.Parameters.Add(GUIDList)

                        command.ExecuteNonQuery();
                    }
                }
            }

澄清: 在代码中,OpenTransaction()将用于OrmLite代码,但在CreateCommand代码上失败。 OrmLite代码的BeginTransaction()将失败。

实际错误位于command.ExecuteNonQuery():当分配给命令的连接处于挂起的本地事务中时,ExecuteNonQuery要求命令具有事务。该命令的Transaction属性尚未初始化。

2 个答案:

答案 0 :(得分:1)

要使用Transactions in OrmLite,您应该使用OpenTransaction() API,例如:

using (var trans = db.OpenTransaction()) 
{
    //...
}

我已经添加了一些新的API,以便能够将OrmLite事务与原始ADO.NET IDbCommand in this commit一起使用。

使用托管的OrmLite数据库命令

使用带有OpenCommand()的托管OrmLite命令,该命令将自动使用当前事务预填充DB命令,例如:

using (var trans = db.OpenTransaction()) 
using (var command = db.OpenCommand())
{
    command.CommandText = "Delete from SomeTable where ...";
}

手动分配基础数据库事务

使用底层ADO.NET IDbCommand时,您还需要自己手动将Transaction分配给命令,即:

using (var trans = db.OpenTransaction()) 
using (var command = db.CreateCommand())
{
    command.Transaction = trans.ToDbTransaction();
    command.CommandText = "Delete from SomeTable where ...";
}

ToDbTransaction()扩展方法允许您访问使用基础ADO.NET IDbTransaction时所需的基础ADO.NET IDbCommand

这两个新API都可以从 v4.0.34 + 获得,现在是available on MyGet

答案 1 :(得分:0)

这是我的建议,有效。它基于以前的答案

IDbConnection conn = DB.Connection;
IDbCommand cmd = conn.CreateCommand();
using (IDbTransaction transaction = conn.OpenTransaction())
{
    //ADO.NET code
    cmd.Transaction = transaction.ToDbTransaction();
    cmd.CommandText = "...Some sql text";
    cmd.executeNonQuery();
    // Some ORMLite code
    conn.Delete<SomeType>();
}