Reputation: 57
I am trying to create a large transactionScope that is all or nothing. I am inserting about 2000 records. I want to insert the primary key, read it back and then insert the foreign key in a transaction and then roll everything back if an error occurs.
PSS_InvoiceTotal Table has PK -> InvoiceTotalID
PSS_Invoices Table has a FK -> InvoiceTotalID
The problem is in the database each time 2 Primary Key rows are made. I ran the code without the Foreign Key insert and it worked fine. Is there a way to prevent it from making 2 Primary Key rows?
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
try
{
conn.Open();
foreach (var uniqueSupply in supplyList.GroupBy(a=>a.ShipTo))
{
//reset total
total = 0;
var supplyListByShipTo = supplyList.Where(a => a.ShipTo == uniqueSupply.Key);
foreach (var addSupply in supplyListByShipTo)
{
total = total + addSupply.Amount;
}
StringBuilder insert_PSS_InvoiceTotal = new StringBuilder();
//save total to DB
insert_PSS_InvoiceTotal = new StringBuilder();
insert_PSS_InvoiceTotal.Append("INSERT INTO [PSS_InvoiceTotal] ");
insert_PSS_InvoiceTotal.Append("([InvoiceDate],[Amount]) ");
insert_PSS_InvoiceTotal.Append("VALUES(@DateTime, @Amount) ");
insert_PSS_InvoiceTotal.Append("SELECT SCOPE_IDENTITY() AS [InvoiceTotalID];");
cmd = new SqlCommand(insert_PSS_InvoiceTotal.ToString(), conn);
cmd.Parameters.AddWithValue("@DateTime", DateTime.Now);
cmd.Parameters.AddWithValue("@Amount", total);
//ToDo: Add back in later
cmd.ExecuteNonQuery();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
InvoiceTotalID = Convert.ToInt32(dr["InvoiceTotalID"].ToString());
}
dr.Close();
foreach (var supply in supplyListByShipTo)
{
StringBuilder insert_PSS_Invoice = new StringBuilder();
//Create the SQL command
insert_PSS_Invoice.Append("INSERT INTO [PSS_Invoices] ");
insert_PSS_Invoice.Append("([ClientDetailId],Amount],InvoiceTotalId)");
insert_PSS_Invoice.Append("VALUES(");
insert_PSS_Invoice.Append("@Amount,@InvoiceTotalId)");
cmd = new SqlCommand(insert_PSS_Invoice.ToString(), conn);
cmd.Parameters.AddWithValue("@Amount", 4.44);
cmd.Parameters.AddWithValue("@InvoiceTotalId", InvoiceTotalID);
//ToDo: put back in later
cmd.ExecuteNonQuery();
}
}
//Close connection
conn.Close();
//Commit and Dispose Transaction
scope.Complete();
scope.Dispose();
}
catch (Exception ex)
{
//Rollback Transaction
scope.Dispose();
return Json(new { success = false, message = ex.ToString() }, JsonRequestBehavior.AllowGet);
}
}
Upvotes: 1
Views: 677
Reputation: 49
May be you can look into using the OUTPUT option of the INSERT command to get the Primary Key on the insert execution. That way you don't have to read it back. Check out this link: https://msdn.microsoft.com/en-us/library/ms177564.aspx
In addition, you may need to add an output parameter to your command object to get that information.
Upvotes: -1
Reputation: 12309
try to comment
//ToDo: Add back in later
//cmd.ExecuteNonQuery();
Upvotes: 0