首页 文章

Microsoft.AspNet.Identity.EntityFramework.IdentityUser的外键?

提问于
浏览
7

我在VS 2013,刚刚创建了一个MVC应用程序 .

我正在创建一个对象,我打算在结果数据库中有一个AspNetUsers表的外键 . 该项目确实有一个ApplicationUser(派生自IdentityUser),看起来像是与AspNetUsers表的属性列匹配 .

我们如何正确地为此声明外键?

public MyObject
{
   public string UserId { get; set; }

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

   // other properties
}

现在,我修改ApplicationUser以获得MyObjects的集合:

public ApplicationUser : IdentityUser
{
     public virtual ICollection<MyObject> MyObjects { get; set; }    
}

这似乎是如何在EF Code First中进行一对多操作 . 但是,当我更新数据库时,我收到的错误表明身份成员(IdentityUserLogin,IdentityUserRole等)没有定义键 . 也许这些课程不打算参加EF Code First Migrations?

我可以“回到”并通过SQL语句添加外键,但如果我想再次从Code First更新,我可能会收到错误(数据库目前不匹配旧的迁移或类似的东西) .

我们如何正确地使用外键参考这些会员表?

我还尝试使用AspNetUsers表的匹配属性创建一个AspNetUser类 . 我没有在Client类上使用“public ApplicationUser”,而是声明了“public AspNetUser” . 这样做会导致迁移失败 - “未应用自动迁移,因为它会导致数据丢失” .

那么该怎么办?

5 回答

  • 3

    ApplicationUserMyObject 之间创建一对多关系很容易,并在 MyObjects 表中添加"UserId"外键 . 我喜欢这个解决方案的是它遵循EF约定,并且模型中不需要 [ForeignKey] 属性:

    public class ApplicationUser : IdentityUser
    {
        public virtual ICollection<MyObject> MyObjects { get; set; }
    }
    
    public class MyObject
    {
        public int MyObjectId { get; set; }
    
        public string MyObjectName { get; set; }
    
        // other properties
    
        public virtual ApplicationUser ApplicationUser { get; set; }
    }
    
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
        }
    
        public DbSet<MyObject> MyObjects { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            modelBuilder.Entity<MyObject>()
                .HasRequired(c => c.ApplicationUser)
                .WithMany(t => t.MyObjects)
                .Map(m => m.MapKey("UserId"));
        }
    }
    

    请注意使用Fluent API在 MyObjects 表中创建"UserId"外键 . 此解决方案仍然可以在不添加Fluent API的情况下工作,但按照惯例,您的外键列将在 MyObjects 表中命名为"ApplicationUser_Id" .

  • 2

    我会执行以下操作:在 ApplicationUser 类中,添加 ForeignKey 属性,

    public ApplicationUser : IdentityUser {
        [ForeignKey("UserID")]
        public virtual ICollection<MyCustomUser> MyCustomUsers{ get; set; }    
    }
    

    并在您的模型中,您要跟踪它所属的用户,

    public MyObject {
        public string UserId { get; set; }
    
        // other properties
    }
    

    您不需要将整个 ApplicationUser 实例存储在 MyObject 类中,并且将自动生成 UserID . 重要的是 string 类型, ApplicationUserID

  • 0

    我认为你倒退了 . 也许尝试类似的东西:

    public MyCustomUser : IUser
    {
       public string Id { get; set; }
    
       public string FavoriteHairColor { get; set;}
    }
    
    public ApplicationUser : IdentityUser
    {
         public virtual ICollection<MyCustomUser> MyCustomUsers{ get; set; }    
    }
    

    我要从记忆中走出来,所以我可能会有点失望 . 无论如何,重要的是让你的EF用户类继承自IUser .

  • 0

    ASP.NET Identity类不使用属性来定义关系,他们希望关系由DbContext配置 .

    与ASP.NET Identity一起使用的默认DbContext, IdentityDbContext<TUser> 包括配置 . 因此,如果您使DbContext类继承自 IdentityDbContext<ApplicationUser> ,则应该全部设置 .

    Update

    如果仍然出现错误:“未应用自动迁移,因为它会导致数据丢失 . ”然后做:

    get Update-Database -Force
    

    如果仍然收到有关IdentityUserLogin的错误消息,IdentityUserRole等没有定义键,那么您很可能在不调用基本方法的情况下覆盖DbContext中的 OnModelCreating 方法 . 像这样添加对基地的调用:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelbuilder);
        // your code here
    }
    

    End of Update

    如果您不想从 IdentityDbContext 继承,则需要为Identity类添加一些配置 . 一种方法是覆盖 OnModelCreating . 这是 IdentityDbContext<ApplicationUser> 配置实体框架映射的地方 . 如果将其添加到DbContext类,则应设置所需的映射 .

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
        modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
        modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
    }
    
  • 0
    public MyObject
    {
       .. other properties
    
       [MaxLength(128), ForeignKey("ApplicationUser")]
       public virtual string UserId { get; set; }
    
       public virtual ApplicationUser ApplicationUser { get; set;}
    }
    

相关问题