【问题标题】:checking user name or user email already exists检查用户名或用户电子邮件是否已存在
【发布时间】:2014-09-12 20:50:36
【问题描述】:

我在一个简单的注册页面中工作,用户无法输入相同的用户名或电子邮件,我制作了一个阻止用户输入用户名的代码并且它有效,但是当我试图阻止用户输入时相同的用户名或电子邮件它不起作用。

我的问题是,“如何添加另一个条件,使用户无法输入已经存在的电子邮件?”

我尝试在这段代码中这样做,但没有成功:

protected void Button_Click(object sender, EventArgs e)
{
  SqlConnection con = new SqlConnection( ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString );
  SqlCommand cmd1 = new SqlCommand("select 1 from Table where Name =@UserName", con);
  SqlCommand cmd2 = new SqlCommand("select 1 from Table where Email=@UserEmail", con);

  con.Open();
  cmd1.Parameters.AddWithValue("@UserName", Name_id.Text);
  cmd2.Parameters.AddWithValue("@UserEmail", Email_id.Text); 

  using (var dr1 = cmd1.ExecuteReader())
  {
    if (dr1.HasRows)
    {
      Label1.Text = "user name already exists";
    }
    using (var dr2 = cmd2.ExecuteReader())
    {
      if (dr2.HasRows)
      {
        Label1.Text = "email already exists";
      }
      else
      {
        dr1.Close();
        dr2.Close();
        //add new users
        con.Close();
      }
    }
  }  
}

但我收到此错误:

已经有一个打开的 DataReader 与此命令关联,必须先关闭。

