簡體   English   中英

如何在EF Core中向Identity用戶添加外鍵?

[英]How do I add a foreign key to Identity user in EF Core?

假設我在EF生成的數據庫中有一個帶有相應Todo表( DbSet<Todo> )的Todo模型。 該表將每行存儲待辦事項。 每個用戶(在ASP.NET Core Identity + IdentityServer應用程序中)將與多個待辦事項相關聯(一對多,用戶可以有多個待辦事項)。

我這樣做的方法是向Todo模型添加一個UserId外鍵,代表擁有待辦事項的用戶。

在使用ASP.NET核心標識證明的類時,如何使用EF Core? 我的直覺是將以下內容添加到Todo類模型中:

public string UserId { get; set; }
[ForeignKey("UserId")]
public ApplicationUser User { get; set; }

這使用ApplicationUser (ASP.NET核心標識默認用戶類模型)作為發現來使用外鍵填充UserId

這是問題所在:當我運行Update-Database出現錯誤! 它表示The entity type 'IdentityUserLogin<string>' requires a primary key to be defined.

瀏覽IdentityUserLogin的代碼,我可以看到它有一個屬性UserId應該被認為是主鍵,對吧?

無論如何,為了確保將其注冊為主鍵,我將此代碼添加到ApplicationUserOnModelCreating方法: builder.Entity<ApplicationUser>().HasKey(u => u.Id); 我仍然得到同樣的錯誤! 不知道我在這里做錯了什么:(。編輯:是的,我打電話給基類,這不是問題所在。

注意:我知道我可以為每個攜帶todo項目ID集合的用戶添加一個字段,而不是使用外鍵,但我不確定這是否是這樣做的好方法。 對此問題的指導表示贊賞。

你沒有為此共享代碼,但我猜你已經在db上下文中重寫了OnModelCreating ,但是沒有調用base.OnModelCreating(modelBuilder);

如果沒有基本調用,則您的上下文不會應用與身份相關的架構。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Add Identity related model configuration
    base.OnModelCreating(modelBuilder);

    // Your fluent modeling here
}

編輯:感覺就像給這個旋轉所以我只是執行了以下任務。 TLDR將是它為我解決的問題。 我相信你所遇到的問題與你正在制作的密鑰無關,而與你無關的東西會導致你的失敗,因為你所獲得的失敗與你正在構建模式的表完全不同。

我使用Identity創建了一個新的.net核心Web應用程序。 我做的第一件事是調用update-database來從項目附帶的初始遷移中構建數據庫。 這很有效。

接下來我添加了一個Todo課程。 沒有屬性,只有Id和用戶字段。 甚至沒有標記外鍵。

public class Todo
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public ApplicationUser User { get; set; }
}

我將它作為DbSet添加到ApplicationDbContext中。 只更改上下文是添加ToDo DbSet

然后我在包管理器控制台中調用了add-migration todo來構建todo遷移。 它與FK一起按預期生成。

public partial class Todo : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Todos",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                UserId = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Todos", x => x.Id);
                table.ForeignKey(
                    name: "FK_Todos_AspNetUsers_UserId",
                    column: x => x.UserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

        migrationBuilder.CreateIndex(
            name: "IX_Todos_UserId",
            table: "Todos",
            column: "UserId");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Todos");
    }
}

然后我在我的About控制器操作中添加了一些代碼,只是將記錄粘貼到表中以確保FK正常工作。 它是。

public async Task<IActionResult> About()
{
    var user = await _userManager.GetUserAsync(HttpContext.User);
    var todo = new Todo
    {
        User = user
    };
    _context.Todos.Add(todo);
    await _context.SaveChangesAsync();

    return View();
}

數據庫中記錄的屏幕截圖以及表和鍵: 在此輸入圖像描述

除了顯而易見的是你的Todo課程中有更多的字段,你有不同的東西,你做了不同的事情,可能會導致我們的問題?

戴夫,你的解決方案運行良好!

只是讀者的一些細節,將類添加到ApplicationDbContext作為DbSet意味着添加到文件ApplicationDbContext.cs類似於:

public DbSet<MyClass> MyClass { get; set; }

當需要時(在包管理器控制台中):PM>添加 - 遷移MyClass PM>更新 - 數據庫

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM