【问题标题】:C# Can I make (SqlDataReader) in pause status?C# 我可以让(SqlDataReader)处于暂停状态吗?
【发布时间】:2018-10-29 20:21:53
【问题描述】:

我得到这个错误:

已经有一个打开的 DataReader 与此命令关联,必须先关闭

这是我的代码:

String sql_get_completed_tasks = "select * from tasks where Ending_date is not null order by Ending_date asc";
SqlCommand command_get_completed_tasks_ = new SqlCommand(sql_get_completed_tasks, cn);

SqlDataReader reader = command_get_completed_tasks_.ExecuteReader();

while (reader.Read())
{  
    String sql_insert_completed_tasks_toTheNewTable = "insert into history_of_tasks_achievements values ("+
                reader[1] +" , N'"+ reader[2]+"' , @image , N'"+ reader[4] +"' , N'"+reader[5]+"' , N'"+ reader[6]+"' , "+
                reader[7] +" , N'"+reader[8]+"' , N'"+reader[9] +"' , "+reader[10]+" , @start_date , @end_date , "+reader[13]+
            ")";

    SqlCommand com_insert_completed_tasks_toTheNewTable = new SqlCommand(sql_insert_completed_tasks_toTheNewTable, cn);

    com_insert_completed_tasks_toTheNewTable.Parameters.Add(new SqlParameter("@image", reader[3]));
    com_insert_completed_tasks_toTheNewTable.Parameters.Add(new SqlParameter("@start_date", reader[11]));
    com_insert_completed_tasks_toTheNewTable.Parameters.Add(new SqlParameter("@end_date", reader[12]));

    com_insert_completed_tasks_toTheNewTable.ExecuteNonQuery();
}    // end of while loop

reader.Close();

MessageBox.Show("Done");

要跳过此错误,我可以为SqlDataReader 创建暂停或关闭,然后从中断值重新打开吗?最好的解决方案是什么?

【问题讨论】:

  • 您知道您可以在同一个连接上使用 MARS 进行多个查询吗? docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/… - 实际上它打开了多个连接,所以要注意这一点。您还可以读取所有数据,然后执行插入语句。
  • 首先我必须激活 MARS 指令,然后执行插入指令,然后是非活动 MARS?
  • 我要让你大吃一惊。 Verbatim strings.
  • @Na'ilLaith 请不要连接值来创建 SQL。这是一个巨大的安全漏洞,而且它会导致多个值的错误。你应该使用 parameters.
  • @Shadetheartist 我对逐字字符串发表了评论-但我是个白痴-我误读了您建议使用$"..."字符串-我的错,对不起; @"..." 字符串很好!

标签: c# sql-server sqldatareader


【解决方案1】:

这实际上应该只是 1 条语句,无需迭代来自 select 的结果,只需使用 insert 将它们推回同一个数据库。

const string sqlInsert = 
@"INSERT INTO [history_of_tasks_achievements] (col1, col2, col3, ...) 
SELECT col1, col2, col3, ... FROM [tasks] WHERE [Ending_date] IS NOT NULL ORDER BY [Ending_date] ASC";

using(var con = new SqlConnection("connection string here"))
using(var command = new SqlCommand(sqlInsert, con))
{
  con.Open();
  var inserted = command.ExecuteNonQuery();
}

确保将SELECTINSERT 之间的列对齐,以便它们匹配。

【讨论】:

  • 我正确使用了您的代码-但没有“使用”语句,而是使用“sqlconnection”并且我已经打开了数据库-但是新表“history_of_tasks_achievements”中没有数据!
  • 我做了一个正确的对齐 - 相同的列序列 - 在 insert 和 select 之间。
  • @Na'ilLaith - 如果您在表中看不到任何内容,则 select 语句过于严格。要查看这是否确实是问题所在,您应该检查 ExecuteNonQuery 方法的结果,该方法返回受影响的记录数。查看更新的代码,您可以在某处记录或显示输出。如果变量中确实有一个正数,那么您正在查找/更新错误的数据库/服务器或在运行时覆盖数据库。
  • @lgor ... 已成功完成,您的解决方案非常正确。但是我犯了一个愚蠢的错误,检查了不同名称的旧表-我重命名了它但没有删除它-非常感谢lgor。
【解决方案2】:

在这种情况下,您可以使用 using 语句。

// set up connection, command

using (var reader = command_get_completed_tasks_.ExecuteReader())
{
    // do the reader stuff
    reader.Close();
}

// Done

【讨论】:

  • 主要问题是我有两个执行操作,一个在另一个里面。
  • 哦,错过了,那么我会采用 Igor 的解决方案,结合这两个语句。
猜你喜欢
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
  • 2013-07-17
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
相关资源
最近更新 更多