非常感谢有关如何在我自己的MVC5自定义类中使用ApplicationUser的一些指导。
简单模型,使用scaffolding创建控制器和视图,sm DbContext用于Internet应用程序模板中的默认ApplicationUser(IdentityUser)。我想使用ApplicationUser在事务中标记当时登录的人的详细信息。
当Entity Framework尝试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; }
}
Entity Framework尝试创建数据库时遇到的错误是:
{“在模型生成期间检测到一个或多个验证错误:\ r \ n \ r \ nMvcApplication1.Models.IdentityUserLogin :: EntityType'IdentityUserLogin'没有定义键。定义此EntityType的键。\ n r \ nMvcApplication1.Models.IdentityUserRole :: EntityType'IdentityUserRole'没有定义键。定义此EntityType的键。\ r \ nIdentityUserLogins:EntityType:EntitySet'IdentityUserLogins'基于没有键定义的类型'IdentityUserLogin'。\ r \ nIdentityUserRoles:EntityType:EntitySet'IdentityUserRoles'基于类型'IdentityUserRole',没有定义键。\ r \ n“}
由于Cascade on Delete导致的参照完整性(我可以覆盖DbContext以删除级联删除)
实现这一目标的最佳方法是什么?任何指导都将不胜感激。
答案 0 :(得分:2)
你的问题是你忘记打电话了
base.OnModelCreating(modelBuilder);
最重要的是你的方法,因为你说ApplicationDbContext是默认创建的,继承自IdentityDbContext。所以调用base.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”。
答案 1 :(得分:1)
我建议您使用ID
属性为[Key]
添加注释。
目前,根据您发布的第一个错误,EF无法找到表Example
的主键。
此外,如果您希望将来延迟加载CreatedBy
和ModifiedBy
,您还需要提及Id
,即使现在不是错误。这对未来可能很容易。
除此之外,还要继承ApplicationUser
班级的IdentityUser
班级和DbContext
班级的IdentityDbContext
班级。
清理项目,重建项目并查看是否发生任何错误。然后可能更容易解决它。
答案 2 :(得分:0)
正在为您的实体寻找[Key]
注释。您似乎错过了IdentityUserLogin
和IdentityUserRole
public class Person
{
[Key] // <--- this needs to be identified here or in the DbContext you setup
public Guid ID { get; set; }
}
答案 3 :(得分:0)
两个建议:
1 - 确保dbcontext派生自IdentityDbContext。
2 - 根据您的模型,您可以在用户和其他实体之间建立关系。您的dbcontext DBSet语句如何显示?你有用户的dbset吗? (这意味着您假设管理用户而不是IdentityFramework)。如果您没有为您的用户提供DBSet,那么我同意Ashish的陈述,身份实体的上下文可能与您的其他实体的上下文不同,这会产生问题。
如果您可以发布上下文类的基础知识,我们可能会告诉您更多
答案 4 :(得分:0)
我已经决定发布一个有效的答案,但我仍然不相信它是最干净的答案,并且很想知道是否有人有更好的方法来做到这一点。
让我这样做的答案是覆盖OnModelCreating()
中的ApplicationDbContext: IdentityDbContext
并使用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
现在这样做。建议非常欢迎。