AddOrUpdate()引发错误:用“身份”模式修改列-我应该如何处理?

时间:2018-06-20 21:24:36

标签: asp.net web-services xamarin controller azure-mobile-services

我一直在研究Adrian Hall的有关Xamarin和Azure移动应用程序集成的书。在Chapter 3中,他添加了一个User表来简化“ Friends”数据。在他的实现中,客户端对用户进行身份验证,然后向自定义端点发出请求,该自定义端点将用户添加到数据库或更新其记录。这是自定义控制器中方法的简化版本:

[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();
    // ...
}

麻烦是,同一用户第二次登录该应用程序,此代码引发了异常

  

不支持使用“身份”模式修改列。列:“ CreatedAt”。表格:“ CodeFirstDatabaseSchema.User”。

This StackOverflow Answer解释说这是因为AddOrUpdate()方法使所有未在实体上设置的属性无效,包括CreatedAt(它是一个标识列)。这给我留下了几个问题:

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

有关CustomAuthController.cs代码,请参见here

1 个答案:

答案 0 :(得分:0)

从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 ,所以用户会被加密码,但是因为您传递的是PK,它会中断。

解决方案?

AddOrUpdate was meant to help with seeding the migrations only。 给定its destructive nature,我不建议在生产环境附近的任何地方使用 GetOrUpdate

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

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