【问题标题】:Prepare requires the command to have a transaction准备需要命令有一个事务
【发布时间】:2018-07-24 06:42:57
【问题描述】:

我收到此错误:

Prepare 要求命令在连接时有事务 分配给该命令的处于挂起的本地事务中。这 该命令的事务属性尚未初始化。

在 Prepare() 上:

connection = new SqlConnection(dbconnectionstring);
connection.Open();
transaction = connection.BeginTransaction();
SqlCommand Command1 = GetCommand1(connection);
SqlCommand Command2 = GetCommand2(connection, transaction);


private SqlCommand GetCommand1(SqlConnection connection)
{
    const string sql = @"
        INSERT INTO R_Activity(start_time, activity_num) OUTPUT INSERTED.ID VALUES(SYSDATETIME(), @ACTIVITY_NUM)
        ";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.Add(new SqlParameter("@ACTIVITY_NUM", System.Data.SqlDbType.Int, 0));
    command.Prepare();  // Error here.
    return command;
}


private SqlCommand GetCommand2(SqlConnection connection, SqlTransaction transaction)
{
    const string sql = @"
        INSERT IVS_RUNHISTORY ( r_activity_id, datasource,  rundate)
                               OUTPUT INSERTED.ID
                               VALUES (@r_activity_id, @datasource, @rundate)
        ";
    SqlCommand command = new SqlCommand(sql, connection, transaction);

    command.Parameters.Add(new SqlParameter("@datasource", System.Data.SqlDbType.Char, 4));
    command.Parameters.Add(new SqlParameter("@rundate", System.Data.SqlDbType.DateTime, 0));
    command.Parameters.Add(new SqlParameter("@r_activity_id", System.Data.SqlDbType.Int, 0));
    command.Prepare();
    return command;
}

我怎样才能避免这个错误?

我的目标是允许 Command1 在事务之外运行,以便在插入运行后立即将行完全写入数据库中,而 Command2 将等待完全写入直到 Commit()。

命令的区别在于,Command1 就像是正在发生的事情的日志,而 Command2 是控制台程序的业务逻辑。也就是即使业务逻辑失败,我还是想看数据库中的日志。

这是代码的精简示例。还有其他命令将与事务相关联。

[编辑] 如果我注释掉 Prepare() 错误会移动执行:

ExecuteScalar 要求命令有一个事务,当 分配给命令的连接处于挂起的本地事务中。 该命令的 Transaction 属性尚未初始化。

[编辑] 用例是:我有一个表我想更新并且不受回滚的影响。该表是程序正在执行的操作的日志。即使有 ROLLBACK,我也希望日志完好无损。

【问题讨论】:

  • Command2 will wait to be fully written until a Commit(). 如果事务中只有一个 INSERT,那么进行 显式 事务是没有价值的。
  • SqlServer 不需要命令准备;坦率地说,你可以在这里删除所有的 .Prepare() 并且什么都不会改变
  • SqlServer 不需要准备但它是否受益于准备?
  • 如果连接上有事务,则指定事务就不能运行命令;你必须要么全无,要么全无
  • @MichaelPotter 以我的经验:不,不是真的 - 而且尤其是如果你是在一个你创建和执行一次的命令上这样做

标签: c# sql-server


【解决方案1】:

我通过为基于事务的 SQL 打开第二个连接解决了这个问题。

[评论告诉我我疯了,欣然接受]

connection = new SqlConnection(dbconnectionstring);
connection.Open();
connectiont = new SqlConnection(dbconnectionstring);
connectiont.Open();
transaction = connectiont.BeginTransaction();
SqlCommand Command1 = GetCommand1(connection);
SqlCommand Command2 = GetCommand2(connectiont, transaction);


private SqlCommand GetCommand1(SqlConnection connection)
{
    const string sql = @"
        INSERT INTO R_Activity(start_time, activity_num) OUTPUT INSERTED.ID VALUES(SYSDATETIME(), @ACTIVITY_NUM)
        ";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.Add(new SqlParameter("@ACTIVITY_NUM", System.Data.SqlDbType.Int, 0));
    command.Prepare();  // Error here.
    return command;
}


private SqlCommand GetCommand2(SqlConnection connection, SqlTransaction transaction)
{
    const string sql = @"
        INSERT IVS_RUNHISTORY ( r_activity_id, datasource,  rundate)
                               OUTPUT INSERTED.ID
                               VALUES (@r_activity_id, @datasource, @rundate)
        ";
    SqlCommand command = new SqlCommand(sql, connection, transaction);

    command.Parameters.Add(new SqlParameter("@datasource", System.Data.SqlDbType.Char, 4));
    command.Parameters.Add(new SqlParameter("@rundate", System.Data.SqlDbType.DateTime, 0));
    command.Parameters.Add(new SqlParameter("@r_activity_id", System.Data.SqlDbType.Int, 0));
    command.Prepare();
    return command;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-15
    • 2016-11-17
    • 2012-07-10
    • 2012-02-15
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多