简体   繁体   English

如何在EF Core中向Identity用户添加外键?

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

Let's say I have a Todo model with a corresponding Todo table ( DbSet<Todo> ) in an EF-generated database. 假设我在EF生成的数据库中有一个带有相应Todo表( DbSet<Todo> )的Todo模型。 The table will store a todo item per row. 该表将每行存储待办事项。 Each user (in an ASP.NET Core Identity + IdentityServer app) will be associated with multiple todo items (one-to-many, a user can have multiple todo items). 每个用户(在ASP.NET Core Identity + IdentityServer应用程序中)将与多个待办事项相关联(一对多,用户可以有多个待办事项)。

The way I'd do it is to add a UserId foreign key to the Todo model that represents the user that owns the todo item . 我这样做的方法是向Todo模型添加一个UserId外键,代表拥有待办事项的用户。

How would I do that with EF Core while utilizing the classes proved by ASP.NET Core Identity? 在使用ASP.NET核心标识证明的类时,如何使用EF Core? My intuition was to add the following to the Todo class model: 我的直觉是将以下内容添加到Todo类模型中:

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

This uses ApplicationUser (the ASP.NET Core Identity default user class model) as discovery to populate UserId with a foreign key. 这使用ApplicationUser (ASP.NET核心标识默认用户类模型)作为发现来使用外键填充UserId

Here's the problem: when I run Update-Database I get an error! 这是问题所在:当我运行Update-Database出现错误! It says The entity type 'IdentityUserLogin<string>' requires a primary key to be defined. 它表示The entity type 'IdentityUserLogin<string>' requires a primary key to be defined. .

Browsing through the code for IdentityUserLogin , I can see it has a property UserId which should be considered a primary key, right? 浏览IdentityUserLogin的代码,我可以看到它有一个属性UserId应该被认为是主键,对吧?

Anyway, to make sure its registered as a primary key, I added this code to ApplicationUser 's OnModelCreating method: builder.Entity<ApplicationUser>().HasKey(u => u.Id); 无论如何,为了确保将其注册为主键,我将此代码添加到ApplicationUserOnModelCreating方法: builder.Entity<ApplicationUser>().HasKey(u => u.Id); . I still get the same error! 我仍然得到同样的错误! Not sure what I'm doing wrong here :(. Edit: Yes, I called the base class so that's not the problem. 不知道我在这里做错了什么:(。编辑:是的,我打电话给基类,这不是问题所在。

Note: I know I can add a field to each user that carries a collection of todo item Ids instead of having a foreign key, but I'm not sure if that's the good way of doing this. 注意:我知道我可以为每个携带todo项目ID集合的用户添加一个字段,而不是使用外键,但我不确定这是否是这样做的好方法。 Guidance on this issue appreciated. 对此问题的指导表示赞赏。

You haven't shared the code for this, but I'm guessing you have made an override of OnModelCreating in your db context, but have not called base.OnModelCreating(modelBuilder); 你没有为此共享代码,但我猜你已经在db上下文中重写了OnModelCreating ,但是没有调用base.OnModelCreating(modelBuilder); .

Without the base call, your context isn't applying the Identity related schema. 如果没有基本调用,则您的上下文不会应用与身份相关的架构。

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

    // Your fluent modeling here
}

Edit: Felt like giving this a whirl so I just performed the below tasks. 编辑:感觉就像给这个旋转所以我只是执行了以下任务。 The TLDR would be that it worked out for me. TLDR将是它为我解决的问题。 I believe the issue you are having has nothing to do with the key you are making and something unrelated is causing your failure, because the failure you are getting is on a completely different table than the one you are building schema for. 我相信你所遇到的问题与你正在制作的密钥无关,而与你无关的东西会导致你的失败,因为你所获得的失败与你正在构建模式的表完全不同。

I created a new .net core web application using Identity. 我使用Identity创建了一个新的.net核心Web应用程序。 First thing I did was call update-database to build up the DB from the initial migration that the project came with. 我做的第一件事是调用update-database来从项目附带的初始迁移中构建数据库。 This worked. 这很有效。

Next I added a Todo class. 接下来我添加了一个Todo课程。 No properties, just an Id and the User field. 没有属性,只有Id和用户字段。 Didn't even mark the foreign key. 甚至没有标记外键。

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

I added it to the ApplicationDbContext as a DbSet. 我将它作为DbSet添加到ApplicationDbContext中。 Only alteration to the context was to add the ToDo DbSet 只更改上下文是添加ToDo DbSet

Then I called add-migration todo in the package manager console to build the todo migration. 然后我在包管理器控制台中调用了add-migration todo来构建todo迁移。 It generated as expected with the FK in place. 它与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");
    }
}

I then added some code to my About controller action to just stick a record into the table to make sure the FK was working. 然后我在我的About控制器操作中添加了一些代码,只是将记录粘贴到表中以确保FK正常工作。 It was. 它是。

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

Screenshot of the record in the DB along with tables and keys: 数据库中记录的屏幕截图以及表和键: 在此输入图像描述

Other than the obvious that you have more fields on your Todo class is there something drastically different that you've done differently that may lead us to the problem? 除了显而易见的是你的Todo课程中有更多的字段,你有不同的东西,你做了不同的事情,可能会导致我们的问题?

Dave, your solution worked fine ! 戴夫,你的解决方案运行良好!

Just some details for readers, adding the class to ApplicationDbContext as a DbSet means adding to the file ApplicationDbContext.cs Something like : 只是读者的一些细节,将类添加到ApplicationDbContext作为DbSet意味着添加到文件ApplicationDbContext.cs类似于:

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

and when it's needed (in Package Manager Console) : PM> Add-Migration MyClass PM> Update-Database 当需要时(在包管理器控制台中):PM>添加 - 迁移MyClass PM>更新 - 数据库

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 EF Core 中的不同项目之间向 ApplicationUser 添加外键? - How to add a foreign key to ApplicationUser between separate project in EF Core? 如何在具有标识和干净架构的 EF Core 中定义一对零或一的关系? - How Do I Define One-to-Zero-Or-One Relationships in EF Core with Identity and Clean Architecture? 如何使用 ASP.NET Core 2.1 Identity 在单个事务中添加新用户和声明? - How do you add a new user and claim in a single transaction using ASP.NET Core 2.1 Identity? ASP MVC5 - 身份。 如何获取当前 ApplicationUser 并使用此用户查询以用户为外键的表 - ASP MVC5 - Identity. How to get current ApplicationUser and use this user to query a table with user as foreign key 如何为带有外键的插入代码? - How do I code for an insert with a foreign key? 如何在EF中使用共享外键 - How to work with Shared foreign key in EF 如何将用户的Guid ID设置为他们正在创建为外键的项目? - How Do I set the Guid Id of a User to an item that they are creating as foreign key? 迁移不会将身份属性添加到EF Core中的列 - Migrations dont add identity atributte to column in EF Core 如何将ASP.Net Identity User Email属性作为外键引用 - How to reference ASP.Net Identity User Email property as Foreign Key 用户的ASP.NET MVC身份外键 - ASP.NET MVC Identity Foreign Key to User
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM