0
votes

I have been having this problem for a week now. I've searched multiple sources on the web and Stackoverflow about referencing a foreign key of your model to IdentityUser class in Entity Framework 6 (EF 6).

I've tried many different variations of setting up my DbContext, Model, custom IdentityUser classes.

Lastly, I've tried adding OnModelCreating while implementing the HasKey method for IdentityUserLogin, IdentityRole, and IdentityUserRole.

Here is the code I currently have:

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; }

    }

Configuration

 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; }



    }

My Model

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.");
            }
        }

    }

Everytime I run any variation of my Entity Framework code, I get this error message:

One or more validation errors were detected during model generation:

  • PacificPetExpenses.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
  • PacificPetExpenses.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
  • IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
  • IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.

When I've clearly, used the HasKey method on all these...

Please help!

Thank you.

1
Don't try to configure the identity tables since that is handled in the base class. Your options are to either use a single context that inherits from IdentityDbContext as Sam suggests below, or another option is add a copy of the ApplicationUser class (that doesn't inherit from IdentityUser) into your app context with all the needed properties, DbSet etc. - Steve Greene

1 Answers

1
votes

You have 2 DB context in your code so your program ended up with 2 separate DB. And your configuration applies to other DB. If you want 1 DB simply move public DbSet<Expense> Expenses { get; set; } to ApplicationDbContext. and remove PacificPetExpensesDb class.

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

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

}

Then you don't need OnModelCreating() method anymore.

But if you really need 2 separate DB your second context must inherit from IdentityDbContext<ApplicationUser> instead of DbContext.