简体   繁体   中英

How to delete a record with a foreign key constraint to another table?

When I tried to delete row from datagridview refer to table Famille, I get this error is :

An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll Additional information: The DELETE statement conflicted with the REFERENCE constraint "FK_NatureCharge_Famille". The conflict occurred in database "Tresorerie", table "dbo.NatureCharge", column 'IdFam'. The statement has been terminated.

this the tables (Famille and NatureCahrge) 在此处输入图片说明
By the way, the Famille part can delete multiple row in datagridview. I tried to add delete the NaturCharge 1st (it begins with comment delete Nature)
The code :

private void DeleteFamBtn_Click(object sender, EventArgs e)
    {
        List<DataGridViewRow> selectedRows = (from row in DataGridViewFamille.Rows.Cast<DataGridViewRow>()
                                              where Convert.ToBoolean(row.Cells["checkBoxColumn"].Value) == true
                                              select row).ToList();


        if (MessageBox.Show(string.Format("Do you want to delete {0} rows?", selectedRows.Count), "Confirmation", MessageBoxButtons.YesNo) == DialogResult.Yes)
        {
            //delete Nature de Charge before delete Famille
            foreach (DataGridViewRow row in selectedRows)
            {
                try
                {
                    using (SqlConnection con = new SqlConnection(connstring))
                    {
                        con.Open();
                        using (SqlCommand command = new SqlCommand("DELETE NatureCharge FROM NatureCharge n INNER JOIN Famille f on n.IdFam = f.IdFam WHERE IdNat = @IdNat", con))
                        {
                            command.Parameters.AddWithValue("@IdFam", row.Cells["IdFam"].Value);
                            command.ExecuteNonQuery();
                        }
                        con.Close();
                    }
                }
                catch (SystemException ex)
                {
                    MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
                }

            }

            //Delete Famille
            foreach (DataGridViewRow row in selectedRows)
            {
                using (SqlConnection con = new SqlConnection(connstring))
                {
                    using (SqlCommand cmd = new SqlCommand("DELETE FROM Famille WHERE IdFam = @IdFam", con))
                    {
                        cmd.CommandType = CommandType.Text;
                        cmd.Parameters.AddWithValue("@IdFam", row.Cells["IdFam"].Value);
                        con.Open();
                        cmd.ExecuteNonQuery();
                        con.Close();
                    }
                }
            }

            //Update the datagridview
            this.BindGrid();
        }
    }

an error shows with line (it is for Famille part) `cmd.ExecuteNonQuery();``

Additional information: The DELETE statement conflicted with the REFERENCE constraint "FK_NatureCharge_Famille". The conflict occurred in database "Tresorerie", table "dbo.NatureCharge", column 'IdFam'.

It looks The DELETE statement doesn't seem to be correct

Update Code

//delete Nature de Charge before delete Famille
            foreach (DataGridViewRow row in selectedRows)
            {
                try
                {
                    using (SqlConnection con = new SqlConnection(connstring))
                    {
                        con.Open();
                        using (SqlCommand command = new SqlCommand("DELETE NatureCharge FROM NatureCharge n INNER JOIN Famille f on n.IdFam = f.IdFam WHERE IdNat = @IdNat", con))
                        {
                            command.ExecuteNonQuery();
                        }
                        con.Close();
                    }
                }
                catch (SystemException ex)
                {
                    MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
                }
            }

and the same error...

You can delete all the foreign key records in their original tables by using cascade.

In some DBMSs its set on the level of the foreign key constraint and some on the delete itself.

Check the following link for more info.

http://www.techonthenet.com/sql_server/foreign_keys/foreign_delete.php

I this case I recomend you to use cascade delete in foreign key action, you can matain your code base more simplified than deleting related registers by yourself.

But if you still want to do it yourself, you can use this piece of code that I have motified

private void DeleteFamBtn_Click(object sender, EventArgs e)
{
    List<DataGridViewRow> selectedRows = (from row in DataGridViewFamille.Rows.Cast<DataGridViewRow>()
                                          where Convert.ToBoolean(row.Cells["checkBoxColumn"].Value)
                                          select row).ToList();


    if (MessageBox.Show(string.Format("Do you want to delete {0} rows?", selectedRows.Count), "Confirmation", MessageBoxButtons.YesNo) == DialogResult.Yes)
    {
        //delete Nature de Charge before delete Famille
        var idsToDelete = selectedRows.Select(row => row.Cells["IdFam"].Value).ToList();
        try
        {
            using (var con = new SqlConnection(connstring))
            {
                var ids = string.Join(",", idsToDelete);
                using (var deleteNatures = new SqlCommand("DELETE FROM NatureCharge IdFam IN " + ids, con))
                using (var deleteFamilles = new SqlCommand("DELETE FROM Famille WHERE Id IN " + ids, con))
                {
                    deleteNatures.Parameters.AddWithValue("@IdFam", row.Cells["IdFam"].Value);
                    con.Open();
                    deleteNatures.ExecuteNonQuery();
                    deleteFamilles.ExecuteNonQuery();
                }

                con.Close();
            }
        }
        catch (SystemException ex)
        {
            MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
        }

        //Update the datagridview
        this.BindGrid();
    }
}

My solution : Before deleted the table, I must delete all related table that relate with. So My ocde is simple, I get the IdFam of selected DataGridView than I delete the row with same ID in NatureCharge's table

My code :

private void DeleteFamBtn_Click(object sender, EventArgs e)
    {
        List<DataGridViewRow> selectedRows = (from row in DataGridViewFamille.Rows.Cast<DataGridViewRow>()
                                              where Convert.ToBoolean(row.Cells["checkBoxColumn"].Value) == true
                                              select row).ToList();

        if (MessageBox.Show(string.Format("Do you want to delete {0} rows?", selectedRows.Count), "Confirmation", MessageBoxButtons.YesNo) == DialogResult.Yes)
        {
            //delete Nature de Charge before delete Famille
            foreach (DataGridViewRow row in selectedRows)
            {
                int aa = Convert.ToInt32(row.Cells["IdFam"].Value);
                conn = new SqlConnection(connstring);
                conn.Open();
                comm = new SqlCommand("DELETE FROM NAtureCharge WHERE IdFam ='" + aa + "'", conn);
                try
                {
                    comm.ExecuteNonQuery();
                    //MessageBox.Show("Deleted...");
                }
                catch (Exception)
                {
                    MessageBox.Show("Not Deleted");
                }
                finally
                {
                    conn.Close();
                }
            }

            //Delete Famille
            foreach (DataGridViewRow row in selectedRows)
            {
                using (SqlConnection con = new SqlConnection(connstring))
                {
                    using (SqlCommand cmd = new SqlCommand("DELETE FROM Famille WHERE IdFam = @IdFam", con))
                    {
                        cmd.CommandType = CommandType.Text;
                        cmd.Parameters.AddWithValue("@IdFam", row.Cells["IdFam"].Value);
                        con.Open();
                        cmd.ExecuteNonQuery();
                        con.Close();
                    }
                }
            }

            //Update the datagridview
            this.BindGrid();
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM