【发布时间】:2014-07-17 16:26:12
【问题描述】:
我有一组需要作为事务运行的存储过程(它们每个都是独立的事务)。我正在使用事务范围对象作为它的全部或全部任务。在第一个 ExecuteNonQuery 运行后,虽然我得到 SQLException “EXECUTE 后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。以前的计数 = 1,当前计数 = 0”。在不包含在事务范围内的情况下运行该过程可以正常工作,并且我没有收到上述错误,但我需要确保所有这些都运行完成而没有错误,或者所有这些都需要回滚。
public static void ImportHedges(DataTable hedges, string fileName, string importedBy)
{
try
{
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Energy"].ConnectionString))
{
connection.Open();
SqlCommand newContractsCommand = new SqlCommand("SP_ImportNewContracts", connection);
newContractsCommand.CommandType = CommandType.StoredProcedure;
newContractsCommand.Parameters.Add("@ImportedBy", SqlDbType.NVarChar).Value = importedBy;
newContractsCommand.Parameters.Add("@FileName", SqlDbType.NVarChar).Value = fileName;
DataTable newContracts = hedges.AsEnumerable().Where(i => i["ContractStatus"].ToString() == "New").CopyToDataTable();
SqlParameter newContractsParameter = newContractsCommand.Parameters.AddWithValue("@Hedges", newContracts);
newContractsParameter.SqlDbType = SqlDbType.Structured;
newContractsParameter.TypeName = "dbo.Hedges";
SqlCommand renewContractsCommand = new SqlCommand("SP_ImportRenewContracts", connection);
renewContractsCommand.CommandType = CommandType.StoredProcedure;
renewContractsCommand.Parameters.Add("@ImportedBy", SqlDbType.NVarChar).Value = importedBy;
renewContractsCommand.Parameters.Add("@FileName", SqlDbType.NVarChar).Value = fileName;
DataTable renewContracts = hedges.AsEnumerable().Where(i => i["ContractStatus"].ToString() == "Renew").CopyToDataTable();
SqlParameter renewContractsParameter = newContractsCommand.Parameters.AddWithValue("@Hedges", renewContracts);
renewContractsParameter.SqlDbType = SqlDbType.Structured;
renewContractsParameter.TypeName = "dbo.Hedges";
SqlCommand amendContractsCommand = new SqlCommand("SP_ImportAmendContracts", connection);
amendContractsCommand.CommandType = CommandType.StoredProcedure;
amendContractsCommand.Parameters.Add("@ImportedBy", SqlDbType.NVarChar).Value = importedBy;
amendContractsCommand.Parameters.Add("@FileName", SqlDbType.NVarChar).Value = fileName;
DataTable amendContracts = hedges.AsEnumerable().Where(i => i["ContractStatus"].ToString() == "Amend").CopyToDataTable();
SqlParameter amendContractsParameter = newContractsCommand.Parameters.AddWithValue("@Hedges", amendContracts);
amendContractsParameter.SqlDbType = SqlDbType.Structured;
amendContractsParameter.TypeName = "dbo.Hedges";
SqlCommand fixedContractsCommand = new SqlCommand("SP_ImportFixedContracts", connection);
fixedContractsCommand.CommandType = CommandType.StoredProcedure;
fixedContractsCommand.Parameters.Add("@ImportedBy", SqlDbType.NVarChar).Value = importedBy;
fixedContractsCommand.Parameters.Add("@FileName", SqlDbType.NVarChar).Value = fileName;
DataTable fixedContracts = hedges.AsEnumerable().Where(i => i["ContractStatus"].ToString() == "Fixed").CopyToDataTable();
SqlParameter fixedContractsParameter = newContractsCommand.Parameters.AddWithValue("@Hedges", fixedContracts);
fixedContractsParameter.SqlDbType = SqlDbType.Structured;
fixedContractsParameter.TypeName = "dbo.Hedges";
newContractsCommand.ExecuteNonQuery();
renewContractsCommand.ExecuteNonQuery();
amendContractsCommand.ExecuteNonQuery();
fixedContractsCommand.ExecuteNonQuery();
connection.Close();
}
ts.Complete();
}
}
catch (Exception Ex)
{
Email.SendEmail("Error in: Energy at " + DateTime.Now.ToString() + " - " + Thread.CurrentPrincipal.Identity.Name, Ex.Message + Environment.NewLine + Ex.StackTrace);
}
}
ALTER PROCEDURE [dbo].[SP_ImportNewContracts]
@FileName NVARCHAR(100),
@ImportedBy NVARCHAR(20),
@Hedges dbo.Hedges READONLY
AS
BEGIN TRY
INSERT INTO ClientRetailers (ClientID, RetailerID, StartDate, EndDate, EnergyType, ContractStatus)
SELECT DISTINCT (SELECT ClientID FROM Clients WHERE CustomerNumber = H.CustomerNumber),(SELECT RetailerID FROM Retailers WHERE RetailerName = H.Retailer),
RetailerStartDate, RetailerEndDate, EnergyType, ContractStatus
FROM @Hedges H
WHERE NOT EXISTS (SELECT ClientRetailersID FROM ClientRetailers WHERE ClientID = (SELECT ClientID FROM Clients WHERE CustomerNumber = H.CustomerNumber) AND
RetailerID = (SELECT RetailerID FROM Retailers WHERE RetailerName = H.Retailer) AND EnergyType = H.EnergyType)
INSERT INTO ClientRetailerProducts (ClientRetailersID, ProductID, StartDate, EndDate, ProductPercentage)
SELECT DISTINCT (SELECT TOP(1) ClientRetailersID FROM ClientRetailers WHERE ClientID = (SELECT TOP(1) ClientID FROM Clients WHERE CustomerNumber = H.CustomerNumber) AND
RetailerID = (SELECT TOP(1) RetailerID FROM Retailers WHERE RetailerName = H.Retailer) AND EnergyType = H.EnergyType),
(SELECT ProductID FROM Products WHERE ProductName = H.HedgeType), ProductStartDate, ProductEndDate, ProductPercentage
FROM @Hedges H
WHERE NOT EXISTS (SELECT TOP(1) ClientRetailersID FROM ClientRetailerProducts WHERE ProductID = (SELECT TOP(1) ProductID FROM Products WHERE ProductName = H.HedgeType)
AND ClientRetailersID = (SELECT TOP(1) ClientRetailersID FROM ClientRetailers WHERE ClientID = (SELECT TOP(1) ClientID FROM Clients WHERE CustomerNumber = H.CustomerNumber) AND
RetailerID = (SELECT TOP(1) RetailerID FROM Retailers WHERE RetailerName = H.Retailer) AND EnergyType = H.EnergyType))
INSERT INTO Files (FileName, ImportDate, ImportedBy)
VALUES (@FileName, GETDATE(), @ImportedBy)
DECLARE @FileID INT = SCOPE_IDENTITY()
INSERT INTO Hedge (ClientRetailersID, ProductID, FixedPricePerUnit, Year, January, February, March, April,
May, June, July, August, September, October, November, December, FileID)
SELECT (SELECT TOP(1) ClientRetailersID FROM ClientRetailers WHERE ClientID = (SELECT TOP(1) ClientID FROM Clients WHERE CustomerNumber = H.CustomerNumber) AND
RetailerID = (SELECT TOP(1) RetailerID FROM Retailers WHERE RetailerName = H.Retailer) AND EnergyType = H.EnergyType),
(SELECT TOP(1) ProductID FROM Products WHERE ProductName = H.HedgeType), FixedPricePerUnit, Year, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, @FileID
FROM @Hedges H
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
其他三个存储过程遵循相同的事务结构。
【问题讨论】:
-
你不能有子交易...抱歉
-
sql server 中的嵌套事务是一个神话。文档确实讨论了它们,但它们没有做你认为应该做的事情。如果您开始第二个事务,实际发生的唯一事情是它增加@@trancount。任何回滚都会回滚事务并将@@trancount 重置为0。
-
该死。好的,我想我必须把这些程序变成一个巨大的程序/交易。
标签: c# sql-server ado.net transactionscope