C# 检查数据库中的现有记录时出现意外行为
我有一个ASP.NET CORE 2.1 API后端和一个Ember前端(在VSCode中创建)。我正在关注来自Embercasts的在线视频教程,以便新用户注册。检查重复用户的逻辑工作不正常:C# 检查数据库中的现有记录时出现意外行为,c#,linq,asp.net-core,visual-studio-code,ember-data,C#,Linq,Asp.net Core,Visual Studio Code,Ember Data,我有一个ASP.NET CORE 2.1 API后端和一个Ember前端(在VSCode中创建)。我正在关注来自Embercasts的在线视频教程,以便新用户注册。检查重复用户的逻辑工作不正常: if (context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 1) { return new ValidationResul
if (context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 1)
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
出于某种原因,上面的代码允许在报告重复用户之前只使用一个重复用户。换句话说,返回一个新的ValidationResult警告用户重复记录的代码没有到达。我认为这可能与一些奇怪的数组索引问题有关,其中第一条记录位于位置0。在验证了这个假设之后,我被证明是正确的。以下代码防止重复,同时仍允许创建一条记录:
if (context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 0)
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
有人知道为什么会这样吗?感谢您的帮助
LibraryApi\Model\User.cs
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using JsonApiDotNetCore.Models;
namespace LibraryApiNew.Models
{
public class User : Identifiable
{
[Attr("email"), UniqueEmail, Required(AllowEmptyStrings = false)]public string Email {get; set; }
[Attr("username"), UniqueUsername, Required(AllowEmptyStrings = false)]public string Username { get; set; }
[Attr("password"), NotMapped, Required(AllowEmptyStrings = false), Compare("PasswordConfirmation")]public string Password { get; set; }
[Attr("password-confirmation"), NotMapped, Required(AllowEmptyStrings = false)]public string PasswordConfirmation { get; set; }
public string PasswordHash { get; set; }
}
public class UniqueUsername : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var context = (AppDbContext) validationContext.GetService(typeof(AppDbContext));
if (context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 0) // Why?
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
return ValidationResult.Success;
}
}
public class UniqueEmail : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var context = (AppDbContext) validationContext.GetService(typeof(AppDbContext));
if (context.Users.Where(u => u.Email.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 0) // Why?
{
return new ValidationResult("Email is already taken", new [] { "Email" });
}
return ValidationResult.Success;
}
}
}
您的代码与用户注册相关,并且带有
context.Users.Where(u=>u.Username.Equals((string)value,StringComparison.OrdinalIgnoreCase))的if子句会检查用户名是否已经存在
如果存在,创建第二个将创建一个副本,因此错误消息“Username已被使用”
如果计数为0,则表示尚未使用该名称,可以使用该名称,验证成功
现在请检查>1
,这意味着您愿意允许一个重复的您的代码与用户注册相关,并且带有context.Users.Where(u=>u.Username.Equals((string)value,StringComparison.OrdinalIgnoreCase)).Count()>0
会检查用户名是否已经存在
如果存在,创建第二个将创建一个副本,因此错误消息“Username已被使用”
如果计数为0,则表示尚未使用该名称,可以使用该名称,验证成功
现在请您检查>1
,这意味着您愿意允许重复一次我知道这应该放在评论中,但我没有那么多的声誉,因此无法总结您的检查
你可以把支票改成
if (context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() >= 1)
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
另一个不会误导你的选择是
if (context.Users.Any(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)))
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
我知道这应该放在评论中,但我没有那么多的声誉,所以总结你的检查
你可以把支票改成
if (context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() >= 1)
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
另一个不会误导你的选择是
if (context.Users.Any(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)))
{
return new ValidationResult("Username is already taken", new [] { "Username" });
}
这里到底出了什么问题?如果使用>1
进行检查,则始终至少有2个条目?我想说第一张支票很简单incorrect@LennartStoop我想得越多,你就对了——它应该大于0。但是,我发誓,我没有疯;视频显示计数>1,培训师获得正确的行为。唯一有意义的是,在视频教程中,没有显示数据库表。因此,培训师可能在数据库中有重复的记录,甚至不知道它。Count()>0
只做一件事:它检查用户名是否已经存在。如果是,这将允许创建一个或多个副本。所以这是correct@Marco你说得对。我认为视频教程有错误。不是代码。@JWeezy,如果你能与教程作者联系并让他知道的话。我想他可能会感激的。这里到底出了什么问题?如果使用>1
进行检查,则始终至少有2个条目?我想说第一张支票很简单incorrect@LennartStoop我想得越多,你就对了——它应该大于0。但是,我发誓,我没有疯;视频显示计数>1,培训师获得正确的行为。唯一有意义的是,在视频教程中,没有显示数据库表。因此,培训师可能在数据库中有重复的记录,甚至不知道它。Count()>0
只做一件事:它检查用户名是否已经存在。如果是,这将允许创建一个或多个副本。所以这是correct@Marco你说得对。我认为视频教程有错误。不是代码。@JWeezy,如果你能与教程作者联系并让他知道的话。我想他可能会很感激。谢谢你提供第二双眼睛。进一步考虑之后,这在逻辑上是有道理的。我认为在本教程中它看起来正确的原因是,本教程中存在一个错误,其中一条重复记录已经存在,培训师甚至没有意识到。如果您使用的是SQL server,默认排序规则是CI(不区分大小写),因此您甚至可能不需要OrdinalIgnoreCase
。其次,由于您只是在寻找任何记录,因此,COUNTHER()是低效的,而是考虑一下。谢谢您提供了第二组眼睛。进一步考虑之后,这在逻辑上是有道理的。我认为在本教程中它看起来正确的原因是,本教程中存在一个错误,其中一条重复记录已经存在,培训师甚至没有意识到。如果您使用的是SQL server,默认排序规则是CI(不区分大小写),因此您甚至可能不需要OrdinalIgnoreCase
。其次,由于您只是在寻找任何记录,因此COUNTHER()是低效的,而应考虑。