我对此感到非常困惑。
我们提供了一个规范来构建一个应用程序,要求用户在使用该应用程序之前创建自己的帐户。
规范说用户的电子邮件应该根据他/她在我们数据库中的电子邮件进行验证。
如果该电子邮件已存在,请通知用户并让他/她选择其他电子邮件。
以下是执行所有操作的代码。
//标记:
<tr>
<td height="27" width="129"><font face="Tahoma" size="2">
<label for="txtEmail">Your Email address:</label></font></td>
<td height="27" width="244">
<asp:TextBox ID="txtEmail" CssClass="Treb10Blue" Runat="server" style="font-family: Trebuchet MS; font-size: 10pt; font-weight: bold; font-style: italic; color: #000080;"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator4" Runat="server" ErrorMessage="*" Display="Dynamic" ControlToValidate="txtEmail"></asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" ControlToValidate="txtEmail" ValidationExpression=".*@.*\..*" ErrorMessage="Email not in correct format" Display="Dynamic" Runat="server"></asp:RegularExpressionValidator>
</td>
</tr>
//然后代码隐藏
Function Fixquotes(ByVal thesqlenemy As String) As String
Fixquotes = Replace(thesqlenemy, "'", "''")
End Function
Sub btnRegister_Onclick(ByVal Src As Object, ByVal e As System.Web.UI.ImageClickEventArgs)
If Page.IsValid Then
Dim objConn As IDbConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("DBConnectionString").ConnectionString)
Dim chkUsername As IDbCommand
Dim addUser As IDbCommand
Dim strSQL1 As String
Dim strSQL2 As String
Dim strUserCount As Integer
'first, check if user already exists
Try
strSQL1 = "SELECT COUNT(*) FROM [tblLogin] WHERE [Email]='" & Fixquotes(txtEmail.Text) & "'"
strSQL2 = "INSERT INTO [tblLogin] ([Fullname], [Email], [Username], [Password],[Rights],[ModifiedDate],Precinct,PositionId,ProcessedFlag)"
strSQL2 = strSQL2 & " VALUES "
strSQL2 = strSQL2 & "('" & Fixquotes(txtFullname.Text) & "', '" & Fixquotes(txtEmail.Text) & "', '" & Fixquotes(txtUsername.Text) & "', '" & Fixquotes(txtPassword.Text) & "',2,getdate(), '" & precinctList.SelectedValue & "'," & PosisitionList.SelectedValue & ",'No')"
'Response.Write(strSQL2)
'Response.End()
objConn.Open()
chkUsername = New SqlCommand(strSQL1, objConn)
strUserCount = chkUsername.ExecuteScalar()
If strUserCount = 0 Then
addUser = New SqlCommand(strSQL2, objConn)
addUser.ExecuteNonQuery()
objConn.Close()
'Display some feedback to the user to let them know it was sent
lblMsg.ForeColor = System.Drawing.Color.Green
lblMsg.Text = "Your account has been successfully created.<br><br>Please click the Close button below to close this window and log in with your newly created username and password."
'Clear the form
txtFullname.Text = ""
txtEmail.Text = ""
Else
lblMsg.Text = "That email address already exists. Please choose another..."
lblMsg.ForeColor = Drawing.Color.Red
End If
Catch
objConn.Close()
End Try
End If
End Sub
到目前为止,在已注册的1,035名用户中,有九(9)名用户可以使用SAME电子邮件地址创建重复的帐户。
其中一位用户做了5次!
这怎么可能,如何防止进一步发生?
提前多多感谢
答案 0 :(得分:2)
您可能会非常快速地发出请求,并且在执行查询之间的时间内,该值不再是唯一的。封装事务中的所有内容会阻止这种情况,并且就实践而言,您应该考虑将其放入存储过程中。
答案 1 :(得分:1)
停止重复条目的一种方法是通过在数据库表中的UNIQUE
列上放置[Email]
约束来阻止重复数据进入数据库。
然后,至少在发生重复的INSERT
尝试时会抛出异常。
答案 2 :(得分:1)
是的,这是可能的,但5次似乎很难做到。用户双击的可能性很大,导致代码运行两次。现在,因为查询之间有一段时间来查看它是否存在以及创建它的时间,所以可以创建倍数。
要解决这个问题,有几种方法。
您可以在代码TransactionScope
中查看实施交易您可以在SQL SQL Transaction
中实现交易或者,我最喜欢的是,以一种跨行的方式编写SQL 将两个SQL语句放入1个以“IF NOT EXISTS(SELECT TOP 1 1 FROM [tblLogin] WHERE [Email] ='”&amp; Fixquotes(txtEmail.Text)&amp;“'”&amp; YourInsertSqlHere
开头的字符串中然后,当您使用ExecuteNonQuery()运行此SQL时,保留结果,如果为0,则表示它没有插入,因为它已经存在。
但首先,在您执行任何其他操作之前,通过在单击按钮时禁用按钮来修复双击问题!