在 C# 中与此命令错误关联的打开数据读取器
An open datareader associated with this command error in C#
我想构建一个简单的循环来检查来自 SQL 服务器的传入数据,将其与文本字段进行比较,如果没有重复则执行非查询。
我写了这段代码:
try
{
bool exists = false;
conn = new SqlConnection(DBConnectionString);
SqlCommand check_user = new SqlCommand("SELECT usrEmail FROM tblUsers", conn);
SqlCommand add_user = new SqlCommand("INSERT INTO tblUsers (usrEmail, usrPassword, usrRealname, usrIsowner) VALUES (@email, @pass, @name, @owner)", conn);
// (I have removed all the paramaters from this code as they are working and irrelevant)
conn.Open();
SqlDataReader check = check_user.ExecuteReader();
while (check.Read())
{
if (Convert.ToString(check[0]) == UserEmail.Text)
{
MessageBox.Show("The email you entered already exists in the system.");
exists = true;
break;
}
}
if (exists == false)
{
add_user.ExecuteNonQuery();
}
else
{
return;
}
}
catch (Exception ex)
{
MessageBox.Show("There was a problem uploading data to the database. Please review the seller's details and try again. " + ex.Message);
return;
}
finally
{
conn.Close();
}
我使用了断点并看到代码运行 while 循环很好,但是当它到达 ExecuteNonQuery 命令时,它 returns 一条错误消息:
there is already an open datareader associated with this command which
must be closed first
我尝试使用 check.Close();
命令,但当我这样做时,由于无法理解的原因,它突然卡在重复的电子邮件错误消息中。
此外,我尝试了一个修复程序,其中数据实际上被发送到数据库(我在 SQL Server Management Studio 中看到它),但仍然给出错误消息......这更奇怪,因为非查询命令是此函数中的最后一个。如果成功了,为什么会成功?
我在网站上搜索了答案,但最常见的答案是 MARS(我不知道那是什么)或数据集,我不想在这种情况下使用它们。
这里有简单的解决方法吗?我是否遗漏了代码中的某些内容?
最简单的出路是:
using(SqlDataReader check = check_user.ExecuteReader())
{
while (check.Read())
{
if (Convert.ToString(check[0]) == UserEmail.Text)
{
MessageBox.Show("The email you entered already exists in the system.");
exists = true;
break;
}
}
}
也就是说,这段代码存在一些严重的问题。
首先,您真的不想阅读 所有 用户只是为了检查电子邮件地址是否已被占用。 select count(*) from tblUsers where usrEmail = @email
很好...
...或不,因为存在竞争条件的可能性。您应该做的是在 usrEmail
列和 insert into tblUsers
上添加一个唯一约束,捕获违规。或者,如果您愿意,可以使用 merge
。
接下来,您真的不希望到处都是数据访问代码。至少将其分解为单独的 classes/methods。
我想构建一个简单的循环来检查来自 SQL 服务器的传入数据,将其与文本字段进行比较,如果没有重复则执行非查询。
我写了这段代码:
try
{
bool exists = false;
conn = new SqlConnection(DBConnectionString);
SqlCommand check_user = new SqlCommand("SELECT usrEmail FROM tblUsers", conn);
SqlCommand add_user = new SqlCommand("INSERT INTO tblUsers (usrEmail, usrPassword, usrRealname, usrIsowner) VALUES (@email, @pass, @name, @owner)", conn);
// (I have removed all the paramaters from this code as they are working and irrelevant)
conn.Open();
SqlDataReader check = check_user.ExecuteReader();
while (check.Read())
{
if (Convert.ToString(check[0]) == UserEmail.Text)
{
MessageBox.Show("The email you entered already exists in the system.");
exists = true;
break;
}
}
if (exists == false)
{
add_user.ExecuteNonQuery();
}
else
{
return;
}
}
catch (Exception ex)
{
MessageBox.Show("There was a problem uploading data to the database. Please review the seller's details and try again. " + ex.Message);
return;
}
finally
{
conn.Close();
}
我使用了断点并看到代码运行 while 循环很好,但是当它到达 ExecuteNonQuery 命令时,它 returns 一条错误消息:
there is already an open datareader associated with this command which must be closed first
我尝试使用 check.Close();
命令,但当我这样做时,由于无法理解的原因,它突然卡在重复的电子邮件错误消息中。
此外,我尝试了一个修复程序,其中数据实际上被发送到数据库(我在 SQL Server Management Studio 中看到它),但仍然给出错误消息......这更奇怪,因为非查询命令是此函数中的最后一个。如果成功了,为什么会成功?
我在网站上搜索了答案,但最常见的答案是 MARS(我不知道那是什么)或数据集,我不想在这种情况下使用它们。
这里有简单的解决方法吗?我是否遗漏了代码中的某些内容?
最简单的出路是:
using(SqlDataReader check = check_user.ExecuteReader())
{
while (check.Read())
{
if (Convert.ToString(check[0]) == UserEmail.Text)
{
MessageBox.Show("The email you entered already exists in the system.");
exists = true;
break;
}
}
}
也就是说,这段代码存在一些严重的问题。
首先,您真的不想阅读 所有 用户只是为了检查电子邮件地址是否已被占用。 select count(*) from tblUsers where usrEmail = @email
很好...
...或不,因为存在竞争条件的可能性。您应该做的是在 usrEmail
列和 insert into tblUsers
上添加一个唯一约束,捕获违规。或者,如果您愿意,可以使用 merge
。
接下来,您真的不希望到处都是数据访问代码。至少将其分解为单独的 classes/methods。