asp.net 核心身份用户自定义
asp.net core Identity user customization
详情
我正在使用 Identity 在 asp.net 核心中开发 Web 应用程序。现在在我的应用程序中我有两种用户。客户和合作伙伴都有不同的个人资料信息和登录 scenario.customer 可以从网页简单注册登录,但合作伙伴可以从不同的视图使用不同的必填字段注册。
问题
- 如何设计 Schema。
- 在这种情况下有哪些好的做法。
- 缺点是什么
代码
这是我目前所做的
public class ApplicationUser : IdentityUser
{
public CustomerProfile CustomerProfile { get; set; }
}
使用继承:
public class ApplicationUser : IdentityUser {}
public class Customer : ApplicationUser
{
// Customer-specific properties
}
public class Partner : ApplicationUser
{
// Partner-specific properties
}
默认情况下,这将通过 STI(single-table 继承)实现。这意味着您将只有标准的 AspNetUsers table 包含 ApplicationUser
和所有派生类型的属性列。将添加一个鉴别器列以指示实际保存的类型,然后在查询时将用于实例化正确的类型。
在大多数情况下,这工作得很好。一个缺点是派生的 classes 上的属性必须 可以为空。原因很简单:不可能在保存 Partner
的同时为 Customer
列提供值,反之亦然。但是,属性只需要在 database-level 处可以为空。您仍然可以要求通过视图模型在表单中设置它们。
替代方法是使用 TPT (table-per-type)。使用这种方法,您将获得 AspNetUsers,还有客户和合作伙伴 table。但是,派生类型的 tables 将具有仅对应于特定于该类型的属性的列和返回 AspNetUsers 的外键。所有公共属性都存储在那里。有了这个,您现在可以强制列在 database-level 处具有值,但查询用户将需要连接。要使用 TPT,您只需将 Table
属性分别添加到 class,即 [Table("Customers")]
和 [Table("Partners")]
。
不过,使用继承时要牢记的一件重要事情是,您需要使用您实际想要保留的类型。如果您保存一个 ApplicationUser
实例,它将是一个 ApplicationUser
,而不是 Customer
或 Partner
。在这方面,您需要小心使用正确的类型,例如 UserManager
通常引用用户类型。即使您创建了 Customer
的实例,如果您通过 UserManager<ApplicationUser>
的实例保存它,它也会向上转换为 ApplicationUser
并且 that 是什么将被坚持。要创建新的 Customer
,您需要一个 UserManager<Customer>
的实例。同样,对于合作伙伴。
但是,这也对您有利,例如,如果您尝试从 UserManager<Customer>
的实例中查找用户,您只会找到他们实际上是 Customer
.这样一来,拥有单独的门户就变得非常简单,只有一个或另一个可以登录,正如您所指出的那样。
详情
我正在使用 Identity 在 asp.net 核心中开发 Web 应用程序。现在在我的应用程序中我有两种用户。客户和合作伙伴都有不同的个人资料信息和登录 scenario.customer 可以从网页简单注册登录,但合作伙伴可以从不同的视图使用不同的必填字段注册。
问题
- 如何设计 Schema。
- 在这种情况下有哪些好的做法。
- 缺点是什么
代码
这是我目前所做的
public class ApplicationUser : IdentityUser
{
public CustomerProfile CustomerProfile { get; set; }
}
使用继承:
public class ApplicationUser : IdentityUser {}
public class Customer : ApplicationUser
{
// Customer-specific properties
}
public class Partner : ApplicationUser
{
// Partner-specific properties
}
默认情况下,这将通过 STI(single-table 继承)实现。这意味着您将只有标准的 AspNetUsers table 包含 ApplicationUser
和所有派生类型的属性列。将添加一个鉴别器列以指示实际保存的类型,然后在查询时将用于实例化正确的类型。
在大多数情况下,这工作得很好。一个缺点是派生的 classes 上的属性必须 可以为空。原因很简单:不可能在保存 Partner
的同时为 Customer
列提供值,反之亦然。但是,属性只需要在 database-level 处可以为空。您仍然可以要求通过视图模型在表单中设置它们。
替代方法是使用 TPT (table-per-type)。使用这种方法,您将获得 AspNetUsers,还有客户和合作伙伴 table。但是,派生类型的 tables 将具有仅对应于特定于该类型的属性的列和返回 AspNetUsers 的外键。所有公共属性都存储在那里。有了这个,您现在可以强制列在 database-level 处具有值,但查询用户将需要连接。要使用 TPT,您只需将 Table
属性分别添加到 class,即 [Table("Customers")]
和 [Table("Partners")]
。
不过,使用继承时要牢记的一件重要事情是,您需要使用您实际想要保留的类型。如果您保存一个 ApplicationUser
实例,它将是一个 ApplicationUser
,而不是 Customer
或 Partner
。在这方面,您需要小心使用正确的类型,例如 UserManager
通常引用用户类型。即使您创建了 Customer
的实例,如果您通过 UserManager<ApplicationUser>
的实例保存它,它也会向上转换为 ApplicationUser
并且 that 是什么将被坚持。要创建新的 Customer
,您需要一个 UserManager<Customer>
的实例。同样,对于合作伙伴。
但是,这也对您有利,例如,如果您尝试从 UserManager<Customer>
的实例中查找用户,您只会找到他们实际上是 Customer
.这样一来,拥有单独的门户就变得非常简单,只有一个或另一个可以登录,正如您所指出的那样。