【问题标题】:Unexpected behavior when checking for existing records in the database检查数据库中现有记录时的意外行为
【发布时间】:2018-10-13 18:45:22
【问题描述】:

我有一个带有 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;
        }
    }
}

【问题讨论】:

  • 这里到底出了什么问题?如果您与>1 核对,总会有至少 2 个条目?我会说第一次检查根本不正确
  • @LennartStoop 我想得越多,你是对的——它应该大于 0。但是,我发誓,我没有疯。视频显示计数 > 1,并且培训师得到正确的行为。唯一有意义的是,在视频教程中,没有显示数据库表。所以,有可能是培训师在数据库中有重复的记录,甚至都不知道。
  • Count() >0 只做一件事:检查用户名是否已经存在。如果是,这将允许或创建一个副本。所以这是正确的
  • @Marco 你是对的。我认为视频教程有错误。不是代码。
  • @JWeezy,如果你能联系到教程作者并让他知道的话。我想他可能会感激不尽。

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


【解决方案1】:

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

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

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

现在你会检查> 1,这意味着你愿意允许一个重复

【讨论】:

  • 感谢您提供第二双眼睛。仔细想了想,这在逻辑上是有道理的。我认为它在教程中看起来正确的原因是教程中存在一个错误,其中一个重复记录已经存在并且培训师甚至没有意识到这一点。
  • 如果您使用的是 SQL Server,默认排序规则是 CI(不区分大小写),因此您甚至可能不需要 OrdinalIgnoreCase。其次,由于您只是在查找任何记录,因此 count() 效率低下,请考虑使用Any()
【解决方案2】:

我知道这应该放在 cmets 中,但我没有那么高的声誉,所以总结一下你的支票。

您可以将检查更改为

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

【讨论】:

    猜你喜欢
    • 2015-09-23
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多