C# 已经有一个开放的DataReader

C# 已经有一个开放的DataReader,c#,asp.net,C#,Asp.net,我有新用户的注册表: 然后,它还有一个按钮: 单击“注册”按钮时,我设置命令以检查电子邮件是否已经存在 它确实会检查这些值,并且能够在调试过程中找到这些值 但是一个错误是这样说的 已存在与此命令关联的打开的DataReader,必须先关闭该命令 以下是我的ASP.NET标记: <div id="success" runat="server" class="alert alert-success" visible="false"> Account registr

我有新用户的注册表:

然后,它还有一个按钮:

单击“注册”按钮时,我设置命令以检查电子邮件是否已经存在

它确实会检查这些值,并且能够在调试过程中找到这些值

但是一个错误是这样说的

已存在与此命令关联的打开的DataReader,必须先关闭该命令

以下是我的ASP.NET标记:

<div id="success" runat="server" class="alert alert-success" visible="false">
            Account registration success!
            <br />
            Account sent for approval. Thank you.
</div>

<div id="emailavail" runat="server" class="alert alert-success" visible="false">
            Email is Available.
</div>

<div id="error" runat="server" class="alert alert-danger" visible="false">
            Email is already in use
            <br />
            Please choose another email / Login if already registered
</div>

<div class="form-group">
        <br />
            <label class="control-label col-lg-4">User Type</label>
            <div class="col-lg-8">
                <asp:Label ID="UserType" runat="server" class="form-control" text="Customer" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">Email</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtEmail" runat="server" class="form-control" type="email" 
                    MaxLength="80" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">Password</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtPassword" runat="server" class="form-control" TextMode="Password" MaxLength="20" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">First Name</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtFN" runat="server" class="form-control" MaxLength="80" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">Last Name</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtLN" runat="server" class="form-control" MaxLength="50" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">Company Name</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtCName" runat="server" class="form-control" MaxLength="50" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">Street</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtStreet" runat="server" class="form-control" MaxLength="50" required />
            </div>
</div>

<div class="form-group">
            <label class="control-label col-lg-4">Municipality</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtMunicipality" runat="server" class="form-control" MaxLength="100" required />
            </div>
</div>

        <div class="form-group">
            <label class="control-label col-lg-4">City</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtCity" runat="server" class="form-control" MaxLength="50" required />
            </div>
        </div>

        <div class="form-group">
            <label class="control-label col-lg-4">Company Phone</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtCPhone" runat="server" class="form-control" MaxLength="12" type="number" required />
            </div>
        </div>

        <div class="form-group">
            <label class="control-label col-lg-4">Mobile</label>
            <div class="col-lg-8">
                <asp:TextBox ID="txtMobile" runat="server" class="form-control" MaxLength="12" type="number" required />
            </div>
        </div>
    </div>
    <div class="col-lg-10">
        <span class="pull-right">
        <asp:Button ID="btnCancel" runat="server" class="btn" style="color:White" text="Cancel" PostBackUrl="~/Default.aspx" BackColor="Black" />
            <asp:Button ID="btnRegister" runat="server" class="btn btn-success" 
            Text="Register" style="color:White" onclick="btnRegister_Click" />

        </span>
    </div>
我确实试过:

删除我的SelectedIndex更改了标签名称,因为它确实再次选择了来自用户的电子邮件。 我试着把控球移近,因为我所研究的是它在那里起了作用。 请帮我把时间花在这上面

提前谢谢你


我还是c的新手,让我们再次阅读您的异常消息:

已存在与此命令关联的打开的DataReader,该命令 必须先关闭

你有几个选择

您可以在con后手动处理读卡器。关闭行,如

dr.Dispose();
或者,您可以使用using语句自动处理我推荐的读取器

using(SqlDataReader dr = cmd.ExecuteReader())
{
   ...
} // <-- On this line your dr will disposed

也意识到:

虽然索纳·哥努尔已经给出了一个解决这种情况的方案,但我想给出另一种观点,让你的整个问题变得毫无意义。答案也太长,无法发表评论

你在这里所做的对学习是有益的,但你在这里重新发明轮子。三种主要的基于web的语言PHP、Java和.NET都有灵活且经验证的用户管理系统

