如何在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方法时…
请帮忙!
谢谢。
你的代码中有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
。