0

Full error: .Net SqlClient Data ProviderThe INSERT statement conflicted with the FOREIGN KEY constraint "FK_SalesOrder_SalesOrderHead". The conflict occurred in database "ControlSecurity", table "dbo.SalesOrderHead", column 'id'.

DB Table information: FK_SalesOrder_SalesOrderHead (relationship) has primary key id from SalesOrderHead, and FK=SalesOrderID.

SalesOrderInsert(Stored Procedure)

[dbo].[SalesOrderInsert] 
@SalesOrder udtSalesOrder readonly
AS
BEGIN
INSERT INTO SalesOrder
(ProductID,Quantity,UnitPrice,SalesOrderID)
SELECT ProductID,Quantity,UnitPrice,SalesOrderID
FROM @SalesOrder
END

User Defined table udtSalesOrder:

CREATE TYPE [dbo].[udtSalesOrder] AS TABLE(
[ProductID] [int] NULL,
[Quantity] [int] NULL,
[SalesOrderID] [int] NULL,
[UnitPrice] [int] NULL
)

I am adding a row to SalesOrderHead table, then get the scope id and use stored procedure to insert multiple rows from a datatable into SalesOrder table. All of this in one transaction in c# code. But it seems that the second ExecuteNonQuery does not know it's part of the transaction, or my understanding of the transaction scope is incorrect. Should I post query of the stored procedure here. I'm not sure.

using (SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["dbconn"].ToString()))
            {
                try
                {
                    con.Open();

                    using (var tran = con.BeginTransaction())
                    {
                        try
                        {

                            SqlCommand cmd = new SqlCommand("Insert into SalesOrderHead(cust_id,Description,OrderDate,DeliveryDate,Priority,CustomerRef) VALUES(@cust_id,@Description,@OrderDate,@DeliveryDate,@Priority,@CustomerRef) SELECT @id = CAST(SCOPE_IDENTITY() AS int)",con,tran);
                            cmd.Parameters.AddWithValue("@cust_id", CustomersList.EditValue);
                            cmd.Parameters.AddWithValue("@Description", Remarks.Text);
                            cmd.Parameters.AddWithValue("@OrderDate", OrderDate.DateTime);
                            cmd.Parameters.AddWithValue("@DeliveryDate", DeliveryDate.DateTime);
                            cmd.Parameters.AddWithValue("@Priority", PriorityComboBox.Text);
                            cmd.Parameters.AddWithValue("@CustomerRef", CustomerRef.Text);
                            cmd.Parameters.AddWithValue("@id", SqlDbType.Int).Direction = ParameterDirection.Output;
                            cmd.ExecuteNonQuery();
                            var SalesOrderHeadID = cmd.Parameters["@id"].Value;


                            cmd.Parameters.Clear();
                            cmd.CommandText = "SalesOrderInsert";

                            //cmd = new SqlCommand("SalesOrderInsert", con, tran);
                            //cmd.Transaction = tran;
                            cmd.CommandType = CommandType.StoredProcedure;
                            //Add from SalesOrderTB to SalesOrder stored procedure
                            cmd.Parameters.AddWithValue("@SalesOrder", SalesOrderTB);
                            cmd.ExecuteNonQuery();

                            // Record inserted in both table
                            tran.Commit();

                            XtraMessageBox.Show("Added to database success");
                            con.Close();
                        }
                        catch (SqlException ex)
                        {
                            tran.Rollback();
                            Console.WriteLine(ex.Source + ex.Message);
                        }
                    }

                }
                catch (Exception)
                {

                    throw;
                }
            }
awaisharoon
  • 463
  • 1
  • 3
  • 16
  • When you create a DataTable using a DataAdapter there is a mapping that is created so when you update the table the changed data will automatically be stored back into the database. A SQL Connection contains 4 commands 1) Select 2) Insert 3) Update 4) Delete. All four command are required to do the update. So a CommandBuilder takes a Select Command and create the other three. See : https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommandbuilder?view=netframework-4.8 – jdweng Nov 02 '19 at 14:08
  • How do I create a datatable with the DataAdapter without loading the data with Fill method? Because the datatable is supposed to be empty and not load anything from database. – awaisharoon Nov 02 '19 at 14:12
  • Related - don't use [addwithvalue](http://www.dbdelta.com/addwithvalue-is-evil/) – SMor Nov 02 '19 at 14:19
  • Please provide the full error you get. It will have more info about which constraint is not satisfied. Also, we have no idea what `SalesOrderInsert` because you have not provided the code. – CodingYoshi Nov 02 '19 at 15:11
  • You're not passing the SalesOrderHeadID to the `SalesOrderInsert` stored procedure. You need to set that value on all the `SalesOrderTB` rows, or pass the value as a scalar parameter to the stored procedure and use it in the INSERT. – David Browne - Microsoft Nov 02 '19 at 15:13
  • Sql profiler says: `declare @p9 int set @p9=1056 declare @p1 dbo.udtSalesOrder insert into @p1 values(N'1',N'111',N'100',N'1056') exec SalesOrderInsert @SalesOrder=@p1` – awaisharoon Nov 02 '19 at 15:31
  • my user defined table: [dbo].[udtSalesOrder] AS TABLE [ProductID] [Quantity] [SalesOrderID] [UnitPrice] stored procedure(SalesOrderInsert): INSERT INTO SalesOrder (ProductID,Quantity,UnitPrice,SalesOrderID) – awaisharoon Nov 02 '19 at 15:35
  • I added the error detail and PK and FK constraint information for better understanding. – awaisharoon Nov 02 '19 at 15:38
  • It seems that either the stored procedure or the user defined table had different order of columns. I had to drop them both and insert them again to fix the error "foreign key constraint" – awaisharoon Nov 02 '19 at 16:38
  • You need just an empty table using the constructor : DataTable dt = new DataTable(); – jdweng Nov 02 '19 at 16:42
  • How do you fill `SalesOrderTB`? – Farhad Rahmanifard Nov 02 '19 at 17:12
  • `SalesOrderTB` gets user input from a GridView – awaisharoon Nov 03 '19 at 15:06

0 Answers0