鉴于这是ASP.NET,我强烈建议您使用默认的ASP.NET成员资格提供程序。成员资格提供程序抽象了所有用户管理,因此您无需手动配置SQL命令。例如,我可以在您的代码中看到两个明显的缺陷:

你没有把你的密码放入盐中; 您正在SHA中使用过时的哈希算法。它应该是bcrypt、Scrypt、PBKDF2或新的Argon2函数。
如果您使用ASP.NET成员资格提供程序,这两个问题都会得到解决。

这在许多级别上都是一团糟

哈斯罗博士是错的 它跳转到另一个 别开玩笑了,你还开着一个数据阅读器 然后重复cmd.Connection=con; 哈斯罗博士是真的 你关闭连接 然后它跳过另一个 然后尝试cmd.ExecuteNonQuery;在已关闭的连接上,一个select语句甚至不是有效的ExecuteOnQuery 首先,DataReader没有任何用途 只需进行计数,从注册中选择计数*,其中Email=@Email 检查计数,如果为0,则执行插入 然后关闭连接

    cmd.CommandText = "SELECT count(*) FROM Registration WHERE Email=@Email";
    cmd.Parameters.AddWithValue("@Email", txtEmail.Text);
    if ((Int32)cmd.ExecuteScalar() > 0)
    {
        error.Visible = true;
        emailavail.Visible = false;
        success.Visible = false;
    }
    else
    {
        cmd.CommandText = "INSERT INTO Users VALUES (@TypeID, @Email, @Password, " +
            "@FirstName, @LastName, @CompanyName, @Street, @Municipality, @City, " +
            "@CompanyPhone, @Mobile, @Status, @DateAdded, @DateModified)";
        cmd.Parameters.AddWithValue("@TypeID", "2");
        cmd.Parameters.AddWithValue("@Email", txtEmail.Text);
        cmd.Parameters.AddWithValue("@Password", Helper.CreateSHAHash(txtPassword.Text));
        cmd.Parameters.AddWithValue("@FirstName", txtFN.Text);
        cmd.Parameters.AddWithValue("@LastName", txtLN.Text);
        cmd.Parameters.AddWithValue("@CompanyName", txtCName.Text);
        cmd.Parameters.AddWithValue("@Street", txtStreet.Text);
        cmd.Parameters.AddWithValue("@Municipality", txtMunicipality.Text);
        cmd.Parameters.AddWithValue("@City", txtCity.Text);
        cmd.Parameters.AddWithValue("@CompanyPhone", txtCPhone.Text);
        cmd.Parameters.AddWithValue("@Mobile", txtMobile.Text);
        cmd.Parameters.AddWithValue("@Status", "Pending");
        cmd.Parameters.AddWithValue("@DateAdded", DateTime.Now);
        cmd.Parameters.AddWithValue("@DateModified", DBNull.Value);
        cmd.ExecuteNonQuery();
    }
    con.Close();
也可以做到这一点,在一次旅行,但我不确定这将与参数的工作

IF NOT EXISTS(SELECT ...); 
 BEGIN 
  INSERT INTO ...;
 END;

谢谢你的帮助和体贴@Soner@Frisbee

我所做的是把它们分开,因为我已经想到了我得到的答案,当我回到同一个场景时,我更容易理解

 protected void btnRegister_Click(object sender, EventArgs e)
    {
        con.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = con;

        cmd.CommandText = "SELECT Email FROM Users WHERE Email=@Email";
        cmd.Parameters.AddWithValue("@Email", txtEmail.Text);
        SqlDataReader dr = cmd.ExecuteReader();

        if (dr.HasRows)
        {
                error.Visible = true;
                emailavail.Visible = false;
                success.Visible = false;
                con.Close(); 
        }

        else
        {

            success.Visible = false;
            con.Close();
            RegisterUser();
        }



    }

    void RegisterUser()
    {
        con.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = con;
        cmd.CommandText = "INSERT INTO Users VALUES (@TypeID, @Email, @Password, " +
            "@FirstName, @LastName, @CompanyName, @Street, @Municipality, @City, @CompanyPhone, @Mobile, " +
            "@Status, @DateAdded, @DateModified)";
        cmd.Parameters.AddWithValue("@TypeID", "2");
        cmd.Parameters.AddWithValue("@Email", txtEmail.Text);
        cmd.Parameters.AddWithValue("@Password", Helper.CreateSHAHash(txtPassword.Text));
        cmd.Parameters.AddWithValue("@FirstName", txtFN.Text);
        cmd.Parameters.AddWithValue("@LastName", txtLN.Text);
        cmd.Parameters.AddWithValue("@CompanyName", txtCName.Text);
        cmd.Parameters.AddWithValue("@Street", txtStreet.Text);
        cmd.Parameters.AddWithValue("@Municipality", txtMunicipality.Text);
        cmd.Parameters.AddWithValue("@City", txtCity.Text);
        cmd.Parameters.AddWithValue("@CompanyPhone", txtCPhone.Text);
        cmd.Parameters.AddWithValue("@Mobile", txtMobile.Text);
        cmd.Parameters.AddWithValue("@Status", "Pending");
        cmd.Parameters.AddWithValue("@DateAdded", DateTime.Now);
        cmd.Parameters.AddWithValue("@DateModified", DBNull.Value);
        cmd.ExecuteNonQuery();
        con.Close();

    }

