2017-04-04 104 views
1

我嘗試自定義聲明添加到現有的用戶身份的一個要求,但我在運行時得到一個異常:無法添加與ASP.NET核心和身份

Npgsql.PostgresException: 23502: null value in column "Id" violates not-null constraint 

幫助!

我做了什麼。我創建使用下面的命令行

dotnet new mvc --auth Individual --framework netcoreapp1.1 

我所做的更改發現here,使應用程序使用PostgreSQL作爲後端數據庫窗口一個簡單的Web應用程序。創建的默認webapp工作正常。我可以作爲一個新的用戶註冊,登錄,註銷等..

然後我修改的家庭控制器的測試方法(我知道的例外是醜陋的):

[Authorize] 
    public async Task<IActionResult> Test() 
    { 
     var user = await GetCurrentUserAsync(); 
     if (user == null) { 
      _logger.LogWarning("User is null."); 
      throw new Exception("Not logged in"); 
     } 
     _logger.LogWarning("User: {0}, {1}", user.Email, user); 

     var claim = new Claim("TestClaimType", "TestClaimValue"); 

     IdentityResult idRes = IdentityResult.Failed(); 
     if (_userManager.SupportsUserClaim) { 
      idRes = await _userManager.AddClaimAsync(user, claim); <------- Adding the claim 
     } 
     _logger.LogWarning("Return from adding claim"); 

     if (idRes != IdentityResult.Success) { 
      throw new Exception("Failed to add claim."); 
     } 

     return View(); 
    } 

在登錄後我觸發試驗方法,並得到以下日誌記錄(該PostgresException已經接近尾聲):

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] 
     Request starting HTTP/1.1 GET http://localhost:5000/Home/Test 
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[3] 
     HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Identity.Application. 
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1] 
     Authorization was successful for user: [email protected] 
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1] 
     Executing action method AlumniConnect.Controllers.HomeController.Test (AlumniConnect) with arguments ((null)) - ModelState is Valid 
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1] 
     Executed DbCommand (1ms) [Parameters=[@__get_Item_0='?'], CommandType='Text', CommandTimeout='30'] 
     SELECT "e"."Id", "e"."AccessFailedCount", "e"."ConcurrencyStamp", "e"."Email", "e"."EmailConfirmed", "e"."LockoutEnabled", "e"."LockoutEnd", "e"."NormalizedEmail", "e"."NormalizedUserName", "e"."PasswordHash", "e"."PhoneNumber", "e"."PhoneNumberConfirmed", "e"."SecurityStamp", "e"."TwoFactorEnabled", "e"."UserName" 
     FROM "AspNetUsers" AS "e" 
     WHERE "e"."Id" = @__get_Item_0 
     LIMIT 1 
warn: AlumniConnect.Controllers.HomeController[0] 
     User: [email protected], [email protected] 
warn: AlumniConnect.Controllers.HomeController[0] 
     User: [email protected], [email protected] 
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1] 
     Executed DbCommand (4ms) [Parameters=[@__normalizedUserName_0='?'], CommandType='Text', CommandTimeout='30'] 
     SELECT "u"."Id", "u"."AccessFailedCount", "u"."ConcurrencyStamp", "u"."Email", "u"."EmailConfirmed", "u"."LockoutEnabled", "u"."LockoutEnd", "u"."NormalizedEmail", "u"."NormalizedUserName", "u"."PasswordHash", "u"."PhoneNumber", "u"."PhoneNumberConfirmed", "u"."SecurityStamp", "u"."TwoFactorEnabled", "u"."UserName" 
     FROM "AspNetUsers" AS "u" 
     WHERE "u"."NormalizedUserName" = @__normalizedUserName_0 
     LIMIT 1 
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1] 
     Executed DbCommand (33ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p17='?', @p3='?', @p4='?', @p18='?', @p5='?', @p6='?', @p7='?', @p8='?', @p9='?', @p10='?', @p11='?', @p12='?', @p13='?', @p14='?', @p15='?', @p16='?'], CommandType='Text', CommandTimeout='30'] 
     INSERT INTO "AspNetUserClaims" ("ClaimType", "ClaimValue", "UserId") 
     VALUES (@p0, @p1, @p2) 
     RETURNING "Id"; 
     UPDATE "AspNetUsers" SET "AccessFailedCount" = @p3, "ConcurrencyStamp" = @p4, "Email" = @p5, "EmailConfirmed" = @p6, "LockoutEnabled" = @p7, "LockoutEnd" = @p8, "NormalizedEmail" = @p9, "NormalizedUserName" = @p10, "PasswordHash" = @p11, "PhoneNumber" = @p12, "PhoneNumberConfirmed" = @p13, "SecurityStamp" = @p14, "TwoFactorEnabled" = @p15, "UserName" = @p16 
     WHERE "Id" = @p17 AND "ConcurrencyStamp" = @p18; 
fail: Microsoft.EntityFrameworkCore.DbContext[1] 
     An exception occurred in the database while saving changes. 
     Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Npgsql.PostgresException: 23502: null value in column "Id" violates not-null constraint 
     at Npgsql.NpgsqlConnector.<DoReadMessageAsync>d__6.MoveNext() 
     --- End of stack trace from previous location where exception was thrown --- 

有很多記錄更多,但它似乎並沒有增加新的信息。我在整個日誌中看到了多次提到的相同異常。

我該怎麼辦?這是PostgreSQL的特定問題嗎?我是否試圖以錯誤的方式添加索賠?

謝謝!

+0

Npgsql.PostgresException:23502:在列「ID」空值違反非空約束。看起來像[dbo]上的Id,[AspNetUserClaims]沒有被設置。你可以檢查用戶對象上的Id嗎? –

+0

我沒有辦法檢查這個。 Claim類沒有ID屬性。我認爲,由於UserManager來自身份庫,因此會提供ID。是不是代碼需要自動生成一個ID,而事實並非如此?嗯,'RETURNING'Id''似乎暗示了類似的東西。 –

+0

我假設用戶對象上的Id屬性未設置,但該對象不爲空。你可以在測試中粘貼一個斷點並檢查用戶對象。 –

回答

2

在移民身份,有一個產生整數ID的所有表具有註釋添加該ID的自動生成。此註釋是SQL Server特定的,如.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)

修復此問題是爲遷移添加Postgres特定註釋:.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)。在舊版本的Npgsql.EntityFrameworkCore.PostgreSQL中,可能需要使用.Annotation("Npgsql:ValueGeneratedOnAdd", true)

遷移用於創建AspNetRoleClaims表,然後將類似於部分:

  migrationBuilder.CreateTable(
      name: "AspNetRoleClaims", 
      columns: table => new 
      { 
       Id = table.Column<int>(nullable: false) 
        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) 
        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), 
       ClaimType = table.Column<string>(nullable: true), 
       ClaimValue = table.Column<string>(nullable: true), 
       RoleId = table.Column<string>(nullable: false) 
      }, 
      constraints: table => 
      { 
       table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); 
       table.ForeignKey(
        name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", 
        column: x => x.RoleId, 
        principalTable: "AspNetRoles", 
        principalColumn: "Id", 
        onDelete: ReferentialAction.Cascade); 
      }); 
+0

這是一個比我的更好的解決方案,謝謝。 –

0

看起來,當將聲明添加到數據庫時,SQL語句的'RETURNING'Id''子句建議返回ID。但是,該表沒有自動遞增ID列。

我通過遵循Adding 'serial' to existing column in Postgres的說明進行驗證。

的問題是現在當然,這應該被照顧的自動...