【问题标题】:Why I obtain this exception when I try to insert records by different methods in a single transaction?当我尝试在单个事务中通过不同方法插入记录时,为什么会出现此异常?
【发布时间】:2014-03-26 11:40:16
【问题描述】:

我有以下问题:

我有一个旧方法在 3 个表中执行插入操作(名为 CpeCpeVendorCpeProduct 尊重参照完整性约束。

此方法只需在其主体中执行 3 次插入查询:首先将记录放入 CpeVendorCpeProduct,然后在 Cpe 中引用前 2 条记录。 3 插入在事务中。

现在我用这种方式重构了这个方法:

我创建了 2 个将记录插入 CpeVendorCpeProduct 的私有方法,我将它们调用到主插入方法中,但现在我得到了一个异常。这是我的代码:

    public long insert(DataModel.CPE.CPE cpe)
    {
        _strSQL = "";
        string strSQLParametri = "";
        string query = "";

        long CpeVendorId, CpeProductId;

        long newId;

        try
        {
            _transactionBegin();

            if (cpe.Cpe == null)
            {
                return -1;
            }

            System.Data.Common.DbCommand command;
            command = _connection.CreateCommand();

            // Se il vendor non è presente nella tabella CpeVendor:
            if (cpe.VendorId == -1)         
            {
                CpeVendorId = this.insertCpeVendor(cpe.Vendor);   
            }

            // Se il product non è presente nella tabella CpeProduct:
            if (cpe.ProductId == -1)         
            {
                cpe.ProductId = this.insertCpeProduct(cpe.Product);
            }

            #region INSERIMENTO DEL CPE

            _strSQL = "INSERT INTO Cpe ( DateAdded,  [Cpe] ";
            strSQLParametri = " VALUES ( GETDATE(), @CPE ";
            addParameter(command, "@CPE ", cpe.Cpe);


            // [SourceId] insertion on the DB:
            if (cpe.SourceId != null)
            {
                _strSQL += ",[SourceId] ";
                strSQLParametri += ", @SOURCEID ";
                addParameter(command, "@SOURCEID ", cpe.SourceId);
            }

            // [vendor_id] insertion on the DB:
            if (cpe.VendorId != null)
            {
                _strSQL += ",[vendor_id] ";
                strSQLParametri += ", @VENDORID ";
                addParameter(command, "@VENDORID ", cpe.VendorId);
            }

            // [Title] insertion on the DB:
            if (cpe.Title != null)
            {
                _strSQL += ",[Title] ";
                strSQLParametri += ", @TITLE ";
                addParameter(command, "@TITLE ", cpe.Title);
            }

            // [part] insertion on the DB:
            if (cpe.Part != null)
            {
                _strSQL += ",[part] ";
                strSQLParametri += ", @PART ";
                addParameter(command, "@PART ", cpe.Part.ToString().ToLower().Substring(0,1));
            }

            // [product_id] insertion on the DB:
            if (cpe.ProductId != null)
            {
                _strSQL += ",[product_id] ";
                strSQLParametri += ", @PRODUCTID";
                addParameter(command, "@PRODUCTID ", cpe.ProductId);
            }

            // [version] insertion on the DB:
            if (cpe.Version != null)
            {
                _strSQL += ",[version] ";
                strSQLParametri += ", @VERSION";
                addParameter(command, "@VERSION ", cpe.Version);
            }

            // [revision] insertion on the DB:
            if (cpe.Revision != null)
            {
                _strSQL += ",[revision] ";
                strSQLParametri += ", @REVISION";
                addParameter(command, "@REVISION ", cpe.Revision);
            }

            // [edition] insertion on the DB:
            if (cpe.Edition != null)
            {
                _strSQL += ",[edition] ";
                strSQLParametri += ", @EDITION";
                addParameter(command, "@EDITION ", cpe.Edition);
            }

            // [language] insertion on the DB:
            if (cpe.Language != null)
            {
                _strSQL += ",[language] ";
                strSQLParametri += ", @LANGUAGE";
                addParameter(command, "@LANGUAGE ", cpe.Language);
            }

            // [software_edition] insertion on the DB:
            if (cpe.SoftwareEdition != null)
            {
                _strSQL += ",[software_edition] ";
                strSQLParametri += ", @SOFTWAREEDITION";
                addParameter(command, "@SOFTWAREEDITION ", cpe.SoftwareEdition);
            }

            // [target_software] insertion on the DB:
            if (cpe.TargetSoftware != null)
            {
                _strSQL += ",[target_software] ";
                strSQLParametri += ", @TARGETSOFTWARE";
                addParameter(command, "@TARGETSOFTWARE ", cpe.TargetSoftware);
            }

            // [target_hardware] insertion on the DB:
            if (cpe.TargetHardware != null)
            {
                _strSQL += ",[target_hardware] ";
                strSQLParametri += ", @TARGETHARDWARE";
                addParameter(command, "@TARGETHARDWARE ", cpe.TargetHardware);
            }

            // [other] insertion on the DB:
            if (cpe.Other != null)
            {
                _strSQL += ",[other] ";
                strSQLParametri += ", @OTHER";
                addParameter(command, "@OTHER ", cpe.Other);
            }

            query = _strSQL + " ) " + strSQLParametri + " );";
            command.CommandText = query;
            _executeNoQuery(command);

            newId = _getIdentity();
            //Debug.WriteLine("Id: " + newId);
            #endregion

            _transactionCommit();

            return newId;
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Exception: " + ex.Message);
            _transactionRollback();
            return -1;
        }
    }

    private long insertCpeVendor(String vendorName){
        System.Data.Common.DbCommand command;
        command = _connection.CreateCommand();
        string strSQLParametri = "";
        string query = "";
        long CpeVendorId = -1;

        // [nome] insertion on the DB:
        if (vendorName != null)
        {
            _strSQL = "INSERT INTO CpeVendor ( [nome] ";
            strSQLParametri = " VALUES (@VENDORNAME ";
            addParameter(command, "@VENDORNAME ", vendorName);

            // [date_added] insertion on the DB:
            _strSQL += ",[date_added] ";
            strSQLParametri += ", GETDATE() ";

            query = _strSQL + " ) " + strSQLParametri + " );";
            command.CommandText = query;
            _executeNoQuery(command);

            CpeVendorId = _getIdentity();
            Debug.WriteLine("PK della tabella CpeVendorId: " + CpeVendorId);
        }
        return CpeVendorId;
    }

    private long insertCpeProduct(String productName)
    {
        System.Data.Common.DbCommand command;
        command = _connection.CreateCommand();
        string strSQLParametri = "";
        string query = "";
        long CpeProductId = -1;

        // [nome] insertion on the DB:
        if (productName != null)
        {
            _strSQL = "INSERT INTO CpeProduct ( [nome] ";
            strSQLParametri = " VALUES (@PRODUCTNAME ";
            addParameter(command, "@PRODUCTNAME ", productName);


            // [date_added] insertion on the DB:
            _strSQL += ",[date_added] ";
            strSQLParametri += ", GETDATE() ";

            query = _strSQL + " ) " + strSQLParametri + " );";
            command.CommandText = query;
            _executeNoQuery(command);

            CpeProductId = _getIdentity();
            Debug.WriteLine("PK della tabella CpeProductId: " + CpeProductId);
        }
        return CpeProductId;
    }

问题在于,现在当它为主 insert() 方法执行 executeNoQuery 时,会启动以下异常:

{"ExecuteNonQuery terminato con errori. \r\nINSERT INTO Cpe ( DateAdded,  [Cpe] ,[SourceId] ,[vendor_id] ,[Title] ,[part] ,[product_id] ,[version]  )  VALUES ( GETDATE(), @CPE , @SOURCEID , @VENDORID , @TITLE , @PART , @PRODUCTID, @VERSION );\r\nThe INSERT statement conflicted with the FOREIGN KEY constraint \"FK_Cpe_CpeVendor\". The conflict occurred in database \"EarlyWarningsV2\", table \"dbo.CpeVendor\", column 'id'.\r\nThe statement has been terminated."}    System.Exception {MyManagerCSharp.MyException}

在我看来(但可能是错误的)如果我通过不同的私有方法执行插入到 CpeVendorCpeProduct 表中,因为这些插入不是在主 insert() 方法中执行的插入的同一事务中。

是问题还是什么?我该怎么做才能解决这个问题?

【问题讨论】:

    标签: c# asp.net .net transactions


    【解决方案1】:

    您使用什么类型的交易? ADO.NET 事务? TransactionScope?

    如果 ADO.NET:您尚未将事务附加到命令 (command.Transaction = ...)

    如果TransactionScope:连接在事务开始之前打开,所以它不会登记;自动登记只发生在环境事务中打开的连接

    在任何一种情况下,我都会说_transactionBegin(); / _transactionRollback(); 等(可能使用字段)是确定事务范围的一种非常糟糕的方式。但如果没有更多上下文就很难说。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      • 1970-01-01
      • 2018-06-08
      • 1970-01-01
      • 1970-01-01
      • 2022-06-12
      • 1970-01-01
      相关资源
      最近更新 更多