using (var connection = new SqlConnection(...))
{
string sql = "SELECT * FROM tableA";
using (var command = new SqlCommand(sql,connection))
{
using (var reader = command.ExecuteReader(...))
{
//***************Sample Start
string sql2 = "INSERT into tableB(column1) VALUES('"+reader["column1"]+"')";
using (var command2 = new SqlCommand(sql2,connection))
{
...
}
//***************Sample End
}
}
}
通过使用上面的代码片段,我相信它是在C#中处理SQL的最佳实践。现在,我从tableA中检索记录列表后,对于我要插入tableB的每一行。
然而,它正在抛出异常
已经有一个与此命令关联的打开DataReader,必须先关闭
我知道这个问题可以通过创建另一个方法并从那里插入表中来解决,我想知道是否还有其他方法。感谢您的任何意见。
答案 0 :(得分:7)
您需要为插入使用不同的sql连接而不是select ...
......但我们可以做得更好。您可以将其重写为一个sql语句,如下所示:
INSERT into tableB(column1)
SELECT column1 FROM tableA
然后像这样立即运行它:
string sql = "INSERT into tableB(column1, column2) SELECT column1, @othervalue As column2 FROM tableA;";
using (var connection = new SqlConnection(...))
using (var command = new SqlCommand(sql,connection))
{
command.Paramters.Add("@othervalue", SqlDbType.NVarChar, 50).Value = "something";
connection.Open();
command.ExecuteNonQuery();
}
单个sql语句通常快得多,并且您最终也会得到更少的代码。我知道这可能是您真实查询的简化示例,但我向您保证:您可以将其全部重新编写为一个语句。
此外,有时您仍希望在插入或更新后进行一些客户端处理或显示新记录。在这种情况下,您仍然只需要向数据库发送一个调用,但在该单个调用中将有两个单独的sql语句。最终的代码看起来更像是这样:
string sql = "INSERT into tableB(column1, column2) SELECT column1, @othervalue As column2 FROM tableA;"
sql += "SELECT columnn1, @othervalue As column2 FROM tableA;";
using (var connection = new SqlConnection(...))
using (var command = new SqlCommand(sql,connection))
{
command.Paramters.Add("@othervalue", SqlDbType.NVarChar, 50).Value = "something";
connection.Open();
using (var reader = command.ExecuteReader() )
{
while (reader.Read() )
{
//...
}
}
}
因为其他人提出了MARS(多个活动结果集),我会补充一点,虽然这可行,但我使用它进行插入/更新的结果好坏参半。当共享连接的所有内容只进行读取时,它似乎效果最好。
答案 1 :(得分:4)
正如评论中所提到的,您需要为插入提供单独的数据库连接。每个连接一次可以处理一个活动语句,这里有两个 - 一个用于SELECT
,一个用于INSERT
。
试试这个例子:
string srcqry = "SELECT * FROM tableA";
using (SqlConnection srccon = new SqlConnection(ConnectionString))
using (SqlCommand srccmd = new SqlCommand(srcqry, srccon))
{
srccon.Open();
using (SqlDataReader src = srccmd.ExecuteReader())
{
string insqry = "INSERT INTO tableB(column1) VALUES(@v1)";
// create new connection and command for insert:
using (SqlConnection inscon = new SqlConnection(ConnectionString))
using (SqlCommand inscmd = new SqlCommand(insqry, inscon))
{
inscmd.Parameters.Add("@v1", System.Data.SqlDbType.NVarChar, 80);
inscon.Open();
while (src.Read())
{
inscmd.Parameters["@v1"].Value = src["column1"];
inscmd.ExecuteNonQuery();
}
}
}
}
使用参数解决了SQL Injection漏洞。您应该始终这样做,而不是从原始用户输入或从数据库中提取的数据构建查询字符串,或者......好吧,总是。如果你愿意,可以写一些辅助方法让它更容易,只要确保你这样做。
答案 2 :(得分:1)
除了一个不好的例子,为什么不简单地将查询简化为
插入TableB(column1),从TableA中选择column1