代码:
我正在尝试运行此函数,但它会抛出错误: 此SqlTransaction已完成;它已不再可用。
我已经使用了其他方式但没有工作。我在没有USING
的情况下使用它但仍然出现相同的错误。
为什么?
public Boolean AddWorkProgress(int WorkID, int ContractorID, float PhysicalProgress,
decimal FinancialProgress, int UserID, int OrgID, float FinancialProgressPecentage)
{
SqlCommand SqlCom = new SqlCommand("AddWorkProgress", DataBaseConnection.OpenConnection());
SqlCom.CommandType = CommandType.StoredProcedure;
using (SqlTransaction sqlTrans = SqlCom.Connection.BeginTransaction())
{
SqlCom.Transaction = sqlTrans;
try
{
SqlCom.Parameters.AddWithValue("@Work_ID", WorkID);
SqlCom.Parameters.AddWithValue("@Contractor_ID", ContractorID);
SqlCom.Parameters.AddWithValue("@PhysicalProgress", PhysicalProgress);
SqlCom.Parameters.AddWithValue("@FinancialProgress", FinancialProgress);
SqlCom.Parameters.AddWithValue("@OrgID", OrgID);
SqlCom.Parameters.AddWithValue("@fk_WebUsers_UserID", UserID);
SqlCom.Parameters.AddWithValue("@FinancialProgressPercentage", FinancialProgressPecentage);
SqlParameter SqlParamReturnStatus = new SqlParameter("@ReturnStatus", SqlDbType.Bit);
SqlCom.Parameters.Add(SqlParamReturnStatus);
SqlParamReturnStatus.Direction = ParameterDirection.Output;
SqlParameter SqlParamReturnStatusMessage = new SqlParameter("@ReturnStatusMessage", SqlDbType.VarChar, -1);
SqlCom.Parameters.Add(SqlParamReturnStatusMessage);
SqlParamReturnStatusMessage.Direction = ParameterDirection.Output;
SqlCom.ExecuteNonQuery();
DataBaseConnection.CloseConnection();
string ReturnStatusMessage = Convert.ToString(SqlParamReturnStatusMessage);
Boolean ReturnStatus = Convert.ToBoolean(SqlParamReturnStatus.Value);
// ProgressID = Convert.ToInt64(SqlParamReturnProgressID.Value);
sqlTrans.Commit();
return ReturnStatus;
}
catch (Exception ex)
{
sqlTrans.Rollback();
sqlTrans.Dispose();
throw ex;
}
}
}
答案 0 :(得分:3)
您在提交交易之前关闭了连接:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="javascript.js"></script>
从MSDN开始:
如果是,则Commit和Rollback都会生成InvalidOperationException 连接终止或事务已经滚动 回到服务器上。
这正是您的情况 - 在提交/回滚事务之前连接已关闭。
答案 1 :(得分:0)
如果连接已关闭,则无法回滚或提交事务。当连接关闭时,SQL Server无论如何都会回滚所有打开的事务。
catch
块也是多余的。除非调用Commit()
,否则事务在处理完毕后会回滚。
最后,连接以不安全的方式处理。如果在CloseConnection()
之前发生任何错误,则连接将保持打开状态。
以正确的方式使用连接和事务简化了代码:
var SqlCom = new SqlCommand("AddWorkProgress");
SqlCom.CommandType = CommandType.StoredProcedure;
//... prepare the command. No need to use a connection
using(var connection=DataBaseConnection.OpenConnection())
using(var transaction= connection.BeginTransaction())
{
SqlCom.Connection=connection;
SqlCom.Transaction=transaction;
SqlCom.ExecuteNonQuery();
transaction.Commit();
//Process the results
}
那就是它。 using
块完成后,连接将关闭。如果Commit()
未被调用,则将回滚该事务,这只有在出现错误时才会发生。
一旦将存储过程的构造与其执行分开,就可以进一步简化代码。例如,当类或应用程序初始化时,您只能创建一次命令。每次要执行它时,只需设置连接和参数值,例如:
public Boolean AddWorkProgress(int WorkID, int ContractorID, float PhysicalProgress, decimal FinancialProgress, int UserID, int OrgID, float FinancialProgressPecentage)
{
using(var connection=DataBaseConnection.OpenConnection())
using(var transaction= connection.BeginTransaction())
{
_addProgressCmd.Parameters["@Work_ID"].Value=WorkID;
....
_addProgressCmd.Connection=connection;
_addProgressCmd.Transaction=transaction;
_addProgressCmd.ExecuteNonQuery();
transaction.Commit();
var status=(bool)_addProgressCmd.Parameters["@ReturnStatus"].Value;
var statusMsg=(string)_addProgressCmd.Parameters["@ReturnStatusMessage"].Value;
//Process the results
...
}
}
答案 2 :(得分:0)
如果以上答案不能解决您的问题,则您可能需要检查数据库和表的设置是否正确。
在某些情况下,缺少主键可能会导致与in this answer中所述的错误相同。