真的很感激如何在MVC5中使用我自己的自定义类中的ApplicationUser的一点指导。
简单的模型,使用脚手架创建控制器和视图,为Internet Application模板中的默认ApplicationUser (IdentityUser)创建DbContext。我想使用ApplicationUser用当时登录者的详细信息标记事务。
当实体框架试图DropAndRecreateAlways
时,我得到两个数据库错误之一首先是我的班级:
public class Example
{
public int ID { get; set; }
[Required]
public string Description { get; set; }
[Required]
public double Amount { get; set; }
[Required]
public virtual ApplicationUser CreatedBy {get; set;}
[Required]
public virtual ApplicationUser ModifiedBy { get; set; }
}
当实体框架试图创建数据库时我得到的错误是:
{"在模型生成过程中检测到一个或多个验证错误:rnr nmvapplication1 . models . "IdentityUserLogin:: EntityType 'IdentityUserLogin'没有定义密钥。定义这个EntityType的键。IdentityUserRole:: EntityType 'IdentityUserRole'没有定义键。定义这个EntityType的键。rnIdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins'基于类型'IdentityUserLogin',没有定义密钥。rnIdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles'是基于类型'IdentityUserRole',没有定义键。rn"}
由于级联删除导致的引用完整性(我可以覆盖DbContext来删除级联删除)
实现这一目标的最佳方法是什么?
你的问题是你忘记打电话了
base.OnModelCreating(modelBuilder);
在你的方法上,因为就像你说的ApplicationDbContext是默认从IdentityDbContext继承创建的。呼叫基数。OnModelCreating,让你的基类如IdentityDbContext,生成所有你需要的。
但是如果你仍然想使用流畅的API,为这两个实体创建键的正确方法是
modelBuilder.Entity<IdentityUserLogin>().HasKey(t => new { t.UserId, t.ProviderKey, t.LoginProvider });
modelBuilder.Entity<IdentityUserRole>().HasKey(t => new { t.RoleId, t.UserId });
如果不这样做,调用UserManager的AddToRole(userid, rolename)方法将抛出一个异常,需要您添加的额外键,并带有消息"字段userid或RoleId是必需的"。
我建议您用[Key]
属性注释您的ID
。目前EF找不到表Example
的主键基于你发布的第一个错误。
同样,如果您想在将来延迟加载CreatedBy
和ModifiedBy
,您还需要提及Id
,即使这现在不是一个错误。
除此之外,还从IdentityUser
类继承ApplicationUser
类,从IdentityDbContext
类继承DbContext
类。
清理项目,重新构建它,看看是否发生任何错误。这样解决起来就容易多了
它正在为您的实体寻找[Key]
注释。看起来你缺少一个IdentityUserLogin
和IdentityUserRole
public class Person
{
[Key] // <--- this needs to be identified here or in the DbContext you setup
public Guid ID { get; set; }
}
两个建议:
1 -确保你的dbcontext从IdentityDbContext派生。
2 -基于你的模型,你有用户和你的其他实体之间的关系。您的dbcontext DBSet语句看起来如何?您为您的用户准备了数据库吗?(这意味着您正在假设管理用户而不是IdentityFramework)。如果您没有为您的用户设置DBSet,那么我同意Ashish的说法,Identity实体的上下文可能与您的其他实体的上下文不同,这将产生问题。
如果你能张贴你的上下文类的基本知识,我们可能能够告诉更多
我已经决定发布一个有效的答案,但是我仍然不相信这是最干净的答案,并希望听到是否有人有更好的方法来做到这一点。
我要做到这一点的答案是在ApplicationDbContext: IdentityDbContext
中覆盖OnModelCreating()
,并使用Fluent API将IdentityUserLogin
和IdentityUserRole
的属性标记为[Key]
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<IdentityUserLogin>().HasKey(t => t.UserId);
modelBuilder.Entity<IdentityUserRole>().HasKey(t => t.UserId);
}
我不认为这是一个很好的解决方案,因为EF Code First现在在我的IdentityUserLogin
和IdentityUserRole
表,UserId
和User_Id
中创建了两列。
现在就可以了。