使用 ApplicationUser 插入依赖实体

Insert dependent entity with ApplicationUser

我有以下实体:

public class ApplicationUser : IdentityUser
{
    ...
    public int? StudentId { get; set; }
    public virtual Student Student { get; set; }
}

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

我正在尝试创建一个新的应用程序用户和学生,所以我这样做了:

var user = new ApplicationUser() {
    Name = "test",
    UserName = "test",
    Student = new Student ()
};

var result = await userManager.CreateAsync(user, "test12345!");

结果成功,两个实体被插入数据库,但是Student.UserId为空

如何插入实体及其关系?

我尝试设置 student.UserId = user.Id,但随后我收到一条异常消息:"Unable to determine a valid ordering for dependent operations"

您正在寻找学生和应用程序用户之间的一对(零或一)关系。所以对于一个用户来说,可能有也可能没有学生。

在这种情况下,您不需要学生 class 中的应用程序用户 ID,或者如果您需要,那将是您的基础 class。

modelBuilder.Entity<ApplicationUser>() 
.HasKey(t => t.StudentId); 


// Map one-to-zero or one relationship 
modelBuilder.Entity<ApplicationUser>() 
    .HasRequired(t => t.Student) 
    .WithOptional(t => t.ApplicationUser);

相反,如果您正在寻找一对一的关系

modelBuilder.Entity<ApplicationUser>() 
    .HasKey(t => t.StudentId); 

modelBuilder.Entity<Instructor>() 
    .HasRequired(t => t.Student) 
    .WithRequiredPrincipal(t => t.ApplicationUser);

在这两种情况下,您可能不需要两个实体的 Id。作为尾注,请尽可能共享两者的映射 class。

此处提供了问题和解决方案 and here EF Code First - 1-to-1 Optional Relationship。但是,让我为这个主题补充一些内容。

您的实体设计在 ApplicationUser 相关数据库 table 中创建了冗余,但更重要的是,它在两者之间创建了一个 外键关系循环 tables。虽然处理这种关系在技术上是可行的,但这是维护的噩梦,应该避免。

EF 代码优先方法的优点在于您不必考虑这些事情。不要尝试将您的 POCO 设计为 db tables。除主键外,不要使用 xxxId 属性。使用正确配置的 导航属性 来表达您的实体之间的关系,并让 EF 负责数据库设计。

考虑到所有这些:

首先,从 ApplicationUser class 中删除 StudentId 属性 并从 Student [=] 中删除 UserId 属性 36=]。请注意,这将从相应的数据库 table 中删除 StudentId 列,因此您可以考虑从新数据库开始或使用迁移。

然后使用如下配置:

modelBuilder.Entity<ApplicationUser>()
    .HasOptional(u => u.Student)
    .WithRequired(s => s.User).Map(a => a.MapKey("UserId"));

你的问题应该已经解决了。