EF 6,Identity 2,ASP.NET MVC 5,代码优先
我的应用程序使用Identity来管理用户;我有标准的ApplicationUser
,添加了一些属性:
public class ApplicationUser : IdentityUser
{
// public async Task<ClaimsIdentity> GenerateUserIdentityAsync ...
public int SchoolId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return String.Format("{0} {1}", FirstName, LastName); }
}
public virtual School School { get; set; }
}
我还使用了两个角色:admin
和teacher
。大多数用户将具有teacher
角色,有些用户具有admin
角色。甚至在某些情况下,两个角色或两者都不应用于某个给定用户。
我还有一个Teacher
模型,如下所示:
public class Teacher
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return String.Format("{0} {1}", FirstName, LastName); }
}
public int SchoolId { get; set; }
public virtual School School { get; set; }
public virtual ICollection<TeacherAssignment> Assignments { get; set; }
}
这种模式有助于将教师与各自的学校以及他们所教授的课程部分联系起来。访问数据库中的教师很简单:
public DbSet<Teacher> Teachers { get; set; } // teacher access
...
contextInstance.Teachers // get the current teachers
到目前为止一切都很好。我可以在各自的视图中管理用户及其角色,以及管理教师。我的问题是代码重复,并增加了在两个地方维护一个老师的开销。此外,教师可能会停止教学,但仍然是用户,也许是管理员。相反,现有用户可能也需要成为一名教师。
我解决问题的想法:
1) 修改Teacher
模型以扩展ApplicationUser
,删除Teacher
中的重复属性。无重复,直接访问。但teacher
的角色有点多余。此外,用户可能不再是教师,因此必须删除教师记录;相反,必须创建一个教师记录来伴随现有用户。所有教师都是用户,但并非所有用户都是教师。
2) 保留Teacher
模型,但将其连接到ApplicationUser
实例:
public class Teacher {
public int Id { get; set; }
public int ApplicationUserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
单独管理教师的一些开销,以及相应角色的一些冗余,但可以很容易地从用户变成匹配的教师,反之亦然。同样简单的教师检索,没有找回非教师的危险。并非所有用户都有匹配的教师记录。
3) 删除Teacher
模型和相关数据访问,并检索teacher
角色中的用户。这使适当用户的检索稍微复杂一些;前面显示的教师检索查询可以用对助手函数的调用来代替:
// within a class that receives a reference to the context
public IEnumerable<ApplicationUser> Teachers
{
get
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(_context));
var role = roleManager.FindByName("teacher");
var roleId = role.Id;
var users = Users.Where(u => u.Roles.Any(r => r.RoleId == roleId));
return users;
}
}
无重复或添加管理。用户不是活跃的教师?将用户从teacher
角色中删除,或将用户添加到该角色以获得另一位教师。对代码的影响应该是最小的,从直接访问改为使用helper函数。
我的感觉是选项#3是更好的,因为它消除了重复,不需要单独的视图来管理另一种用户类型,并且应该易于实现。#3看起来是理想的路线吗?或者还有其他更好的选择吗?
为什么需要Teacher
类?会有Teacher
不是用户吗?
即使会有,通过将此属性public virtual ICollection<TeacherAssignment> Assignments { get; set; }
添加到ApplicationUser
类,也不会丢失任何内存。无论哪种方式,它都将被转换为新表(TeacherId、AssignmentId)。
如果以后你决定Admin也可以分配给你可以使用的东西。在我看来,这一个字段更多不值得新类,而且它会使数据库中的它复杂化。