无法使用 ASP .NET Core 更新 SQL 位列

Posted

技术标签:

【中文标题】无法使用 ASP .NET Core 更新 SQL 位列【英文标题】:Can't update SQL Bit column with ASP .NET Core 【发布时间】:2019-05-21 07:26:48 【问题描述】:

我有一个 ASP .NET Core Web 应用程序,当我创建项目时,身份验证是使用个人用户帐户选项自动设置的。用户帐户/角色的数据库表也是自动创建的。

我创建了自己的继承自 IdentityUser 的 ApplicationUser 类,并为 FirstName、LastName 和 LockoutReason 添加了参数。 (我也将这些字段添加到数据库表中)现在我正在尝试添加一项功能以允许某人手动锁定用户,但我似乎无法更新数据库中的 LockoutEnabled 字段。每次我这样做时,它都会自动重置为false。

这是表格的图片:

以及它的 GET/POST 代码:

//GET Users lock
    public async Task<IActionResult> Lock(string id)
    
        if (id == null)
        
            return NotFound();
        

        var userFromDb = await _db.ApplicationUser.SingleOrDefaultAsync(m => m.Id == id);
        if (userFromDb == null)
        
            return NotFound();
        
        else
        
            return View(userFromDb);
        
    

    //POST Users lock
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Lock(string Id, ApplicationUser model)
    
        var userFromDb = await _db.Users.Where(u => u.Id == Id).FirstOrDefaultAsync();

        userFromDb.LockoutEnd = model.LockoutEnd;
        userFromDb.LockoutEnabled = true;
        userFromDb.AccessFailedCount = model.AccessFailedCount;
        userFromDb.LockoutReason = model.LockoutReason;

        _db.ApplicationUser.Update(userFromDb);
        await _db.SaveChangesAsync();

        return RedirectToAction(nameof(Index));           
    

ApplicationUser.cs

public class ApplicationUser : IdentityUser
        
    public string FirstName  get; set; 
    public string LastName  get; set; 
    public string LockoutReason  get; set; 

当我单击 Lock 按钮时,LockoutEnd 和 LockoutReason 字段会正确更新,但 LockoutEnabled 字段仍然为 false,并且帐户没有被锁定。

尝试实施解决方案后的新POST方法:

//POST Users lock
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Lock(string Id, ApplicationUser model)
    
        var userFromDb = await _db.Users.Where(u => u.Id == Id).FirstOrDefaultAsync();

        userFromDb.LockoutEnd = model.LockoutEnd;            
        userFromDb.AccessFailedCount = model.AccessFailedCount;
        userFromDb.LockoutReason = model.LockoutReason;

        _db.ApplicationUser.Update(userFromDb);            
        await _db.SaveChangesAsync();

        var user2 = await _userManager.FindByIdAsync(userFromDb.Id);
        var result = await _userManager.SetLockoutEnabledAsync(user2, true);

        return RedirectToAction(nameof(Index));           
    

【问题讨论】:

尝试更新然后保存,参考(***.com/questions/15799329/…) 我只是试了一下,它对我不起作用编辑:感谢您的帮助 不知道为什么,也许其他人可以提供帮助。 您查看过应用程序发送到数据库的查询吗?字段是否包含在 select 和 update 语句中? 【参考方案1】:

您需要LockoutEnabledLockoutEnd 这两个属性的组合。

LockoutEnabled 是查看用户是否可以被锁定的指示器,LockoutEnd 是 DateTimeOffset。所以为了锁定用户,将 lockout 设置为 true 并将 LockoutEnd 的值放在将来,因为过去的值表示用户没有被锁定。

【讨论】:

哦,哇,我完全误解了锁定的工作原理。出于某种原因,我认为 LockoutEnabled 是一个指示器,用于查看用户当前是否被锁定,并且会设置为 1,直到 LockoutEnd 日期过去。我刚刚手动更新了 LockoutEnabled 值,现在我的锁定功能按预期工作。谢谢! 你也可以创建你自己的锁定/禁用机制,通过向用户添加一个属性,例如:IsDisabled,然后创建你自己的SignInManager,它继承自 SignInManager 并在其中你可以覆盖PasswordSignInAsync 检查用户是否被禁用。【参考方案2】:

您无法通过更改 LockoutEnabled 属性来实现此目的。

相反,您需要添加自定义属性,例如IsEnabled

关于注册操作修改应用用户

var user = new ApplicationUser UserName = model.Email, Email = model.Email, IsEnabled = true ;

在 PasswordSigninAsync 上添加 IsEnabled 检查

'

if (user.IsEnabled)
     return base.PasswordSignInAsync(userName, password, rememberMe, shouldLockout);

return Task.FromResult<SignInStatus>(SignInStatus.LockedOut);

【讨论】:

这是在评论中建议的,它对我不起作用。位字段 (LockoutEnabled) 是唯一不会更新的字段。 感谢您的帮助 - 原来我只是误解了锁定的工作原理,但我最终可能会采纳您的建议并创建自己的 SignInManager 和自定义锁定功能。 您已检查@Hameed 的帖子作为答案。成功了吗?【参考方案3】:

UserManager&lt;ApplicationUser&gt; _userManager

_userManager = userManager; //DI'd via CTOR for the class

从用户表直接访问表是永远不会完成的。

在您的情况下,您可能需要通过调用来抓住用户 var user = await _userManager.FindByIdAsync(model.Id)

因为您可能没有足够的信息来传递模型变量中填充的帖子。

//used from with in method
//model.LockoutEnabled will be either true or false depending on your selection
//from the view.
var result = await _userManager.SetLockoutEnabledAsync(user, model.LockoutEnabled); 

这会返回IdentityResult,它有Errors 集合或bool Succeeded 属性,可以随意处理。

【讨论】:

将结果设置为该值是否会将用户锁定,或者我是否需要对该变量执行某些操作?我尝试只调用 await _userManager.SetLockoutEnabledAsync(user, true) 并没有用。我还将用户设置为 await _userManager.FindByIdAsync(userFromDb.Id) 所以事实证明我什至不需要更新 LockoutEnabled,我只是误解了帐户锁定的工作原理。不过,我感谢您的帮助! 您在 Startup.cs 中是否为 Identity 设置了项目? services.Configure&lt;IdentityOptions&gt;(config =&gt; );

以上是关于无法使用 ASP .NET Core 更新 SQL 位列的主要内容,如果未能解决你的问题,请参考以下文章

无法在 ASP.NET Core 中更新数据库

更新到 ASP.NET Core 2 后无法获取配置部分

无法从在 Docker (Linux) 中运行的 ASP.NET Core 连接到 SQL Server 命名实例

将 SQLite 与 ASP.NET Core MVC 一起使用会产生 SQL Server 错误 52(无法找到本地数据库运行时安装)

解决ASP.NET Core部署到IIS,更新项目"另一个程序正在使用此文件,进程无法访问"

解决ASP.NET Core部署到IIS,更新项目"另一个程序正在使用此文件,进程无法访问"...