如何在EF 6中引用自定义IdentityUser类的外键

本文关键字:IdentityUser 自定义 引用 EF | 更新日期: 2023-09-27 18:10:54

我已经有这个问题一个星期了。我已经在web和Stackoverflow上搜索了多个来源,关于在实体框架6 (EF 6)中将模型的外键引用到IdentityUser类。

我尝试了许多不同的变化来设置我的DbContext, Model,自定义IdentityUser类。

最后,我尝试在实现IdentityUserLogin, IdentityRole和IdentityUserRole的HasKey方法时添加OnModelCreating。

下面是我目前的代码:

IdentityModel

 public class ApplicationUser : IdentityUser
    {
        [Required]
        public string Fullname { get; set; }
        [Required]
        public string Province { get; set; }
        [Required]
        public string Company { get; set; }
        public virtual ICollection<Expense> Expenses { get; set; }
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }

    }
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("PacificPetEntities", throwIfV1Schema: false)
        {
        }
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
        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 });
            base.OnModelCreating(modelBuilder);
        }
        //public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    }

配置

 internal sealed class ExpensesConfiguration : DbMigrationsConfiguration<PacificPetExpensesDb>
    {
        public ExpensesConfiguration()
        {
            AutomaticMigrationsEnabled = true;
            ContextKey = "PacificPetExpenses.Models.PacificPetExpensesDb";
        }
        protected override void Seed(PacificPetExpensesDb context)
        {
            //  This method will be called after migrating to the latest version.
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }

    internal sealed class UserConfiguration : DbMigrationsConfiguration<ApplicationDbContext>
    {
        public UserConfiguration()
        {
            AutomaticMigrationsEnabled = true;
            ContextKey = "PacificPetExpenses.Models.ApplicationDbContext";
        }
        protected override void Seed(ApplicationDbContext context)
        {
            //  This method will be called after migrating to the latest version.
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }

DbContext

public class PacificPetExpensesDb : DbContext
    {
        public PacificPetExpensesDb()
            : base("PacificPetEntities")
        {
            //Create database always, even If exists
            Database.SetInitializer<PacificPetExpensesDb>(new CreateDatabaseIfNotExists<PacificPetExpensesDb>());
        }
        public DbSet<Expense> Expenses { get; set; }

    }

我的模型

public class Expense : IValidatableObject
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }
        [Required]
        public string Category { get; set; }
        public string Description { get; set; }
        [Required]
        [Display(Name = "Gross Amount")]
        public double GrossAmount { get; set; }
        [Required]
        [Display(Name = "Tax Amount")]
        public double TaxAmount { get; set; }
        [Required]
        [Display(Name = "Net Amount")]
        public double NetAmount { get; set; }
        public int Mileage { get; set; }
        [Display(Name = "Mileage Rate")]
        public double MileageRate { get; set; }
        [Required]
        [Display(Name = "Date Submitted")]
        public DateTime? DateSubmitted { get; set; }
        [Required]
        [Display(Name = "Expense Date")]
        public DateTime? ExpenseDate { get; set; }

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

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Category == "Auto - Mileage" && Mileage == 0)
            {
                yield return new ValidationResult("You must enter a mileage amount if the chosen category is mileage.");
            }
        }
    }

每次我运行我的实体框架代码的任何变化,我得到这个错误消息:

在模型生成过程中检测到一个或多个验证错误:

  • PacificPetExpenses.Models。IdentityUserLogin:: EntityType'IdentityUserLogin'没有定义密钥。为此定义键EntityType。
  • PacificPetExpenses.Models。IdentityUserRole:: EntityType'IdentityUserRole'没有定义键。为此定义键EntityType。
  • IdentityUserLogins: EntityType: EntitySet'IdentityUserLogin'基于'IdentityUserLogin'类型,它没有键的定义。
  • IdentityUserRoles: EntityType: EntitySet'IdentityUserRoles'基于'IdentityUserRole'类型,它没有键定义。

当我清楚地在所有这些上使用HasKey方法时…

请帮忙!

谢谢。

如何在EF 6中引用自定义IdentityUser类的外键

你的代码中有2个DB上下文,所以你的程序最终有2个独立的DB。您的配置也适用于其他DB。如果您想要1个DB,只需将public DbSet<Expense> Expenses { get; set; }移动到ApplicationDbContext。去除PacificPetExpensesDb类。

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("PacificPetEntities", throwIfV1Schema: false)
    {
    }
    public DbSet<Expense> Expenses { get; set; }
    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

那么你就不再需要OnModelCreating()方法了。

但是如果你真的需要2个单独的DB,你的第二个上下文必须继承IdentityDbContext<ApplicationUser>而不是DbContext