为啥我的存储过程在包含在事务块中时会抛出错误?
Posted
技术标签:
【中文标题】为啥我的存储过程在包含在事务块中时会抛出错误?【英文标题】:Why does my store procedure throw error when enclosed within transaction block else not?为什么我的存储过程在包含在事务块中时会抛出错误? 【发布时间】:2018-03-02 15:02:32 【问题描述】:为什么我的代码会抛出错误:
EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 1,当前计数 = 0
当我删除事务块时,它可以正常工作,但不适用于这些块。为什么 ?
我在过去 2 天里对其进行了测试,但它仍然抛出了太多不应该但它仍然存在的错误。请帮帮我。
代码:
ALTER PROC [dbo].[ContractRegistration]
@ContractorType_ID tinyint,
@RegistrationDate date,
@ExpiryDate date,
@Email varchar(200),
@FName varchar(50),
@Mobile varchar(50),
@Name varchar(50),
@CNIC varchar(20),
@ContactNo varchar(20),
@Password varchar(200),
@IsActive bit = 0,
@User_ID smallint,
@Organization_ID int,
@District_ID smallint,
@ContractorID int,
@EnlistmentNo varchar(50),
@Address varchar(300),
@OfficeID int,
@PECCategoryID int,
@PECCategoryNo varchar(50),
@CNWEnlistmentNo varchar(50),
@NTN varchar(50),
@SPCode [dbo].[ContractorSpecializationCode] READONLY,
@Doc [dbo].[ContractorDocuments] READONLY,
@Farm varchar(200),
@TaxExempted bit,
@BankCode varchar(20),
@BankName varchar(20),
@BankDraft varchar(30),
@Amount money,
@RenwalID int = 0,
@ExpectedDate date=null,
@PecReciptNo varchar(50),
@IsRenewal BIT,
@RoleID int= 2
AS
BEGIN
Begin Try
Begin Transaction tran1
/*
THIS STORED PROCEDURE IS CALLED FOR CONTRACTOR SAVING, UPDATION AND RENWAL...
-- IN CASE OF RENEWAL OLD REGISTRATION, OLD SPECIALZATION CODE AND OLD DOCUMENTS HISTORY IS MAINTAINED IN HISTORY TABLES.
-- IN CASE OF SAVING NEW ENTRY IS DONE, IN CONTRACTOR, SPECIALZATION CODES AND DOCUMENTS.
-- IN CASE OF UPDATION REGISTION SPECIALZTION AND DOUCMENTS ARE UPDATED..
*/
/* Constractor Status
1: New
2 : Approved
3: Deffered
4: Rejected
5 : Approved with c&W Exemption
*/
----------------------------- PEC Cat and Category validation
if(@PECCategoryID = 1 AND (@ContractorType_ID NOT BETWEEN 1 AND 10))
Begin
RAISERROR('Category must be between PK-1 and PK-10 for C-A ',16,1);
RETURN;
End
if(@PECCategoryID = 2 AND (@ContractorType_ID NOT BETWEEN 2 AND 10))
Begin
RAISERROR('Category must be between PK-2 and PK-10 for C-B ',16,1);
RETURN;
End
if(@PECCategoryID = 3 AND (@ContractorType_ID NOT BETWEEN 3 AND 10))
Begin
RAISERROR('Category must be between PK-3 and PK-10 for C-1 ',16,1);
RETURN;
End
if(@PECCategoryID = 4 AND (@ContractorType_ID NOT BETWEEN 4 AND 10))
Begin
RAISERROR('Category must be between PK-4 and PK-10 for C-2 ',16,1);
RETURN;
End
if(@PECCategoryID = 5 AND (@ContractorType_ID NOT BETWEEN 5 AND 10))
Begin
RAISERROR('Category must be between PK-5 and PK-10 for C-3',16,1);
RETURN;
End
if(@PECCategoryID = 6 AND (@ContractorType_ID NOT BETWEEN 6 AND 10))
Begin
RAISERROR('Category must be between PK-6 and PK-10 for C-4 ',16,1);
RETURN;
End
if(@PECCategoryID = 7 AND (@ContractorType_ID NOT BETWEEN 7 AND 10))
Begin
RAISERROR('Category must be between PK-7 and PK-10 for C-5 ',16,1);
RETURN;
End
if(@PECCategoryID = 8 AND (@ContractorType_ID NOT BETWEEN 8 AND 10))
Begin
RAISERROR('Category must be between PK-8 and PK-10 for C-6 ',16,1);
RETURN;
End
----------------------------- PEC Cat and Category validation
DECLARE @CurrentStatus int,@HistoryID int;
-------- If New Entry...
IF @IsRenewal=0
BEGIN
IF EXISTS(SELECT ContractorID FROM dbo.Contractors WHERE ContractorID = @ContractorID)
BEGIN
----- SMS section (if contractor mobile no has been modified then sms must be sent to the contractor and MIS manager)
Declare @OldMobileNo varchar(20)
Set @OldMobileNo= ISNULL((Select c.ContactNo from Contractors c where c.ContractorID= @ContractorID),0)
IF(@OldMobileNo not like @Mobile)
Begin
Declare @ContractorName varchar(200)
Set @ContractorName= (Select c.Name from dbo.Contractors c where c.ContractorID= @ContractorID)
Declare @OrganizationID int
Set @OrganizationID= (Select c.Organization_ID from dbo.Contractors c where c.ContractorID= @ContractorID)
DECLARE @smsbody NVARCHAR(MAX);
Declare @smsbody_MIS NVARCHAR(MAX);
SET @smsbody = 'Your mobile no. has been changed to '+ @Mobile +'. '+'If you have any query regarding this change then contact system admin.'
SET @smsbody_MIS= @ContractorName + ' '+ 'mobile no. has been changed to '+ @Mobile
Declare @EntryDate date
Set @EntryDate= (Select GETDATE())
EXEC MC_SMS.App.SaveQueueSMSSingle @smsbody,@OldMobileNo,1,1,1,0, @EntryDate, @OrganizationID
EXEC MC_SMS.App.SaveQueueSMSSingle @smsbody_MIS,'03369883499',1,1,1,0, @EntryDate, @OrganizationID -- send a copy to MIS manager
End
----- SMS section
DELETE FROM [dbo].[SpecializationCodeContractor]
WHERE Contractor_ID = @ContractorID;
DELETE FROM [dbo].[DocumentContractor]
WHERE Contractor_ID = @ContractorID;
--delete from dbo.ContractorRenewal where ID=@RenwalID
UPDATE [dbo].[Contractors]
SET [ContractorType_ID] = @ContractorType_ID, [RegistrationDate] = @RegistrationDate, [RegExpiryDate] = @ExpiryDate, [Name] = @Name, [FatherName] = @FName,
[CNIC] = @CNIC, [ContactNo] = @Mobile, [PhoneNo] = @ContactNo, [EnlistmentNo] = @EnlistmentNo,
[Password] = @Password, [Organization_ID] = @Organization_ID, [DistrictID] = @District_ID, [User_ID] = @User_ID, [Office_ID] = @OfficeID,
[Address] = @Address, [Email] = @Email, [PecCategoryID] = @PECCategoryID, [PECCategoryNo] = @PECCategoryNo,
[CNWEnlistmentNo] = @CNWEnlistmentNo, [NTN] = @NTN, [HasTaxExempted] = @TaxExempted, [Farm] = @Farm,UpdatedBy=@User_ID, UpdatedDate=GETDATE()
WHERE ContractorID = @ContractorID;
----------------------------------------- Maintain History
INSERT INTO ContractorsHistory (ContractorID, ContractorType_ID, RegistrationDate, RegExpiryDate, Name, FatherName, CNIC, ContactNo, PhoneNo, EnlistmentNo, Password,
Organization_ID, DistrictID, User_ID, IsActive, EntryDateTime, LastLoginDate, Office_ID, Address, Email, PECCategoryID, PECCategoryNo, CNWEnlistmentNo, NTN, Status, HasTaxExempted, Farm, ApprovedBy, ApprovedDate, PECReceiptNo, ExpectedDate,UpdatedBy,UpdateDate)
SELECT ContractorID, ContractorType_ID, RegistrationDate, RegExpiryDate, Name, FatherName, CNIC, ContactNo, PhoneNo, EnlistmentNoNew, Password,
Organization_ID, DistrictID, User_ID, IsActive, EntryDateTime, LastLoginDate, Office_ID, Address, Email,PECCategoryID, PECCategoryNo, CNWEnlistmentNo, NTN, Status, HasTaxExempted, Farm, ApprovedBy, ApprovedDate, PECReceiptNo, ExpectedDate,UpdatedBy,UpdatedDate
FROM Contractors WHERE ContractorID=@ContractorID;
SELECT @CurrentStatus = Status
FROM Contractors
WHERE ContractorID = @ContractorID;
IF @CurrentStatus = 5 ---5 : Approved with c&W Exemption
BEGIN
INSERT INTO dbo.SpecializationCodeContractor
SELECT SP_ID, @ContractorID
FROM @SPCode s
JOIN SpecializationCodes SP ON SP.SpecializationID = S.SP_ID
WHERE SP.SpecCategory_ID = 4; -----Electrical Engineering
END;
ELSE
BEGIN
INSERT INTO dbo.SpecializationCodeContractor
SELECT SP_ID, @ContractorID
FROM @SPCode;
END;
INSERT INTO [dbo].[DocumentContractor]
SELECT Doc_ID, @ContractorID
FROM @Doc;
-- insert into [dbo].[ContractorRenewal]
-- select @ContractorID,@BankCode,@BankName,@BankDraft,@ExpiryDate,@Amount,GETDATE()
UPDATE [dbo].[ContractorRenewal]
SET [BankCode] = @BankCode, [BankName] = @BankName, [BankDraftNo] = @BankDraft, [ValidUpto] = @ExpiryDate, [Amount] = @Amount, [RenwalDate] = @RegistrationDate
WHERE ID = @RenwalID;
END;
ELSE
BEGIN --- save new contractor
-------------------auto enlistment no generation------------------
declare @MaxContractorID int
Set @MaxContractorID= (SELECT ISNULL(max(c.contractorID),0) FROM Contractors c where Office_ID= @OfficeID)
declare @CurrentYear varchar(4)
Set @CurrentYear = (Select YEAR(getdate()))
declare @EnlistmentNoNew varchar(20) --- format= OfficeIDCurrentYearMaxContractorID
set @EnlistmentNoNew= (Select CAST(@OfficeID as varchar) + @CurrentYear + CAST(@MaxContractorID as varchar))
-------------------auto enlistment no generation------------------
INSERT INTO [dbo].[Contractors]([ContractorType_ID], [RegistrationDate], [RegExpiryDate], [Name], [FatherName], [CNIC], [ContactNo], [PhoneNo], [EnlistmentNo],
[Password], [Organization_ID], [DistrictID], [User_ID], [IsActive], [EntryDateTime], [LastLoginDate], [Office_ID], [address], [Email], [PECCategoryID],
[PECCategoryNo], [CNWEnlistmentNo], [ntn], [HasTaxExempted], [Status], [Farm], PECReceiptNo, ExpectedDate, EnlistmentNoNew)
VALUES(@ContractorType_ID, @RegistrationDate, @ExpiryDate, @Name, @FName, @CNIC, @Mobile, @ContactNo, @EnlistmentNo, @Password, @Organization_ID, @District_ID,
@User_ID, 0, GETDATE(), GETDATE(), @OfficeID, @Address, @Email, @PECCategoryID, @PECCategoryNo, @CNWEnlistmentNo, @NTN, @TaxExempted, 1, @Farm,
@PecReciptNo, @ExpectedDate, @EnlistmentNoNew);
DECLARE @Con_ID int;
SELECT @Con_ID = IDENT_CURRENT('[dbo].[Contractors]');
----------------------------------------- Maintain History
INSERT INTO ContractorsHistory (ContractorID, ContractorType_ID, RegistrationDate, RegExpiryDate, Name, FatherName, CNIC, ContactNo, PhoneNo, EnlistmentNo, Password,
Organization_ID, DistrictID, User_ID, IsActive, EntryDateTime, LastLoginDate, Office_ID, Address, Email, PECCategoryID, PECCategoryNo, CNWEnlistmentNo, NTN, Status, HasTaxExempted, Farm, ApprovedBy, ApprovedDate, PECReceiptNo, ExpectedDate)
SELECT ContractorID, ContractorType_ID, RegistrationDate, RegExpiryDate, Name, FatherName, CNIC, ContactNo, PhoneNo, EnlistmentNoNew, Password,
Organization_ID, DistrictID, User_ID, IsActive, EntryDateTime, LastLoginDate, Office_ID, Address, Email, PECCategoryID, PECCategoryNo, CNWEnlistmentNo, NTN, Status, HasTaxExempted, Farm, ApprovedBy, ApprovedDate, PECReceiptNo, ExpectedDate
FROM Contractors WHERE ContractorID=@Con_ID;
Set @HistoryID= IDENT_CURRENT('ContractorsHistory')
INSERT INTO dbo.SpecializationCodeContractor
SELECT SP_ID, @Con_ID
FROM @SPCode;
INSERT INTO [dbo].[DocumentContractor]
SELECT Doc_ID, @Con_ID
FROM @Doc;
IF @Amount > 0
BEGIN
INSERT INTO [dbo].[ContractorRenewal](Contractor_ID,BankCode,BankName,BankDraftNo,ValidUpto,Amount,RenwalDate,ContractorHistory_ID)
SELECT @Con_ID, @BankCode, @BankName, @BankDraft, @ExpiryDate, @Amount, @RegistrationDate,@HistoryID;
END;
END;
END
ELSE
----- Renewal Section...
BEGIN
--------------- Maintain Previous Year Documents and Specializtion COde in History Tables..
SELECT TOP 1 @HistoryID=HistoryID FROM ContractorsHistory WHERE ContractorID=@ContractorID ORDER BY HistoryID DESC;
----------------- Specialization Code history...
INSERT INTO SpecializationCodeContractorHistory (SP_ID,Contractor_ID,ContractorHistory_ID)
SELECT SP_ID,Contractor_ID,@HistoryID from SpecializationCodeContractor WHERE Contractor_ID=@ContractorID;
---------------------- Documents History.....
INSERT INTO DocumentContractorHistory (Doc_ID,Contractor_ID,ContractorHistory_ID)
SELECT Doc_ID,Contractor_ID,@HistoryID FROM DocumentContractor WHERE Contractor_ID=@ContractorID;
----------------------
-------------------auto enlistment no generation------------------
declare @MaxContractorID1 int
Set @MaxContractorID1= (SELECT ISNULL(max(c.contractorID),0) FROM Contractors c where Office_ID= @OfficeID)
declare @CurrentYear1 varchar(4)
Set @CurrentYear1 = (Select YEAR(getdate()))
declare @EnlistmentNoNew1 varchar(20) --- format= OfficeIDCurrentYearMaxContractorID
set @EnlistmentNoNew1= (Select CAST(@OfficeID as varchar) + @CurrentYear1 + CAST(@MaxContractorID1 as varchar))
-------------------auto enlistment no generation------------------
UPDATE [dbo].[Contractors]
SET [ContractorType_ID] = @ContractorType_ID, [RegistrationDate] = @RegistrationDate, [RegExpiryDate] = @ExpiryDate, [Name] = @Name, [FatherName] = @FName,
[CNIC] = @CNIC, [ContactNo] = @Mobile, [PhoneNo] = @ContactNo, [EnlistmentNo] = @EnlistmentNo,
[Password] = @Password, [Organization_ID] = @Organization_ID, [DistrictID] = @District_ID, [User_ID] = @User_ID, [Office_ID] = @OfficeID,
[Address] = @Address, [Email] = @Email, [PecCategoryID] = @PECCategoryID, [PECCategoryNo] = @PECCategoryNo,
[CNWEnlistmentNo] = @CNWEnlistmentNo, [NTN] = @NTN, [HasTaxExempted] = @TaxExempted, [Farm] = @Farm,UpdatedBy=@User_ID,UpdatedDate=GETDATE(), EnlistmentNoNew=@EnlistmentNoNew1
WHERE ContractorID = @ContractorID;
----------- Save History...
INSERT INTO ContractorsHistory (ContractorID, ContractorType_ID, RegistrationDate, RegExpiryDate, Name, FatherName, CNIC, ContactNo,
PhoneNo, EnlistmentNo, Password, Organization_ID, DistrictID, User_ID, IsActive, EntryDateTime, LastLoginDate, Office_ID,
Address, Email, PECCategoryID, PECCategoryNo, CNWEnlistmentNo, NTN, Status, HasTaxExempted, Farm, ApprovedBy, ApprovedDate, PECReceiptNo, ExpectedDate,UpdateDate,UpdatedBy)
SELECT ContractorID, ContractorType_ID, RegistrationDate, RegExpiryDate, Name, FatherName, CNIC, ContactNo, PhoneNo, EnlistmentNoNew,
Password, Organization_ID, DistrictID, User_ID, IsActive, EntryDateTime, LastLoginDate, Office_ID, Address, Email, PECCategoryID,
PECCategoryNo, CNWEnlistmentNo, NTN, Status, HasTaxExempted, Farm, ApprovedBy, ApprovedDate, PECReceiptNo, ExpectedDate,UpdatedDate,UpdatedBy FROM Contractors
WHERE ContractorID=@ContractorID;
DELETE FROM [dbo].[SpecializationCodeContractor]
WHERE Contractor_ID = @ContractorID;
----------------------------------------
DELETE FROM [dbo].[DocumentContractor]
WHERE Contractor_ID = @ContractorID;
--delete from dbo.ContractorRenewal where ID=@RenwalID
SELECT @CurrentStatus = Status
FROM Contractors
WHERE ContractorID = @ContractorID;
IF @CurrentStatus = 5 ---5 : Approved with c&W Exemption
BEGIN
INSERT INTO dbo.SpecializationCodeContractor
SELECT SP_ID, @ContractorID
FROM @SPCode s
JOIN SpecializationCodes SP ON SP.SpecializationID = S.SP_ID
WHERE SP.SpecCategory_ID = 4; -----Electrical Engineering
END;
ELSE
BEGIN
INSERT INTO dbo.SpecializationCodeContractor
SELECT SP_ID, @ContractorID
FROM @SPCode;
END;
INSERT INTO [dbo].[DocumentContractor]
SELECT Doc_ID, @ContractorID
FROM @Doc;
-- insert into [dbo].[ContractorRenewal]
-- select @ContractorID,@BankCode,@BankName,@BankDraft,@ExpiryDate,@Amount,GETDATE()
IF EXISTS(SELECT Contractor_ID FROM ContractorRenewal WHERE ValidUpto=@ExpiryDate AND Contractor_ID=@ContractorID)
BEGIN
RAISERROR('Payment Entry already exists for selected Renewal Year!',16,1);
RETURN;
END
ELSE
BEGIN
INSERT INTO [dbo].[ContractorRenewal] (Contractor_ID,BankCode,BankName,BankDraftNo,ValidUpto,Amount,RenwalDate)
VALUES ( @ContractorID, @BankCode, @BankName, @BankDraft, @ExpiryDate, @Amount, @RegistrationDate);
END
END
Commit Transaction
End Try
Begin Catch
rollback transaction
End Catch
END;
更新:关于建议:
C#结束
public static bool SaveContractor(clsAdmin A, bool IsRenewal = false)
SqlCommand com = new SqlCommand("[dbo].ContractRegistration", OpenConnection());
bool result = false;
SqlTransaction tran = conn.BeginTransaction();
try
com.Transaction = tran;
// // Passing DataTable to SP...
SqlParameter sp = com.Parameters.AddWithValue("@SPCode", A.dt);
sp.SqlDbType = SqlDbType.Structured;
SqlParameter sp1 = com.Parameters.AddWithValue("@Doc", A.dtDoc);
sp1.SqlDbType = SqlDbType.Structured;
com.Parameters.AddWithValue("@ContractorID", A.ContractorID);
com.Parameters.AddWithValue("@ContractorType_ID", A.CategoryID);
com.Parameters.AddWithValue("@RegistrationDate", A.RegistractionDate);
com.Parameters.AddWithValue("@ExpiryDate", A.ExpiryDate);
com.Parameters.AddWithValue("@Email", A.Email);
com.Parameters.AddWithValue("@FName", A.FName);
com.Parameters.AddWithValue("@Mobile", A.Mobile);
com.Parameters.AddWithValue("@Name", A.Name);
com.Parameters.AddWithValue("@CNIC", A.CNIC);
com.Parameters.AddWithValue("@ContactNo", A.Contact);
com.Parameters.AddWithValue("@Password", A.Password);
com.Parameters.AddWithValue("@IsActive", 1);
com.Parameters.AddWithValue("@User_ID", A.UserID);
com.Parameters.AddWithValue("@Organization_ID", A.OrganizationID);
com.Parameters.AddWithValue("@District_ID", A.DistrictID);
com.Parameters.AddWithValue("@EnlistmentNo", A.EnlistmentNo);
com.Parameters.AddWithValue("@Address", A.Address);
com.Parameters.AddWithValue("@OfficeID", A.OfficeID);
com.Parameters.AddWithValue("@PECCategoryID", A.PECCategoryID);
com.Parameters.AddWithValue("@PECCategoryNo", A.PECCategoryNo);
com.Parameters.AddWithValue("@CNWEnlistmentNo", A.CNWEnlistmentNo);
com.Parameters.AddWithValue("@NTN", A.NTN);
com.Parameters.AddWithValue("@Farm", A.Farm);
com.Parameters.AddWithValue("@TaxExempted", A.TaxExe);
com.Parameters.AddWithValue("@BankCode", A.BankCode);
com.Parameters.AddWithValue("@BankName", A.BankName);
com.Parameters.AddWithValue("@BankDraft", A.BankDraftNo);
com.Parameters.AddWithValue("@Amount", A.Amount);
com.Parameters.AddWithValue("@RenwalID", A.ReID);
com.Parameters.AddWithValue("@PecReciptNo", A.PecReciptNo);
com.Parameters.AddWithValue("@ExpectedDate", A.ExpectedDate);
com.Parameters.AddWithValue("@IsRenewal", IsRenewal);
com.Parameters.AddWithValue("@RoleID", A.RoleID);
com.CommandType = CommandType.StoredProcedure;
result = com.ExecuteNonQuery().ToBool();
tran.Commit();
CloseConnection();
catch (Exception ex)
tran.Rollback();
CloseConnection();
throw ex;
return result;
【问题讨论】:
也许您在某处遗漏了END
?代码有点多,不是最好的对齐方式,很难确定
您正在处理您的过程中的事务。当这个过程的调用者在调用它之前也启动了一个事务,完成后它会得到这个错误,因为你结束了这个事务。在过程中进行事务处理总是很棘手,因为您不知道调用是否也进行事务处理
我总是让调用者处理事务,如果过程返回错误(在你的情况下是这样),那么调用者会显示错误并回滚。当没有错误时,调用者会提交。简单有效
回滚将回滚所有更改,因此跨表的不一致不会发生变化
你仍然在你的过程中开始一个事务,并且仍然提交或回滚
【参考方案1】:
您已经在应用代码中使用了事务,这就是为什么当您在过程中提交或回滚事务时,应用代码找不到要提交的内容。你得到了这个异常。
实际上,您不需要在该过程中进行任何额外的交易。一个就够了。
【讨论】:
以上是关于为啥我的存储过程在包含在事务块中时会抛出错误?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的自定义 UICollectionViewLayout 在单元格之间添加空格时会抛出错误?
为啥 npm start 会抛出 events.js:187 throw er; // 我的反应项目中未处理的“错误”事件?