Неожиданное поведение при проверке существующих записей в базе данных - PullRequest
0 голосов
/ 13 октября 2018

У меня есть серверная часть API ASP.NET CORE 2.1 с интерфейсом Ember (созданным в 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 голосов
/ 13 октября 2018

Я знаю, что это должно быть размещено в комментариях, но у меня не было такой хорошей репутации, чтобы подвести итоги по вашим чекам.

Вы можете изменить свой чек на

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" });
}
0 голосов
/ 13 октября 2018

Ваш код относится к регистрации пользователя, а условие if с context.Users.Where(u => u.Username.Equals((string) value, StringComparison.OrdinalIgnoreCase)).Count() > 0 проверяет, присутствует ли уже имя пользователя.

Если оно присутствует, создание второго создаст дубликат, следовательно, сообщение об ошибке«Имя пользователя уже занято».

Если счетчик равен 0, это просто означает, что имя еще не занято и может использоваться, и проверка прошла успешно.

Теперь вы проверите для > 1, это означает, что вы охотно разрешите один дубликат

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...