自定义和集成自己的数据库与 mvc5 身份



我正在处理一个 MVC 项目,该项目需要使用 Identity 创建身份验证和授权,我的项目数据库还包括应该使用该系统的主要实体,处理这种情况的最佳实践是什么。

  1. 我是否应该根据我的要求自定义标识应用程序用户。
  2. 创建我自己的表(模型)并将它们与标识表集成,我不知道该怎么做。 或任何其他解决方案。

当然,您应该自定义标识实体,因为这是创建标识的全部原因:允许更大的可扩展性。要拥有不同类型的"用户",您应该从ApplicationUser继承;重要的是,不是直接来自IdentityUser。这将确保核心标识关系(角色、声明、登录名等)都绑定到单个"用户"表,同时你可以扩展该表或创建其他表来保存其他用户数据。

public class ApplicationUser : IdentityUser
public class Student : ApplicationUser
public class Instructor : ApplicationUser

默认情况下,此继承将由 TPH(每个层次结构的表)实现,也称为 STI(单表继承)。这意味着所有派生类的所有属性都将由单个数据库表上的列表示。还将添加一个Discriminator列,该列将保存实际保存的班级的名称,即"应用程序用户"、"学生"或"教师"。EF 在从查询生成对象图以实例化正确的"用户"类型时,将使用此列。

这种方法有利有弊。由于所有内容都存在于单个表中,因此查询既简单又快速。但是,此方法要求每个派生类上的所有属性在数据库级别必须为空。显而易见的原因是,如果Instructor具有必需的列,您将无法保存Student,因为Student没有满足该要求的属性。您仍然可以使用视图模型强制要求在视图级别需要属性。但是,数据库中的实际列必须为空。

另一种方法是使用所谓的 TPT(每个类型的表)。在这个继承策略中,将为基类(ApplicationUser)创建一个具有所有公共属性的表。然后,将为每个离散派生类创建一个表,仅包含该类上存在的属性。外键将添加到基类的表中,然后 EF 将使用该外键将该表中的公共数据联接到派生类表上的特定数据。此方法允许您在数据库级别强制实施 NOT NULL,但它当然需要联接来引入所有数据,这可能会减慢查询速度。

若要实现 TPT,只需将[Table]注释添加到派生类:

[Table("Students")]
public class Student : ApplicationUser
[Table("Instructors")]
public class Instructor : ApplicationUser

最后需要注意的一件事是您需要如何利用UserManager.如果您搭建了基架AccountController,您会注意到它设置了一个UserManager控制器属性,然后使用该属性创建用户、查找用户、更改密码等。这实际上是UserManager<ApplicationUser>的一个实例,因为它是一个泛型类型。如果您需要专门使用StudentInstructor,则需要分别实例化UserManager<Student>UserManager<Instructor>。不能使用UserManager<ApplicationUser>实例,因为它会将派生类型向上转换为ApplicationUser。例如:

var student = new Student { ... };
await UserManager.CreateAsync(student);

实际上会导致ApplicationUser被保存到数据库中。特定于学生的数据将被丢弃,Discriminator列的值将为"应用程序用户"。

相关内容

  • 没有找到相关文章

最新更新