当我尝试在单个事务中使用不同方法插入记录时,为什么会出现此异常?

时间:2014-03-26 11:40:16

标签: c# asp.net .net transactions

我有以下问题:

我有一个旧方法在3个表中执行插入(名为 Cpe CpeVendor CpeProduct ,尊重参照完整性约束。< / p>

此方法只需在其正文中执行3个插入查询:首先记录到 CpeVendor CpeProduct ,然后 Cpe ,并引用前2条记录。 3插入是在交易中。

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

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

    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}

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

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

1 个答案:

答案 0 :(得分:2)

您使用的是哪种类型的交易? ADO.NET交易? TransactionScope

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

如果TransactionScope:在交易开始之前连接已打开,那么它就不会登记;自动登记仅发生在环境事务内部打开的连接

在任何一种情况下,我都会说_transactionBegin(); / _transactionRollback();等(可能是使用字段)是一种非常糟糕的方法来确定交易范围。但如果没有更多的背景,很难说。