为啥我不能用 Attach() 更新 IdentityUser?
Posted
技术标签:
【中文标题】为啥我不能用 Attach() 更新 IdentityUser?【英文标题】:Why can't I update IdentityUser with Attach()?为什么我不能用 Attach() 更新 IdentityUser? 【发布时间】:2021-07-01 07:28:09 【问题描述】:下面的代码抛出:
数据库操作预计会影响 1 行,但实际上影响了 0 行。
var updatedUser = new User Id = _currentUserService.UserId, MyBool = true ;
_dbContext.Users.Attach(updatedUser);
_dbContext.Entry(updatedUser).Property(user => user.MyBool).IsModified = true;
await _dbContext.SaveChangesAsync()
用户是从IdentityUser
继承的,这是我项目中唯一一个这种更新方法不起作用的地方。我在没有UserManager
的情况下这样做,因为我不想获取所有用户列。我想要的只是更新MyBool
属性。所以我不需要其他方法来做到这一点,我只是想了解我为什么会出现这种行为。
当然,我传递的不是同一个布尔值。
我假设我不明白IdentityUser
对DbContext
的影响,因为上面的代码适用于我所有未与Identity
连接的自定义实体。
【问题讨论】:
欢迎来到 Stack Overflow。请通过tour 了解 Stack Overflow 的工作原理,并阅读How to Ask 以了解如何提高问题的质量。然后edit你的问题包含你拥有的完整源代码作为minimal reproducible example,其他人可以编译和测试。 我忘了在我的问题中添加 await _dbContext.SaveChangesAsync(),我的错。如果我没有在我的项目中编写它,我不会得到预期会影响 1 行但实际上影响 0 行异常的数据库操作。这个问题仍然相关.. 如果你想执行UPDATE SET MyBool=1 Where ID=@id
,就这样做。不要试图通过 ORM 来近似它。所有 ORM 都是为处理对象图而构建的,而不是作为 SQL 的替代品。要使用 ORM 更新对象,您必须加载对象、修改它然后持久化它。是的,这很慢,需要两次往返,而且更有可能导致并发冲突。
是的,我已经被告知无论我要更新多少列,我都应该获取整个实体。是的,正如你提到的,我害怕性能速度。看起来我正在尝试结合 SQL 和 ORM 的最佳效果,并有点破坏 ORM 的概念。
【参考方案1】:
在IdentityDbContext<TUser>
的基类中,您可以在 OnModelCreating() 中找到以下内容:
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
所以你的var updatedUser = new User
方法不起作用。
您需要先获取用户。在无论如何都应该如此的普通代码中,您不想在“更新”中丢失名称和其他所有内容,对吗?
【讨论】:
只修改一个属性而不覆盖任何其他属性是一种非常好的方法。但是您正确地指出他们还应该设置确实需要往返数据库的ConcurrencyStamp
属性。
是的,我知道。我用 IsModified 误读了该行。当您进行往返时,您不妨将其留给 ChangeTracker。
哦,谢谢你的回答,我稍后再看看。【参考方案2】:
我总是使用这样的代码:
var existedUser = _dbContext.Set<ApplicationUser>()
.FirstOrDefault( i=> i.UserId=_currentUserService.UserId);
if(existedUser ==null) ... error
existedUser.MyBool=true;
_dbContext.Entry(existedUser).Property(user => user.MyBool).IsModified = true;
await _dbContext.SaveChangesAsync();
【讨论】:
我不想获取所有用户列。这就是问题的重点。请参阅另一个答案:它要求从数据库中检索ConcurrencyStamp
的当前值。不获取整个记录是否只是过早优化是另一个讨论。以上是关于为啥我不能用 Attach() 更新 IdentityUser?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能用我的 api 响应更新我的状态?数据是一个对象数组