我正在一个简单的注册页面中,用户无法输入相同的用户名或电子邮件,我制作了一个代码,阻止用户输入用户名,但是当我试图阻止用户进行调用时相同的用户名或电子邮件,它不起作用。
我的问题是,“如何添加用户无法输入已存在的电子邮件的其他条件?”
我尝试在此代码中执行此操作,但它不起作用:
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,必须先关闭它。
答案 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() ;
}
}