【问题讨论】:

  • 在执行cmd2之前关闭你的第一个using块,你也可以使用ExecuteScalar获取第一行的第一列而不是使用ExecuteReader
  • 但插入新用户代码应该在两者中使用
  • 没有INSERT语句(SQL) ?? , 反正为INSERT执行单独的语句
  • 我有一个插入代码,但我放了(//添加新用户)注释,因为我不希望代码很长。
  • 与您的直接问题无关,但它可以编译吗?在您的 else 语句中,您指的是两个似乎未定义的变量:drconn

标签: c# asp.net


【解决方案1】:

就像我在评论中所说,你的设计很糟糕!

首先你应该有数据访问层。这应该是大型解决方案中的项目,但在您的情况下,您可以像新目录一样放置它。在此目录中创建 SqlManager 类,代码如下:

public class SqlManager
{

    public static string ConnectionString
    {
        get
        {
            return ConfigurationManager.ConnectionStrings["DevConnString"].ConnectionString;
        }
    }

    public static SqlConnection GetSqlConnection(SqlCommand cmd)
    {
        if (cmd.Connection == null)
        {
            SqlConnection conn = new SqlConnection(ConnectionString);

            conn.Open();

            cmd.Connection = conn;

            return conn;
        }

        return cmd.Connection; 
    }

    public static int ExecuteNonQuery(SqlCommand cmd)
    {
        SqlConnection conn = GetSqlConnection(cmd);

        try
        {
            return cmd.ExecuteNonQuery();
        }
        catch
        {
            throw;
        }
        finally
        {
            conn.Close();
        }
    }

    public static object ExecuteScalar(SqlCommand cmd)
    {

        SqlConnection conn = GetSqlConnection(cmd);

        try
        {
            return cmd.ExecuteScalar();
        }
        catch
        {
            throw;
        }
        finally
        {
            conn.Close();
        }
    }

    public static DataSet GetDataSet(SqlCommand cmd)
    {
        return GetDataSet(cmd, "Table");
    }

    public static DataSet GetDataSet(SqlCommand cmd, string defaultTable)
    {
        SqlConnection conn = GetSqlConnection(cmd);

        try
        {
            DataSet resultDst = new DataSet();

            using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
            {
                adapter.Fill(resultDst, defaultTable);
            }

            return resultDst;
        }
        catch
        {
            throw;
        }
        finally
        {
            conn.Close();
        }
    }


    public static DataRow GetDataRow(SqlCommand cmd)
    {
        return GetDataRow(cmd, "Table");
    }

    public static DataRow GetDataRow(SqlCommand cmd, string defaultTable)
    {
        SqlConnection conn = GetSqlConnection(cmd);

        try
        {
            DataSet resultDst = new DataSet();

            using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
            {
                adapter.Fill(resultDst, defaultTable);
            }

            if (resultDst.Tables.Count > 0 && resultDst.Tables[0].Rows.Count > 0)
            {
                return resultDst.Tables[0].Rows[0];
            }
            else
            {
                return null;
            }
        }
        catch
        {
            throw;
        }
        finally
        {
            conn.Close();
        }
    }
}

之后,您应该拥有业务对象层。更大的解决方案是您的案例目录中的项目。如果您在 TaxesEdit.aspx 页面中,则应在 BO(业务对象)中添加 Tax.cs 类。

类的方法示例,用于您的第一个按钮:

public DataSet GetTaxesByUserName(string userName)
{
     SqlCommand cmd = new SqlCommand(@"

        select 1 from Table where Name =@UserName");

      cmd.Parameters.AddWithValue("@UserName", userName);

      return DA.SqlManager.GetDataSet(cmd);
}

您在数据集中获取所有需要的数据。之后,您进行诸如 taxDst.Tables[0].Rows.Count > 0(或 == 0)之类的检查

对于插入你可以有这样的方法:

    public virtual void Insert(params object[] colValues)
    {
        if (colValues == null || colValues.Length % 2 != 0)
            throw new ArgumentException("Invalid column values passed in. Expects pairs (ColumnName, ColumnValue).");

        SqlCommand cmd = new SqlCommand("INSERT INTO " + TableName + " ( {0} ) VALUES ( {1} )");

        string insertCols = string.Empty;
        string insertParams = string.Empty;

        for (int i = 0; i < colValues.Length; i += 2)
        {
            string separator = ", ";
            if (i == colValues.Length - 2)
                separator = "";

            string param = "@P" + i;

            insertCols += colValues[i] + separator;
            insertParams += param + separator;

            cmd.Parameters.AddWithValue(param, colValues[i + 1]);
        }

        cmd.CommandText = string.Format(cmd.CommandText, insertCols, insertParams);

        DA.SqlManager.ExecuteNonQuery(cmd);
    }

为此,您需要在当前 BO 类中拥有属性 TableName。

在这种情况下,这种方法可以在任何地方使用,您只需要一行代码来调用它们,不会发生像您这样的问题。

【讨论】:

    【解决方案2】:

    您在 First 内部打开了另一个 DataReader,这就是导致问题的原因。在这里我重新安排了你的代码

    SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
    SqlCommand cmd1 = new SqlCommand("select 1 from Table where Name =@UserName", con),
    cmd2 = new SqlCommand("select 1 from Table where Email=@UserEmail", con);
    
    con.Open();
    cmd1.Parameters.AddWithValue("@UserName", Name_id.Text);
    cmd2.Parameters.AddWithValue("@UserEmail", Email_id.Text);
    
    bool userExists = false, mailExists = false;
    
    using (var dr1 = cmd1.ExecuteReader())
         if (userExists = dr1.HasRows) Label1.Text = "user name already exists";
    
    using (var dr2 = cmd2.ExecuteReader())
         if (mailExists = dr2.HasRows) Label1.Text = "email already exists";
    
    if (!(userExists || mailExists)) {
         // can add User
    }
    

    【讨论】:

    • 简洁明了,尽管在条件语句中进行赋值对于初学者来说可能有点难以调试... :)
    • 我打算投票,但我的声誉还不够。
    【解决方案3】:

    您需要先关闭一个数据读取器,然后再打开另一个数据读取器。虽然这不是我的做法,但您可以通过在每个IF 之后关闭数据读取器来处理运行时错误:

    using (var dr1 = cmd1.ExecuteReader())
    {
        if (dr1.HasRows)
        {
            string Text = "user name already exists";
        }
        dr1.Close();
    }
    
    using (var dr2 = cmd2.ExecuteReader())
    {
        if (dr2.HasRows)
        {
            string ext = "email already exists";
        }
    
        else
        {
            //add new users
        }
        dr2.Close();
    }
    con.Close();
    

    【讨论】:

      【解决方案4】:

      这可能会奏效,尽管我会做一些不同的事情......

      protected void Button_Click(object sender, EventArgs e)
      {
          bool inputIsValid = true;
          var con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
          var userNameCmd = new SqlCommand("SELECT 1 FROM Table WHERE Name = @UserName", con);
          var emailCmd = new SqlCommand("SELECT 1 FROM Table WHERE Email = @UserEmail", con);
      
          con.Open();
          userNameCmd.Parameters.AddWithValue("@UserName", Name_id.Text);
          emailCmd.Parameters.AddWithValue("@UserEmail", Email_id.Text);
      
          using (var userNameReader = userNameCmd.ExecuteReader())
          {
              if (userNameReader.HasRows)
              {
                  inputIsValid = false;
                  Label1.Text = "User name already exists";
              }
          }
          using (var emailReader = emailCmd.ExecuteReader())
          {
              if (emailReader.HasRows)
              {
                  inputIsValid = false;
                  Label1.Text = "Email address already exists";
              }
          }
      
          if (inputIsValid)
          {
              // Insert code goes here
          }
          con.Close();
      }
      

      【讨论】:

      • @Hbk Hhh - 好吧,这与您提出的问题不同,并且您的示例不包含任何插入代码。您可能希望使用方法顶部的bool inputIsValid = true; 跟踪是否有任何错误。然后在每个 if (reader.HasRows) 块内将其设置为 false。最后,在关闭连接之前,可以有一个block:if (inputIsValid) { &lt;InsertRecordCodeHere&gt; }
      【解决方案5】:

      你为什么不做这样的事情:

      [Flags]
      public enum ValidationStatus
      {
        Valid         = 0 ,
        UserNameInUse = 1 ,
        EmailInUse    = 2 ,
      }
      public ValidationStatus ValidateUser( string userName , string emailAddr )
      {
        ValidationStatus status ;
        string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString ;
      
        using ( SqlConnection con = new SqlConnection( connectionString ) )
        using ( SqlCommand    cmd = con.CreateCommand() )
        {
          cmd.CommandText + @"
            select status = coalesce( ( select 1 from dbo.myTable t where t.UserName  = @UserName  ) , 0 )
                          + coalesce( ( select 2 from dbo.myTable t where t.UserEmail = @UserEmail ) , 0 )
             " ;
                  cmd.Parameters.AddWithValue( "@UserName"  , userName  ) ;
                  cmd.Parameters.AddWithValue( "@emailAddr" , emailAddr ) ;
      
          int value = (int) cmd.ExecuteScalar() ;
          status = (ValidationStatus) value ;
      
        }
      
        return status ;
      }
      

      除此之外,为了这样的事情两次访问数据库是愚蠢的。这更清楚地表达了意图。

      然后你可以在你的按钮点击处理程序中使用它,像这样:

      protected void Button_Click( object sender , EventArgs e )
      {
        string           userName  = Name_id.Text ;
        string           emailAddr = Email_id.Text ;
        ValidationStatus status    = ValidateUser( userName , emailAddr ) ;
      
        switch ( status )
        {
        case ValidationStatus.Valid         :
          Label1.Text = "" ;
          break ;
        case ValidationStatus.EmailInUse    :
          Label1.Text = "Email address in use" ;
          break ;
        case ValidationStatus.UserNameInUse :
          Label1.Text = "User name in use" ;
          break ;
        case ValidationStatus.EmailInUse|ValidationStatus.UserNameInUse:
          Label1.Text = "Both user name and email address in use." ;
          break ;
        default :
          throw new InvalidOperationException() ;
        }
      
        if ( status == ValidationStatus.Valid )
        {
          CreateNewUser() ;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-28
        • 2011-12-02
        • 2018-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多