我的数据库中有一个自定义用户表,我想与aspnetusers表创建一对一的关系,这样当我注册一个新客户时,通过UserManager的applicationuser类应该添加用户名,电子邮件,密码和学校代码到users表,并在自己的表中添加fk。是否有任何教程/示例实现这种情况?
我正在尝试与我的用户表添加一对一的关系,但fk与pk不同
ASPNETUsers表[标准列]
我在 ApplicationUser 类
中添加了属性public class ApplicationUser : IdentityUser
{
public virtual User user { get; set; }
public int UserID { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>()
.HasRequired(i => i.user).WithRequiredDependent(i => i.appUser);
}
}
public class User
{
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public virtual ApplicationUser appUser { get; set; }
}
我还需要做什么,是否正确? entityframework如何与这个一起工作?
更新 在运行它时给我错误 MySql.Data.MySqlClient.MySqlException:未知列&#39; Extent8.appUser_Id&#39;在&#39; on条款&#39;
如果我定义
modelBuilder.Entity<ApplicationUser>().HasKey(u => u.UserID);
在 OnModelCreating 中,它会尝试通过此UserID和当前崩溃链接AspNetRoles和Claims etc表。
ApplicationUser_Claims_Source_ApplicationUser_Claims_Target ::参照约束的从属角色中的所有属性的类型必须与主体角色中的相应属性类型相同。属性类型&#39; UserId&#39;在实体&#39; IdentityUserClaim&#39;与财产类型不匹配&#39; UserID&#39;在实体&#39; ApplicationUser&#39;在参考约束&#39; ApplicationUser_Claims&#39;。 ApplicationUser_Logins_Source_ApplicationUser_Logins_Target ::参照约束的从属角色中的所有属性的类型必须与主体角色中的相应属性类型相同。属性类型&#39; UserId&#39;在实体&#39; IdentityUserLogin&#39;与财产类型不匹配&#39; UserID&#39;在实体&#39; ApplicationUser&#39;在引用约束&#39; ApplicationUser_Logins&#39;。 ApplicationUser_Roles_Source_ApplicationUser_Roles_Target ::参照约束的从属角色中的所有属性的类型必须与主体角色中的相应属性类型相同。属性类型&#39; UserId&#39;实体&#39; IdentityUserRole&#39;与财产类型不匹配&#39; UserID&#39;在实体&#39; ApplicationUser&#39;在参考约束&#39; ApplicationUser_Roles&#39;。
答案 0 :(得分:1)
使用一对一关系时,实体框架使用子项中父项的Id
列作为父项的FK,它不会创建第二列FK,因为那将被视为一对多关系,因为第二列将允许父{4}存在于许多子条目中,而PK作为FK则不会。< / p>
由于Id
继承自ApplicationUser
,它将使用现有的属性和关系。它已经定义了IdentityUser
列,因此不必创建Id
,也不必尝试将UserId
设为键属性。您应该使用现有的UserId
列,默认情况下为Id
,并且您现有的string
表看起来有User
PK,因此它们不匹配。
但是,这不是世界末日。 Identity的内置实现使用integer
作为其类的键( AspNetUsers,AspNetRoles等...... ),但它们允许我们使用其他类型的主键。
Identity为每个表定义了两个类,因此有两个string
类,两个IdentityUser
,依此类推。一个是基础泛型类,它接受一些泛型。另一个是该基类的内置实现,它提供这些泛型类型。
此基类如下所示:
IdentityRole
第一个泛型类型是public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
where TLogin : IdentityUserLogin<TKey>
where TRole : IdentityUserRole<TKey>
where TClaim : IdentityUserClaim<TKey>
,它定义了键的类型,即TKey
。第二个是string
,它是TLogin
,这意味着它应该是某个继承IdentityUserLogin<TKey>
的类,使用与密钥相同的IdentityUserLogin
类型(也许TKey
},也许是string
)。
同时,这些基类的内置实现如下所示:
int
将public class IdentityUser
: IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string> {}
定义为TKey
以用作关键字。其他泛型,如string
和IdentityUserLogin
,是内置类,实现了IdentityUserRole
键的基类。看看string
的样子:
IdentityUserRole
请参阅? public class IdentityUserRole IdentityUserRole<string> {}
也是如此。许多其他类使用string
作为string
的默认值。
所以,如果你要像这样改变你的课程:
TKey
它还不行,因为我们将public class ApplicationUser : IdentityUser<int, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
{
public virtual User user { get; set; }
}
更改为TKey
,但内置的int
仍使用IdentityUserLogin
。所以我们需要像这样创建自己的string
:
IdentityUserLogin
...并像这样使用它:
public class MyNiceUserLogin : IdentityUserLogin<int>
{
}
...但我们仍然需要对public class ApplicationUser : IdentityUser<int, MyNiceUserLogin, IdentityUserRole, IdentityUserClaim>
{
public virtual User user { get; set; }
}
和IdentityUserRole
等其他类做同样的事情。
IdentityUserClaim
。那么一对一的关系呢?您的代码在这里:
int
......工作正常。您的配置方式是必须,没有protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>()
.HasRequired(i => i.user).WithRequiredDependent(i => i.appUser);
}
没有ApplicationUser
,反之亦然。
现在,我建议您阅读this Stack Overflow answer以确切了解要更改Identity的类以使用User
作为关键字要遵循的步骤。
我强烈建议您阅读John Atten的this post,所以 可以深入了解如何定制/扩展身份。