【问题标题】:Insert dependent entity with ApplicationUser使用 ApplicationUser 插入依赖实体
【发布时间】:2015-08-29 00:10:58
【问题描述】:

我有以下实体:

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,但随后我收到一条异常消息:“无法确定相关操作的有效排序”

【问题讨论】:

  • 这些是如何映射的? Student.UserId 不能与 User.Id 相同(我假设),因为 UserId 是字符串类型,并且当 Id 是数据库生成时,它必须是数值。编辑:当 user.Id 确实是一个字符串值时,可以使用 HasOptional().WithOptionalDependant() 修复出现的错误
  • 是的,Student.UserId和User.Id一样,ApplicationUser继承自IdentityUser,IdentityUser默认有字符串Id
  • 另外,模型创建正确,在数据库中我有正确的外键,只是没有设置值

标签: c# entity-framework asp.net-web-api asp.net-identity asp.net-identity-2


【解决方案1】:

这里提供了问题和解决方案One-to-one relationsip with optional dependent end using default conventions 和这里EF Code First - 1-to-1 Optional Relationship。但是,让我为这个主题添加一些东西。

您的实体设计在ApplicationUser 相关的db 表中创建了冗余,但更重要的是,它在两个表之间创建了一个外键关系循环。尽管在技术上可以处理这样的关系,但这是一个维护噩梦,应该避免。

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

考虑到所有这些:

首先,从ApplicationUser 类中删除StudentId 属性,并从Student 类中删除UserId 属性。请注意,这将从相应的 db 表中删除 StudentId 列,因此您可以考虑从新的 db 开始或使用迁移。

然后使用如下配置:

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

你的问题应该得到解决。

【讨论】:

  • 这个确实有效,我还有一个问题,这只能通过 Fluent API 来完成,或者我有什么方法可以用 Data Annotations 做到这一点?
  • AFAIK,仅限 Fluent API。
【解决方案2】:

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

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

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。最后,请尽可能分享两者的映射类。

【讨论】:

  • 我已经尝试了两种方式,数据库结构似乎没问题,但是当我将学生添加到 ApplicationUser 并尝试将其添加到 dbcontext 时,它显示 UserId 字段(在学生) 是必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多