我目前在单个方法中遇到多个SqlDataReader
和命令的问题。此方法应删除客户及其相关地址,网络,ipaddresses ......
当我执行代码时,出现错误
已经有一个与此命令关联的打开DataReader,必须先关闭
所以我用Google搜索了一下,然后读了
using(SqlDataReader....)
并将MultipleActiveResultSets=True
添加到连接字符串应该有帮助。
我正在使用SQL Server 2014,我听说SQL Server 2005存在问题,所以这不应该是个问题。
但它仍然不起作用......
抛出异常
var addressId = (int)command.ExecuteScalar();
连接字符串:
Data Source=.\\DATABASE;Initial Catalog=customer;Persist Security Info=True;MultipleActiveResultSets=True;User ID=sa;Password=xxxxxxxx!
代码:
public static Boolean ExecuteDeleteCutomer(string customerId) {
using (SqlConnection connection = new SqlConnection(new DatabaseConnection().ConnectionString)) {
connection.Open();
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;
SqlDataReader locationReader;
SqlDataReader networkReader;
SqlDataReader ipaddressReader;
// Start a local transaction to delete a customer and related table entries.
transaction = connection.BeginTransaction("StartTransaction DeleteCustomer");
// Must assign both transaction object and connection
// to Command object for a pending local transaction
command.Connection = connection;
command.Transaction = transaction;
try {
//First get the locations of selected customer
command.Parameters.AddWithValue("@customerId", customerId);
command.CommandText =
"SELECT l_id from location where c_id = @customerId";
locationReader = command.ExecuteReader();
using (locationReader) { //save location ids in a reader
while (locationReader.Read()) {
var locationID = locationReader.NextResult();
command.Parameters.AddWithValue("@locationId", locationID);
command.CommandText =
"SELECT a_id from address where l_location = @locationId";
var addressId = (int)command.ExecuteScalar(); // get address ID to delete later
command.Parameters.AddWithValue("@addressId", addressId);
command.CommandText = "SELECT n_id from network where n_location = @locationId";
using (networkReader = command.ExecuteReader()) { // save networks in a reader;
while (networkReader.Read()) {
var networkId = networkReader.NextResult();
command.Parameters.AddWithValue("@networkId", networkId);
command.CommandText = "SELECT ip_id from ipaddress where n_id = @networkId";
using (ipaddressReader = command.ExecuteReader()) { // get ipaddressId ID to delete later
while (ipaddressReader.Read()) {
var ipaddressId = ipaddressReader.NextResult();
command.Parameters.AddWithValue("@ipId", ipaddressId);
command.CommandText = "Delete from ipaddress where ip_id = @ipId; ";
command.ExecuteScalar();
}
}
command.CommandText = "Delete from network where n_id = @networkId; ";
command.ExecuteScalar();
}
}
command.CommandText = "Delete from location where l_id = @locationID; ";
command.ExecuteScalar();
}
}
command.CommandText = "Delete from customer where c_id = @customerId; ";
command.ExecuteScalar();
// Attempt to commit the transaction.
transaction.Commit();
return true;
}
catch (Exception ex) {
Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
Console.WriteLine(" Message: {0}", ex.Message);
// Attempt to roll back the transaction.
try {
transaction.Rollback();
}
catch (Exception ex2) {
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
Console.WriteLine(" Message: {0}", ex2.Message);
}
return false;
}
}
}
谢谢!
答案 0 :(得分:1)
当错误消息显示时,您已经与该DataReader
对象关联了一个打开的Command
。
您需要为要执行的每个(嵌套)命令创建一个新的SqlCommand
对象。
SqlCommand locationCommand = connection.CreateCommand();
SqlCommand networkCommand = connection.CreateCommand();
SqlCommand ipAddrCommand = connection.CreateCommand();
根据需要为每个命令对象分配CommandText
,然后您可以在每个命令对象上调用ExecuteReader
并根据需要进行处理。
答案 1 :(得分:0)
对外部和内部命令使用不同的命令实例;基本上是这样的:
var innerCommand = ...
innerCommand.CommandText = "Delete from ipaddress where ip_id = @ipId; ";
var ipId = innerCommand.Parameters.Add(...);
while (ipaddressReader.Read()) {
ipId.Value = ...
innerCommand.ExecuteNonQuery();
}
(每个命令类似)
基本上,每个命令实例应该一次只执行一次,无论它们是否共享连接。