检查数据库中的现有记录时出现异常行为

时间:2018-10-13 18:45:23

标签: c# linq asp.net-core visual-studio-code ember-data

我有一个带有Ember前端的ASP.NET CORE 2.1 API后端(在VSCode中创建)。我正在关注Embercasts提供的有关新用户注册的在线视频教程。检查重复用户的逻辑无法正常工作:

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;
        }
    }
}

2 个答案:

答案 0 :(得分:4)

您的代码与用户注册有关,带有context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 0的if子句会检查用户名是否已经存在。

如果存在,则创建第二个副本将创建一个副本,因此错误消息“用户名已被占用”。

如果计数为0,则仅表示该名称尚未使用并且可以使用,并且验证成功。

现在您是否要检查> 1,也就是说,您愿意允许重复一次

答案 1 :(得分:2)

我知道应该在评论中注明此词,但我的声誉不高,因此可以总结一下您的支票。

您可以将支票更改为

if (context.Users.Any(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)))
{
     return new ValidationResult("Username is already taken", new [] { "Username" });
}

另一种可以避免误导您的支票是

{{1}}