AddOrUpdate() 抛出错误:使用 'Identity' 模式修改列 - 我应该如何处理这个问题?



我一直在阅读Adrian Hall关于集成Xamarin和Azure移动应用程序的书。在第3章中,他添加了一个用户表来方便"朋友"数据。在他的实现中,客户端对用户进行身份验证,然后向自定义终结点发出请求,该终结点将用户添加到数据库或更新其记录。下面是自定义控制器中该方法的删节版本:

[HttpGet]
public async Task<IHttpActionResult> Get()
{
// ...Obtain user info
User user = new User()
{
Id = sid,
Name = name,
EmailAddress = email
};
dbContext.Users.AddOrUpdate(user);
dbContext.SaveChanges();
// ...
}

问题是,同一用户第二次登录应用程序时,此代码会抛出异常,指出

不支持使用"标识"模式修改列。列:"创建时间"。表:"CodeFirstDatabaseSchema.User"。

此 StackOverflow 答案解释说,这是因为AddOrUpdate()方法会清空实体上未设置的任何属性,包括CreatedAt,这是一个标识列。这给我留下了几个问题:

  1. 如果无法编辑 CreatedAt 值,添加或更新实体的正确方法是什么?同一 SO 线程建议使用帮助程序方法来查找现有的 CreatedAt 并将其应用于实体,然后再尝试保存它。这似乎很麻烦。
  2. 为什么将其实现为自定义身份验证控制器,当它只需要在数据库中添加或更新用户时返回新的身份验证令牌?为什么不使用普通实体控制器来添加/更新新用户,并允许客户端继续使用它已有的身份验证令牌?

有关CustomAuthController.cs代码,请参阅此处。

当你从SQL的角度专注于你试图做的事情时,它会像这样:

update dbo.some_table set some_primary_key = new_primary_key where some_primary_key = ...

这将导致cannot update identity column some_primary_key这是有意义的。

但是,如果您确实有理由更新PK,如果您设置了身份插入,您仍然可以这样做SET IDENTITY_INSERT dbo.some_table ON;然后在插入后,使用类似的语法将其设置。

但这是相当特殊的情况。 通常不需要手动插入PK。

现在回到 EF。

您收到的错误告诉您无法使用 PK 修改列,如果您具有复合 PK,则很可能是user_id和/或其他一些列。

因此,第一次创建新用户。第二次,因为你起诉GetOrUpdate,一个用户被udped,但因为你通过PK,它就会中断。

溶液?

AddOrUpdate旨在帮助播种迁移。 鉴于其破坏性,我不建议在生产环境附近的任何地方使用GetOrUpdate

您可以将GetOrUpdate替换为两个操作 Get 和 Update

  1. 获取用户,然后
  2. 如果不存在,则创建一个新的
  3. 或者如果它确实存在,则更新它

最新更新