检查用户名或用户电子邮件已存在

时间:2014-09-12 20:50:37

标签: c# asp.net

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

我的问题是,“如何添加用户无法输入已存在的电子邮件的其他条件?”

我尝试在此代码中执行此操作,但它不起作用:

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,必须先关闭它。

5 个答案:

答案 0 :(得分:2)

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

首先你应该拥有数据访问层。这应该是大解决方案中的项目,但在您的情况下,您可以将其设置为新目录。在这个目录中创建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。

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

答案 1 :(得分:1)

您在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
}

答案 2 :(得分:0)

这可能有用,虽然我会做一些不同的事情......

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();
}

答案 3 :(得分:0)

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

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 :(得分:0)

为什么不做这样的事情:

[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() ;
  }
}