[英]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);
无论如何,为了确保将其注册为主键,我将此代码添加到
ApplicationUser
的OnModelCreating
方法: 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.