【问题标题】:Transaction Count mismatch with layered transactions事务计数与分层事务不匹配
【发布时间】: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


【解决方案1】:

您的存储过程中缺少BEGIN TRANSACTION

【讨论】:

  • 您使用的是命名事务、未命名事务还是两者的组合?将两者混合可能会导致问题...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多