本文写于2016年10月31日,因为只是在学习过程中的一些记录,当时觉得公开发布的话可能还不太完善,于是只放到了 blogspot 上,现在发现 Google 基本已经不管 blogspot 了,也不会支持 Markdown,于是还是搬到简书上来吧。
使用项目样例
创建空项目并安装样例
首先可以创建一个空项目,然后使用Nuget命令行
Install-Package Microsoft.AspNet.Identity.Samples -Pre
将项目转换为相关样例,官方网址为:
https://www.nuget.org/packages/Microsoft.AspNet.Identity.Samples
修改数据库连接
样例的数据库使用了自带的 LocalDB,如果有 SQL Server 的环境,可以在 Web.config 中创建一个相关连接,然后在 IdentityModels.cs 文件中将连接改为相应的连接名。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("EntityModel", throwIfV1Schema: false)
{
}
...
}
上面使用官方样例在 VS2015 下会不成功,不知道是否与环境有关,如果这样的话,直接创建一个带个人验证的项目也是可以的,基本的用户体系功能也会有。
创建默认用户数据库与已存在数据一对一的关系
修改数据库属性
假设已经存在名字为 Staff 的数据库表,Identity 模块自动创建的用户表为 AspNetUsers,为了将两个表创建一对一的关系,需要对数据进行修改,为了避免系统创建的 AspNetUsers 表因为修改而产生未知的错误,决定修改 Staff 表。
而关于在 SQL Server 中创建表关系在 StackOverflow上有这么一个回答表述得很好:
Any relationship requires that the "parent" table (the one side) have a Primary (or unique) Key (PK), that uniquely identifies each row, and the "child" table (the other side) have a Foreign Key column or columns, that must be populated with values that are the same as some existing value[s] of the Primary Key in the parent table. If you want a one to many (1-M) relationship then the Foreign Key should be an ordinary attribute (column or columns) in the child table that can repeat (there can be many rows with the same value)
If you want a one to one (1-1) relationship then the Foreign key should itself be a Primary Key or unique index in the child table that guarantees that there may be at most one row in the child table with that value.
A 1-1 relationship effectively partitions the attributes (columns) in a table into two tables. This is called vertical segmentation. This is often done for sub-classing the table entities, or, for another reason, if the usage patterns on the columns in the table indicate that a few of the columns need to be accessed significantly more often than the rest of the columns. (Say one or two columns will be accessed 1000s of times per second and the other 40 columns will be accessed only once a month). Partitioning the table in this way in effect will optimize the storage pattern for those two different queries.
Sub-Classing. The above actually creates a 1 to zero or one relationship, which is used for what is called a sub-class or subtype relationship. This occurs when you have two different entities that share a great number of attributes, but one of the entities has additional attributes that the other does not need. A good example might be Employees, and SalariedEmployees. The Employee table would have all the attributes that all employees share, and the SalariedEmployee table would exist in a (1-0/1) relationship with Employees, with the additional attributes (Salary, AnnualVacation, etc.) that only Salaried employees need.
If you really want a 1-1 relationship, then you have to add another mechanism to guarantee that the child table will always have one record for each record/row in the parent table. Generally the only way to do this is by enforcing this in the code used to insert data (either in a trigger, stored procedure or code outside the database). This is because if you added referential integrity constraints on two tables that require that rows always be in both, it would not be possible to add a row to either one without violating one of the constraints, and you can't add a row to both tables at the same time.
参见 http://stackoverflow.com/questions/5112473/designing-11-and-1m-relationships-in-sql-server
另外还有一篇文章举了不错的例子 http://www.tech-recipes.com/rx/56738/one-to-one-one-to-many-table-relationships-in-sql-server/
上面说了,我们准备在 Staff 表中进行一定的修改,首先创建一个字段用于作为 AspNetUsers 的外键: aspNetUserId,注意类型需要与要关联的另一个表的字段,即 Id 要相同,然后将这个字段设置为唯一的索引属性,但是你会发现这个设置并不能成功,因为唯一的属性需要这个字段上的值是不同的,而观察这个字段属性,发现勾选了允许为 null,但是如果去掉的话,显然不能成功,因为这个字段是新加入的列,上面是不能有值的,当然,你可以用Excel生成一个等差序列先将这个空白填上。
填充关联数据
刚才填充数据的那个操作只完成了一小半的工作,由于我们的最终目的是要关联两个表,因此我们需要真实的数据来进行表的数据是最科学,也是必须的。
由于 Identity2 默认的程序里已经自带了创建用户的功能,因此我们改造下程序,使用 Staff 表中的登录账号生成 AspNetUsers 的相关账号信息,然后将 AspNetUsers 的 Id 值同时保存至 Staff 新建字段 aspNetUserId 中即可(这里程序就不说了,很简单,看看代码就应该知道如何操作了)。
建立两个表的一对一关系
数据已经填充好,现在重复之前说的,将 Staff 中的字段 aspNetUserId 设置为唯一索引属性,然后在 Staff 创建关系,相关联的字段当然是 aspNetUserId 与 AspNetUsers 的 Id 字段,保存后即可看到两个表上出现了一对一的连接关系。