我有以下问题:
我有一个旧方法在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()方法中执行的插入的同一事务中。
是问题还是什么?我该怎么做才能解决这个问题?
答案 0 :(得分:2)
您使用的是哪种类型的交易? ADO.NET交易? TransactionScope
?
如果是ADO.NET:您尚未将事务附加到命令(command.Transaction = ...
)
如果TransactionScope
:在交易开始之前连接已打开,那么它就不会登记;自动登记仅发生在环境事务内部打开的连接
在任何一种情况下,我都会说_transactionBegin();
/ _transactionRollback();
等(可能是使用字段)是一种非常糟糕的方法来确定交易范围。但如果没有更多的背景,很难说。