再次感谢各位

您有一个open reader,但您尝试发送新命令。始终关闭第一个连接,然后打开新的连接进行插入。或者,使用IF NOT EXISTS语法在一个SQL命令中检查和插入操作。您需要启用在哪里关闭它?我想在电子邮件可用时在else命令insert中执行它@PaulineGailMallariChan的可能副本为什么不试试看?它是参数化的,因此不易受到SQL注入的攻击exploit@Frisbee不过,我的其他观点仍然站得住脚。他没有正确地使用散列来保存密码,他也没有使用散列。这两项都由成员资格提供者处理。会员资格提供商还提供了其他好处。我没有对其他几点发表评论。为什么不纠正你的答案呢?@飞盘完成了。我时间紧迫,没有一个好办法来编辑答案。我不确定以这种方式使用的参数是否足以完全阻止SQLi。我在这方面找到的所有指南都提到使用SqlDbType和max-length。我准备冒险,更多地学习c和asp.net。谢谢你的建议!非常感谢。我做了,但我只是决定把它们分开。
IF NOT EXISTS(SELECT ...); 
 BEGIN 
  INSERT INTO ...;
 END;
 protected void btnRegister_Click(object sender, EventArgs e)
    {
        con.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = con;

        cmd.CommandText = "SELECT Email FROM Users WHERE Email=@Email";
        cmd.Parameters.AddWithValue("@Email", txtEmail.Text);
        SqlDataReader dr = cmd.ExecuteReader();

        if (dr.HasRows)
        {
                error.Visible = true;
                emailavail.Visible = false;
                success.Visible = false;
                con.Close(); 
        }

        else
        {

            success.Visible = false;
            con.Close();
            RegisterUser();
        }



    }

    void RegisterUser()
    {
        con.Open();
        SqlCommand cmd = new SqlCommand();
        cmd.Connection = con;
        cmd.CommandText = "INSERT INTO Users VALUES (@TypeID, @Email, @Password, " +
            "@FirstName, @LastName, @CompanyName, @Street, @Municipality, @City, @CompanyPhone, @Mobile, " +
            "@Status, @DateAdded, @DateModified)";
        cmd.Parameters.AddWithValue("@TypeID", "2");
        cmd.Parameters.AddWithValue("@Email", txtEmail.Text);
        cmd.Parameters.AddWithValue("@Password", Helper.CreateSHAHash(txtPassword.Text));
        cmd.Parameters.AddWithValue("@FirstName", txtFN.Text);
        cmd.Parameters.AddWithValue("@LastName", txtLN.Text);
        cmd.Parameters.AddWithValue("@CompanyName", txtCName.Text);
        cmd.Parameters.AddWithValue("@Street", txtStreet.Text);
        cmd.Parameters.AddWithValue("@Municipality", txtMunicipality.Text);
        cmd.Parameters.AddWithValue("@City", txtCity.Text);
        cmd.Parameters.AddWithValue("@CompanyPhone", txtCPhone.Text);
        cmd.Parameters.AddWithValue("@Mobile", txtMobile.Text);
        cmd.Parameters.AddWithValue("@Status", "Pending");
        cmd.Parameters.AddWithValue("@DateAdded", DateTime.Now);
        cmd.Parameters.AddWithValue("@DateModified", DBNull.Value);
        cmd.ExecuteNonQuery();
        con.Close();

    }