簡體   English   中英

無法添加或更新子行:在 foreach 中執行 INSERT 時外鍵約束失敗

[英]Cannot add or update a child row: a foreign key constraint fails while doing INSERT in a foreach

在嘗試在 MySQL db 中添加一些項目時,我收到以下錯誤:

:'無法添加或更新子行:外鍵約束失敗( articoli_ordini ,CONSTRAINT fk_articoli_ordini_ordini1 FOREIGN KEY( ID_OR_ART )REFERENCES ordiniID_OR )ON DELETE CASCADE ON UPDATE CASCADE)'

通過執行LAST_INSERT_ID()似乎找不到我應該添加到 INSERT 查詢的外鍵,但是列表的第一項已成功添加,而下一項則失敗。

我要添加項目的 MySQL 表是 3, Ordini假設它是父表, Articoli_OrdiniOrdini的 id 和Varianti_Articoli上有外鍵,它指的是Articoli_Ordini所以在Articoli_Ordini的 id 上有外鍵。

我正在執行所有 INSERT 的方法如下所示:

var query_ordine = @"INSERT INTO `ordini` (`TIPO_OR`, `ORA_OR`, `SENT_OR`, `ID_OR_CFG`) VALUES (@tipo, NOW(), 0, @cfg);";

using var connection = new MySqlConnection(connectionString);
connection.Open();
using var cmd = new MySqlCommand(query_ordine, connection);
cmd.Parameters.AddWithValue("@tipo", carrello.tipo);
cmd.Parameters.AddWithValue("@cfg", cfg);
cmd.Parameters.AddWithValue("@id", 0);
cmd.Parameters.AddWithValue("@qta", 0);
cmd.Prepare();

try
{
    cmd.ExecuteNonQuery();
}
catch (Exception e)
{
    return new StatusCodeResult(500);
}

foreach (var articolo in carrello.articoli)
{
    var query_articolo = @"INSERT INTO `articoli_ordini` (`TIPO_ART`, `COD_ART`, `QTA_ART`, `ID_OR_ART`) VALUES (@tipo, (SELECT CODICE_PRP FROM vo_plurep WHERE ID_PLUREP = @id), @qta, LAST_INSERT_ID());";
    cmd.CommandText = query_articolo;
    cmd.Parameters["@tipo"].Value = articolo.tipo;
    cmd.Parameters["@id"].Value = articolo.id;
    cmd.Parameters["@qta"].Value = articolo.qta;
    cmd.ExecuteNonQuery();

    foreach(var variante in articolo.varianti)
    {
        var query_variante = @"INSERT INTO `varianti_articoli` (`COD_VAR`, `ID_ART_VAR`) VALUES ((SELECT CODICE_VAR FROM vo_varianti WHERE ID_VARIANTI = @id),  LAST_INSERT_ID());";
        cmd.CommandText = query_variante;
        cmd.Parameters["@id"].Value =  variante.id;
        cmd.ExecuteNonQuery();
    }
}

並且在foreach (var articolo in carrello.articoli)

我應該先為Articoli_Ordini甚至為Varianti_Articoli存儲LAST_INSERT_ID()並使用它而不是直接插入LAST_INSERT_ID()嗎?

假設您要插入 3 樣東西; 一位家長和兩個相關的孩子。 您添加了父級,您成功添加了第一個子級,因為您將其父級 ID 聲明為 LAST_INSERT_ID 並且最近插入的東西是父級,所以 LAST_INSERT_ID 返回的東西是父級的 ID。

但是當您插入第二個孩子時,最近插入的是第一個孩子,並且 LAST_INSERT_ID 將更改為告訴最近插入的孩子記錄的 ID。 如果父母多於孩子,這甚至可能有效,但您最終會將這個孩子與錯誤的父母聯系起來

insert parent -> last_id is parent 1234
insert child1 as child of 1234 -> last_id is child 6667
insert child2 as child of 6667 -> either: works and links child to parent 6667 
                                  or: fails (no parent 6667)

所以是的,您應該插入父 SELECT 其 LAST_INSERT_ID 並將其檢索/存儲在您的 C# 中,然后為您必須插入的每個孩子重用該緩存的父 ID


或者更好的是,使用 ORM 可以為您完成所有這些工作,因此您只有一個父 object 和一個包含兩個子 object 的列表,然后您只需說出類似context.Add(myParentWithTwoChildren); context.SaveChanges(); context.Add(myParentWithTwoChildren); context.SaveChanges(); . 存在這樣的軟件並將為您節省無數時間浪費的生命,編寫重復的插入查詢,這些查詢是如此的樣板,以至於它們可以(並且應該)由代碼而不是人類編寫

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM