我一直在尝试防止重复并输入一条重复的电子邮件或用户名(或两者都输入)时出现错误消息,我想知道我的代码有什么问题。
我已经尝试了一些解决类似问题的方法,但是它们似乎没有用。我不确定我的代码或执行此操作的其他方式是否有问题。它只是运行并执行代码,即使结果重复了,结果也会添加到数据库中。
sqlCon.Open();
string query = "SELECT COUNT(*) FROM SSUser WHERE username=@username AND password=@password AND email=@email";
SqlCommand c1 = new SqlCommand(query);
SqlCommand c = new SqlCommand("insert into SSUser values(@username, @password, @email)", sqlCon);
c.Parameters.AddWithValue("@username", register_username.Text);
c.Parameters.AddWithValue("@password", register_password.Text);
c.Parameters.AddWithValue("@email", register_mail.Text);
SqlCommand check_username = new SqlCommand("SELECT COUNT(*) FROM SSUser WHERE (username=@username) AND (email = @email)", sqlCon);
check_username.Parameters.AddWithValue("@username", register_username.Text);
check_username.Parameters.AddWithValue("@email", register_mail.Text);
int check = (int)check_username.ExecuteScalar();
if (check > 0)
{
register_error.Visible = true;
}
else
{
if (register_c.Text != register_password.Text)
{
register_error.Visible = true;
}
else
{
c.ExecuteNonQuery();
register_username.Text = "";
register_password.Text = "";
register_c.Text = "";
register_mail.Text = "";
Response.Redirect("Login.aspx");
}
}
答案 0 :(得分:0)
为防止重复,请在数据库中创建唯一的约束或索引:
alter table ssuser add constraint unq_ssuser_username unique (username);
alter table ssuser add constraint unq_ssuer_email unique (email);
任何将创建重复项的插入或更新都将返回错误。尝试insert
和update
时,您可能想捕获该错误。
答案 1 :(得分:0)
除了戈登·利诺夫(Gordon Linoff)的答案外: 在将唯一性约束添加到数据库中的适当属性之后,您应该可以捕获SqlException:
try {
c.ExecuteNonQuery();
}
catch (SqlException ex)
{
}
答案 2 :(得分:0)
请考虑为此使用数据库层;这是T-SQL
的一个工作示例,正是这样的:
create table [dbo].[SSUser] (
[UserId] bigint not null identity (0, 1)
, [UserName] nvarchar(255) not null
, [Email] nvarchar(255) not null
, [PasswordHash] varbinary(64) null
, constraint [dbo_SSUser_Pk] primary key clustered ([UserName] asc) with (data_compression = page)
);
go
create type [dbo].[ISSUser] as table (
[UserName] nvarchar(255) not null
, [Email] nvarchar(255) not null
, [PasswordHash] varbinary(64) null
, primary key clustered ([UserName] asc)
);
go
create procedure [dbo].[usp_SSUser_Insert] (
@users [dbo].[ISSUser] readonly
)
as
begin;
set nocount on;
set xact_abort on;
insert into [dbo].[SSUser] (
[UserName]
, [Email]
, [PasswordHash]
)
output [inserted].[UserId]
, [inserted].[Email]
, [inserted].[PasswordHash]
select a.[UserName]
, a.[Email]
, a.[PasswordHash]
from @users as a;
end;
以及随附的C#
代码将调用该过程并捕获任何错误:
var connectionString = "Data Source=.;Initial Catalog=Koholint;Trusted_Connection=True;";
var userName = register_username.Text;
var email = register_mail.Text;
var passwordHash = register_password.HashBytes;
try {
var tableMetadata = new[] {
new SqlMetaData("UserName", SqlDbType.NVarChar, 255),
new SqlMetaData("Email", SqlDbType.NVarChar, 255),
new SqlMetaData("PasswordHash", SqlDbType.VarBinary, 64),
};
var tableValues = new SqlDataRecord(tableMetadata);
tableValues.SetValue(0, userName);
tableValues.SetValue(1, email);
tableValues.SetValue(2, passwordHash);
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand()) {
command.CommandText = "[dbo].[usp_SSUser_Insert]";
command.CommandTimeout = 15;
command.CommandType = CommandType.StoredProcedure;
var tableParameter = new SqlParameter("users", SqlDbType.Structured);
tableParameter.TypeName = "[dbo].[ISSUser]";
tableParameter.Value = new[] { tableValues };
command.Parameters.Add(tableParameter);
connection.Open();
using (var reader = command.ExecuteReader()) {
do {
while (reader.Read()) {
Console.WriteLine(reader.GetInt64(0)); // TODO: something more useful, or maybe nothing...
}
} while (reader.NextResult());
}
}
}
catch (SqlException e) {
register_error.Visible = true;
if (e.Number == 2627) {
// special handling for primary key/unique constraint violation
}
else {
throw; // rethrow everything else
}
}
register_username.Text = "";
register_password.Text = "";
register_mail.Text = "";
Response.Redirect("Login.aspx");
为什么要麻烦这些?
第一,它确实防止重复。如果要防止在数据库中重复代码,检查客户端代码中的重复绝对没有任何意义。只需使用primary key或unique constraint阻止它们发生。
另一个主要好处是,我们至少可以保存一次数据库访问。 OP的原始代码必须查询数据库以检查重复项。这不仅在使用相同键值的并发作者面前失败,而且在时间上也很昂贵。
使用table-valued parameter以便将所有输入封装到单个“接口”中,从而可以更轻松地指定C#
和T-SQL
之间的协定。这样做还有一个好处,就是可以让我们在一个事务中插入许多不同的用户,而不用进行某种循环的调用。