C# 无法添加或更新子行:在foreach中执行INSERT时,外键约束失败
在尝试在MySQL db中添加某些项时,出现以下错误: :'无法添加或更新子行:外键约束失败(C# 无法添加或更新子行:在foreach中执行INSERT时,外键约束失败,c#,mysql,C#,Mysql,在尝试在MySQL db中添加某些项时,出现以下错误: :'无法添加或更新子行:外键约束失败(articoli\u ordini,约束fk\u articoli\u ordini\u ordini 1外键(ID\u或\u ART)引用ordini(ID\u或)在更新级联时删除级联)' 通过执行LAST\u INSERT\u ID()似乎找不到我应该添加到INSERT查询的外键,但是成功添加了列表的第一项,而下一项失败 我要添加项的MySQL表是3个,Ordini假设它是父表,Articoli\u
articoli\u ordini
,约束fk\u articoli\u ordini\u ordini 1
外键(ID\u或\u ART
)引用ordini
(ID\u或
)在更新级联时删除级联)'
通过执行LAST\u INSERT\u ID()
似乎找不到我应该添加到INSERT查询的外键,但是成功添加了列表的第一项,而下一项失败
我要添加项的MySQL表是3个,Ordini
假设它是父表,Articoli\u Ordini
的id上有外键Ordini
和Variati\u Articoli
,它指的是Articoli\u Ordini
,所以在Articoli\u Ordini
的id上有外键
我执行所有插入的方法如下所示:
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的第二个循环中失败(carrello.articoli中的var articolo)
我是否应该首先为
Articoli\u Ordini
甚至为Varianti\u Articoli
存储LAST\u INSERT\u ID();一名家长和两名相关子女。添加父对象后,成功添加第一个子对象,因为您将其父对象id声明为LAST_INSERT_id,并且最近插入的对象是父对象,因此LAST_INSERT_id返回的对象是父对象的id
但是当您插入第二个子记录时,最近插入的是第一个子记录,最后一个插入的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)
因此,是的,您应该插入父项,选择其最后一个插入ID,并将其检索/存储到C中,然后将缓存的父项ID重新用于您必须插入的每个子项
或者更好的方法是,使用一个ORM来为您完成所有这些,这样您就有了一个包含两个子对象列表的父对象,您只需说一些类似于context.Add(myParentWithTwoChildren)的话;SaveChanges()代码>。这样的软件存在,将为您节省无数时间的浪费,编写重复的insert查询,这些查询可以(也应该)由代码编写,而不是由人编写您将存储父级的最后一个插入ID
。第二次迭代使用子查询的LAST\u INSERT\u ID
。我不知道LAST\u INSERT\u ID()获取最近插入项的ID,我认为这就像获取引用外键表的最后ID一样,虽然从未听说过ORM,但通过现在阅读有关它的内容,它看起来很有趣,我一定会尝试使用它!