List<User> 中已存在支票或昵称
Posted
技术标签:
【中文标题】List<User> 中已存在支票或昵称【英文标题】:Check or nickname already exists in List<User> 【发布时间】:2013-07-17 17:38:59 【问题描述】:我正在创建一个可以注册的 ASP 网站。
访问者选择注册的昵称必须是唯一的。
每次用户注册时,我从数据库中选择所有用户,然后我使用foreach循环检查或用户名是否已存在:
private List<User> listExistingUsers;
listExistingUsers = Database.GetUsers();
foreach (User u in listExistingUsers)
if (u.Nickname == txtNickname.text)
Error = "Username already in use.";
但是上面的代码不能正常工作。它不会检查从数据库中读取的列表中的所有项目。所以可能会有用户使用相同的用户名,这是我不想要的。
我可以做些什么来解决这个问题?我阅读了有关 LINQ 的信息,但我认为这是使用 List 检查用户名的错误方法。我认为这个用户名检查必须以另一种方式完成。
各位专家能帮帮我吗?我也可以使用 SQL 查询进行此检查,但我想在 c# 中进行。
【问题讨论】:
不检查从数据库中读取的列表中的所有项目是什么意思?哪条线从foreach
循环中跳出?你确定listExistingUsers
包含所有用户吗?
只是一个想法,但可能是案例问题。在继续解决方案之前尝试if (u.Nickname.ToLower() == txtNickname.text.ToLower())
。
【参考方案1】:
不是从数据库返回所有用户,而是将用户名传递给查询/存储过程并让后端进行检查,然后只返回一个状态标志 1/0 - 存在/不存在。
【讨论】:
你的意思是我需要做这样的事情?: public ListSELECT 1
并检查 DbNull 的结果
类似If (dbComm.ExecuteScalar("SELECT Username FROM User WHERE Username = @username") == DbNull.Value) Error = "Username already in use.";
抱歉应该是!= DbNull.Value
【参考方案2】:
if (Database.GetUsers().Select(x => x.Nickname).Contains(txtNickname.Text))
应该做你想做的事。
我已将所有内容浓缩为一行,因此我将快速解释一下;首先,我使用您的Database.GetUsers()
方法来检索用户,然后我使用 select 来投影昵称,因为这就是我们要比较的。如果它自己执行,它将导致一个带有所有昵称的IEnumerable<string>
。从那里我使用 contains 来查看该列表是否包含(我假设)已在 UI 中输入的昵称。
【讨论】:
谢谢。这是您认为最好的检查方式吗? @xVizzi 在 C# 代码中,它是。如果您实际上并不需要用户,那么您最好只在 SQL 中进行检查。另外,如果您要在其他地方使用用户,那么您应该将Database.GetUsers()
的返回值分配给该行上方的本地变量,这样您就不必重复该查询。【参考方案3】:
您可以使用Contains operator
进行检查
listExistingUsers.Select(x => x.Nickname).Contains(txtNickname.text);
链接:http://msdn.microsoft.com/fr-fr/library/bhkz42b3%28v=vs.80%29.aspx
备注:你可以使用Any
或count
(非常昂贵的最后一个解决方案)
【讨论】:
【参考方案4】:使用Any 运算符。它检查序列的任何元素是否满足某些条件。在您的情况下,用户昵称等于 textBox 中的文本:
if (Database.GetUsers().Any(u => u.Nickname == txtNickname.Text))
Error = "Username already in use.";
顺便说一句,如果您将GetUsers
更改为返回IQueryable<User>
,则将在服务器端进行检查。
【讨论】:
【参考方案5】:获取昵称列表一次
var nickNames = new List<string>();
for(int i=0;i<listExistingUsers.Count;i++)
nickNames.Add(listExistingUsers.NickName);
那么你可以简单地使用
if(nickNames.Contains(txtNickname.text))
Error = "Username already in use.";
【讨论】:
listExistingUsers 是用户列表,必须选择用户名【参考方案6】:1) 您是否验证过 Database.GetUsers() 实际上返回的是完整列表,没有 SQL 问题?
2) 你需要它不区分大小写吗?
3) 您可以使用 LINQ 进行如下查询:
if (listExistingUsers.Any(u => string.Equals(u, txtNickname.Text, StringComparison.CurrentCultureIgnoreCase)))
// Process error
【讨论】:
【参考方案7】:如果 Database.GetUsers() 返回数据库中的所有用户,那么不要使用它!想象一下,如果您已经有 1000 个用户,对于每个新用户,它将加载所有用户,您将遇到性能问题。
相反,创建一个新方法来搜索您的数据库并仅返回 一个 结果,以防它存在。 类似的东西:
private bool Database.UserExists(txtNickname.text)
//Your query to database with a where statment looking for the nickname. It could be a LINQ query, or any other way you use in your system.
//If it brings 1 result, it has to return true.
【讨论】:
【参考方案8】:我认为您的任务中最棘手的部分是正确填充数据库。
特别是:
切断尾随和结束空格 决定用户名是否区分大小写 确保在创建新用户名时您还没有昵称关于加载用户和检查:
如上所述,LINQ 是最有效的 C# 类似检查重复项 ( if (Database.GetUsers().Select(x => x.Nickname).Contains(txtNickname.Text)))
我更习惯于编写 SQL 语句而不是使用 LINQ。如果您有很多用户,SQL 将只读取选定的用户,但我不知道上面的 LINQ 语句是将所有用户拉入内存池还是仅将具有相同昵称的用户拉入内存池。
【讨论】:
以上是关于List<User> 中已存在支票或昵称的主要内容,如果未能解决你的问题,请参考以下文章
EF框架另一个 SqlParameterCollection 中已包含 SqlParameter。
ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象