当我尝试执行超过 1 个查询时,循环在 OleDb 中插入数据中断

Posted

技术标签:

【中文标题】当我尝试执行超过 1 个查询时,循环在 OleDb 中插入数据中断【英文标题】:Loop to insert data in OleDb breaks when I try to execute more than 1 query 【发布时间】:2015-05-14 14:19:43 【问题描述】:

我正在开发一个带有 Access 2002 数据库 (.mdb) 和 OleDb 的小型离线 C# 应用程序。

我有 2 个表需要同时插入数据,其中一个持有另一个的外键。因此,为了简化,假设一个表有 2 个属性:“idTable1”(自动增量整数)和“数字”,另一个有 2 个属性:“idTable2”(自动增量整数)和“fkTable1”(包含一个与表 1 中的“idTable1”匹配的整数值。

foreach 循环遍历集合并将每个元素插入 Table1 中。然后想法是在Table1上使用SELECT @@Identity查询来获取最后插入的记录的自增id字段,并将其作为外键插入到Table2中。

我只是在尝试插入外键之前尝试第一部分:遍历集合,将每个项目插入 Table1 并获取最后插入记录的 idTable1。但是每当我尝试执行 SELECT @@Identity 时,我的数据库中只会得到 1 条记录,即使循环正确地遍历了所有集合项。

我的代码如下所示:

string queryInsertTable1 = "INSERT INTO Table1 (numero) VALUES (?)";
string queryGetLastId = "Select @@Identity";

using (OleDbConnection dbConnection = new OleDbConnection(strDeConexion))

    using (OleDbCommand commandStatement = new OleDbCommand(queryInsertTable1, dbConnection))
    
        dbConnection.Open();
        foreach (int c in Collection)
        
            commandStatement.Parameters.AddWithValue("", c);
            commandStatement.ExecuteNonQuery();
            commandStatement.CommandText = queryGetLastId;
            LastInsertedId = (int)commandStatement.ExecuteScalar();
        
    

如果我注释掉最后 3 行:

commandStatement.CommandText = queryGetLastId;
LastInsertedId = (int)commandStatement.ExecuteScalar();

然后Collection 中的所有记录都正确插入到BD 中。但是一旦我取消注释这些,我只插入了 1 条记录,而存储在“c”中的值是集合中的最后一个元素(所以循环工作正常)。

我还尝试在 commandStatement.ExecuteNonQuery() 句子之后立即调用 commandStatement.Parameters.Clear(),但这没有区别(不应该,但我仍然尝试过)。

我不想通过使用事务等使事情变得复杂,如果可以避免的话,因为这是一个非常简单的单机离线小型应用程序。因此,如果有人知道我可以做些什么来使该代码正常工作,我将非常感激:)

【问题讨论】:

【参考方案1】:

这里:commandStatement.CommandText = queryGetLastId; 您实际上将命令从插入更改为选择身份。

因此,在下一次迭代中,它不会插入任何内容,而是再次选择标识,这就是为什么您只将一条记录插入 DB。

我认为最好有两个单独的命令用于插入和选择身份。

另请注意 - 您尝试在每次迭代时将新参数添加到 commandStatement 中,因此在迭代时,例如 N 它将是 N 个参数。在添加新参数之前清除参数,或者在循环之外添加参数并在循环中仅更改其值。

using (OleDbConnection dbConnection = new OleDbConnection(strDeConexion))

    using (OleDbCommand commandStatement = new OleDbCommand(queryInsertTable1, dbConnection))
    using (OleDbCommand commandIdentity = new OleDbCommand(queryGetLastId , dbConnection))
        
        commandStatement.Parameters.Add(new OleDbParameter());

        dbConnection.Open();
        foreach (int c in Collection)
        
            commandStatement.Parameters[0].Value = c;
            commandStatement.ExecuteNonQuery();

            LastInsertedId = (int)commandIdentity.ExecuteScalar();
        
    

【讨论】:

foreach的开头加上commandStatement.CommandText = queryInsertTable1怎么样? @MikeDebela 好吧,这是可能的。但我仍然认为有两个单独的命令更好。否则,您需要重新分配来回参数、命令文本等 - 这会使代码的可读性大大降低。 该死!我知道这一定很愚蠢 :P 太多的编程和太少的睡眠!谢谢!!【参考方案2】:

一旦您更改了命令文本,第一个查询就会从它那里消失,因此它不会再次向第一个表插入任何数据。重新评估并尝试

【讨论】:

以上是关于当我尝试执行超过 1 个查询时,循环在 OleDb 中插入数据中断的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历文本文件中的 SQL 查询并执行 - pyodbc

Laravel Eloquent 方法 updateOrCreate 更新时超过执行时间

用OLEDB读取EXCEL时,单元格内容长度超过255被截断

无法从 .NET OleDB.DataReader 检索行

循环通过api请求时插入失败只执行第一个查询

尝试执行 INSERT INTO 时 OleDb 异常 0x80040e14