已经有一个开放的DataReader

时间:2016-02-28 16:16:44

标签: c# asp.net

我的新用户有注册表单:

enter image description here

然后,它还有一个按钮:

enter image description here

单击按钮Register时,我设置命令以检查电子邮件是否已存在。

它会检查值并能够在调试过程中找到值。

但是发生了一个错误

  

已经有一个与此命令关联的打开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>

以下是代码隐藏:

protected void btnRegister_Click(object sender, EventArgs e)
{
    con.Open();

    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;

    cmd.CommandText = "SELECT Email FROM Registration 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
    {
        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();
}

我确实尝试过:

  1. 删除我的selectedindexchanged标签名称,因为它确实再次从用户中选择电子邮件。
  2. 我尝试移动con.close,因为正如我所研究的那样,它有一些事情要做。
  3. 请帮忙给我几个小时。

    提前谢谢!

    我还是c#

    的新手

4 个答案:

答案 0 :(得分:4)

让我们再次重新阅读您的异常消息:

  

已经与此命令相关联的打开DataReader   必须先关闭

您有几个选择。

您可以在con.Close()行之后手动处理阅读器

dr.Dispose();

或者您可以使用using语句自动处理您的阅读器(我推荐)。

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

或者您可以为SqlCommand语句创建新的INSERT对象,例如;

cmd = new SqlCommand();
cmd.Connection = con;
...

同样:There is already an open DataReader associated with this Command which must be closed first

答案 1 :(得分:4)

虽然SonerGönül已经提供了适用于这种情况的解决方案,但我想提出另一个视角,使您的整个问题没有实际意义(答案也太长,无法发表评论)。

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

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

  1. 你没有腌制密码哈希;
  2. 您在SHA中使用过时的哈希算法。它应该是bcrypt,Scrypt,PBKDF2或新的Argon2功能。
  3. 如果您使用ASP.NET成员资格提供程序,则会解决这两个问题。

答案 2 :(得分:2)

这只是搞砸了很多层次

  • dr.HasRows是假的 它会跳到其他人身上 不开玩笑你仍然打开DataReader 然后重复cmd.Connection = con;
  • dr.HasRows是真的 你关闭连接
    然后它跳过其他人 然后你尝试一个cmd.ExecuteNonQuery();在您已关闭的连接和一个甚至不是有效的ExecuteNonQuery
  • 的select语句上

首先,DataReader没有任何意图 只需计算“SELECT count(*)FROM Registration WHERE 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;

答案 3 :(得分:0)

感谢@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();

    }

再次感谢你们