【问题标题】:Entity Framework Core: Npgsql.PostgresException: 23505: duplicate key value violates unique constraint实体框架核心:Npgsql.PostgresException:23505:重复键值违反唯一约束
【发布时间】:2016-12-23 18:29:39
【问题描述】:

当我尝试从 asp.net web api 插入用户时出现以下异常: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Npgsql.PostgresException: 23505: duplicate key value violates unique constraint

以下是我的实体模型:角色和用户。每个用户都与一个角色相关联。

public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime? LastUpdate { get; set; }
}

public class User
{
    public int Id { get; set; }
    public Role role { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public DateTime? DateCreated { get; set; }
    public DateTime? LastLogin { get; set; }
}

我的端点如下所示:

[HttpPost]
    public async Task<IActionResult> PostUser([FromBody] User user)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        user.DateCreated = DateTime.Now;
        //user.LastLogin = DateTime.Now;
        var hashedPassword = BCrypt.Net.BCrypt.HashPassword(user.Password);
        user.Password = hashedPassword;
        _context.User.Add(user);
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateException ex)
        {
            Console.WriteLine(ex.Message);
            if (UserExists(user.Id))
            {
                return new StatusCodeResult(StatusCodes.Status409Conflict);
            }
            else
            {
                Console.WriteLine(ex.Message);
            }
        }

        return CreatedAtAction("GetUser", new { id = user.Id }, user);
    }

请注意,在进行了一些调试之后,从主体传递的新用户通过了下面的检查,这意味着我的模型是有效的:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

但最后,在 catch 块上结束并打印出上面提到的异常。

它似乎试图创建一个链接到新用户的角色。我现在不知道为什么,因为角色已经存在。

这个问题的原因可能是什么?

【问题讨论】:

  • 您的 User 实例是如何准确创建的,其角色设置为什么?在保存更改之前尝试将角色设置为 null,以确认它是角色。如果确实是导致异常的角色,您需要准确了解它是何时创建的以及如何创建的。您可能需要将您的角色实例附加到现有的数据库实体(否则 EF 事物它是一个新实体并尝试插入)。阅读 Add vs. Attach 以更好地理解这一点。
  • 我的用户界面是使用 angular2 创建的。当我在角色属性上传递 null 时,它可以工作。但是,当我指定现有角色时,它会失败,因为它试图重新创建角色,而不是仅仅将其附加到正在创建的新用户。

标签: c# entity-framework postgresql npgsql


【解决方案1】:

如果您的角色实例已经存在,您需要附加它以让 EF 知道它已经存在于数据库中。否则 EF 假定它是一个新实例并尝试重新创建它,从而导致违反唯一约束。这就是 EF 的工作原理,您可以阅读https://msdn.microsoft.com/en-us/data/jj592676.aspx 了解更多详细信息(它是关于 EF6,但也适用于 EFCore)。

请注意,您也可以像在自己的答案 (_context.Role.FirstOrDefault(...)) 中所做的那样从数据库中加载现有角色,但这可能涉及不必要的数据库查询。只要您能够在 .NET 中完全构建 Role 对象,您只需将其附加到您的上下文中,EF 就会明白它应该已经存在于数据库中。

【讨论】:

    【解决方案2】:

    肯定是和实体框架有关的东西。虽然我正在创建一个附加到现有角色的新用户,但我也在尝试重新创建该角色。在保存实体之前,我转到我的点并添加了以下几行,以确保附加到用户的角色使用与正在保存的用户相同的数据库上下文:

     var rl = _context.Role.FirstOrDefault(r=> r.Id==user.role.Id);
     user.role= rl;
    

    现在可以了……

    当我必须保存引用其他对象的对象时,是否总是需要这样做?

    【讨论】:

      猜你喜欢
      • 2018-06-06
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 2022-01-13
      • 2020-03-27
      • 2013-06-23
      • 2016-06-12
      • 2013-03-15
      相关资源
      最近更新 更多