C# 存储过程c上的多个ExecuteOnQuery#
我想使用相同的连接和相同的事务,使用不同的参数执行相同的存储过程。C# 存储过程c上的多个ExecuteOnQuery#,c#,sql-server,stored-procedures,transactions,C#,Sql Server,Stored Procedures,Transactions,我想使用相同的连接和相同的事务,使用不同的参数执行相同的存储过程。 理想情况下,如果对ExecuteNonQuery()的任何调用失败,则应回滚整个事务 存储过程:Sample1 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[Sample1] @start_date datetime, @end_date datetime, @empID int WITH EXEC AS CALLER AS BEG
理想情况下,如果对
ExecuteNonQuery()
的任何调用失败,则应回滚整个事务
存储过程:Sample1
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Sample1]
@start_date datetime, @end_date datetime, @empID int
WITH EXEC AS CALLER
AS
BEGIN
BEGIN TRANSACTION;
BEGIN TRY
-- set of insert, delete and update
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
Declare @ErrorMessage Varchar(100), @ErrorNumber Int
SELECT ERROR_NUMBER() AS ErrorNumber ,ERROR_MESSAGE() AS ErrorMessage;
ROLLBACK TRANSACTION;
RAISERROR(@ErrorMessage,@ErrorNumber,1);
END CATCH;
END
我的C代码
public int ExecuteSP()
{
var connectionString=ConfigurationManager.AppSettings[“\uuu WaveDatabaseConnection”];
int rowsAffected=0;
使用(var连接=新的SqlConnection(connectionString))
{
connection.Open();
var transaction=connection.BeginTransaction();
尝试
{
var command=newsqlcommand(_StoreProcedureName,connection){CommandType=CommandType.StoredProcedure};
command.CommandType=CommandType.storedProcess;
command.Connection=连接;
command.Transaction=事务;
Add(“@empid”,SqlDbType.Int).Value=site.ID;
command.Parameters.Add(“@start_date”,SqlDbType.DateTime).Value=new DateTime();
Add(“@end_date”,SqlDbType.DateTime).Value=new DateTime();
对于(i=0;i<10;i++)
{
command.Parameters[“@start_date”].Value=new DateTime().Add(i);
command.Parameters[“@end_date”].Value=new DateTime().Add(i+1);
rowsAffected+=command.ExecuteNonQuery();
}
Commit();
}
捕获(SqlException SqlException)
{
var sqlExceptionMessage=string.Format(“错误号:{0},错误类型:{1}错误消息:{2}”,
sqlException.ErrorCode、sqlException.GetType()、sqlException.Message);
尝试
{
transaction.Rollback();
}
捕获(异常)
{
sqlExceptionMessage=
Format(“ExecuteError:{0},回滚异常错误类型:{1}错误消息:{2}”,
sqlExceptionMessage,exception.GetType(),exception.Message);
}
抛出新异常(sqlExceptionMessage);
}
}
返回受影响的行;
}
}
现在我得到了这个例外
EXECUTE后的事务计数表示BEGIN和COMMIT语句的数量不匹配。上一次计数=1,当前计数=0
当我从存储过程中删除所有的BEGIN TRANS/COMMIT/ROLLBACK
语句时,第一个命令.ExecuteNonQuery()
将毫无问题地执行。当第二次调用它时,它会抛出以下异常: 在批处理结束时检测到不可提交的事务。事务被回滚 我甚至试着在SP中使用
设置XACT\u ABORT ON
,但没有效果
请帮助我如何提交全部或回滚C#代码,以及如何解决上述问题
谢谢
Vijay可能重复@GSerg,但当我删除SP上的所有事务时,会出现不同的错误。理想情况下,我只想在c#级别控制事务。你能帮我看一下如何实现它的代码吗?看看这篇关于SQL Server神话的文章——神话嵌套事务是真实的——让存储过程在没有事务的情况下执行多个语句是错误的。让C#代码在不启动事务的情况下调用多个SP也是错误的。正如Steve Ford所注意到的,因为实际上没有真正的嵌套事务,所以不能通过将begin trans与相同数量的回滚匹配来平衡代码。相反,您应该使用一种模式,例如,只有在当前级别上启动事务时才回滚事务。例如,您应该从SP检测到存在环境事务,如果存在,请不要回滚。请查看本博客,其中解释了16级SQL Server错误何时会导致这些症状。您需要检查XACT_状态以确定事务是否可提交。
public int ExecuteSP()
{
var connectionString = ConfigurationManager.AppSettings["__WaveDatabaseConnection"];
int rowsAffected = 0;
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
var transaction = connection.BeginTransaction();
try
{
var command = new SqlCommand(_StoreProcedureName, connection) { CommandType = CommandType.StoredProcedure };
command.CommandType = CommandType.StoredProcedure;
command.Connection = connection;
command.Transaction = transaction;
command.Parameters.Add("@empid", SqlDbType.Int).Value = site.ID;
command.Parameters.Add("@start_date", SqlDbType.DateTime).Value = new DateTime();
command.Parameters.Add("@end_date", SqlDbType.DateTime).Value = new DateTime();
for (i = 0; i < 10; i++))
{
command.Parameters["@start_date"].Value = new DateTime().Add(i);
command.Parameters["@end_date"].Value = new DateTime().Add(i+1);
rowsAffected += command.ExecuteNonQuery();
}
transaction.Commit();
}
catch (SqlException sqlException)
{
var sqlExceptionMessage = string.Format("Error number : {0}, Error Type : {1} Error message : {2}",
sqlException.ErrorCode, sqlException.GetType(), sqlException.Message);
try
{
transaction.Rollback();
}
catch (Exception exception)
{
sqlExceptionMessage =
string.Format("ExecuteError : {0}, RollBack exception Error Type : {1} Error message : {2}",
sqlExceptionMessage, exception.GetType(), exception.Message);
}
throw new Exception(sqlExceptionMessage);
}
}
return rowsAffected;
}
}