用户具有系统角色 - 如何(对象)模型三元关系?

时间:2013-04-20 11:59:25

标签: c# entity-framework entity-framework-5

我有以下实体:

Privilege ( Id, Name )
Role ( Id, Name, ICollection<Privilege> )
System ( Id, Name )

User ( Id, Name, Pass, ? )

现在我想建模“一个用户可能拥有零个或多个系统中的每一个零个或多个角色”,例如:

IDictionary<System, ICollection<Role>> SystemRoles { get; set; }

ASP.NET EntityFramework可以实现吗?如果有,怎么样?我需要设置什么属性?

现在已经考虑了很长一段时间,但我没有在网上找到任何有用的“实体框架代码第一个三元关系”

你能指点我一些很好的链接吗?或者也许给我一个提示如何建模/我可以把哪些属性放在字典上?

其他问题:如果IDictionary解决方案以某种方式工作,是否有任何更改以获得更改跟踪代理性能? IDictionary不是ICollection ......

1 个答案:

答案 0 :(得分:1)

  

用户可能拥有零个或多个系统中的每个系统零个或多个角色

您需要一个描述三者之间关系的实体:

public class UserSystemRole
{
    public int UserId { get; set; }
    public int SystemId { get; set; }
    public int RoleId { get; set; }

    public User User { get; set; }
    public System System { get; set; }
    public Role Role { get; set; }
}

我会从所有三个属性创建一个复合主键,因为每个组合可能只出现一次而且必须是唯一的。密钥的每个部分都是相应导航属性UserSystemRole的外键。

然后其他实体将拥有引用此“链接实体”的集合:

public class User
{
    public int UserId { get; set; }
    //...
    public ICollection<UserSystemRole> UserSystemRoles { get; set; }
}

public class System
{
    public int SystemId { get; set; }
    //...
    public ICollection<UserSystemRole> UserSystemRoles { get; set; }
}

public class Role
{
    public int RoleId { get; set; }
    //...
    public ICollection<UserSystemRole> UserSystemRoles { get; set; }
}

然后使用Fluent API的映射如下所示:

modelBuilder.Entity<UserSystemRole>()
    .HasKey(usr => new { usr.UserId, usr.SystemId, usr.RoleId });

modelBuilder.Entity<UserSystemRole>()
    .HasRequired(usr => usr.User)
    .WithMany(u => u.UserSystemRoles)
    .HasForeignKey(usr => usr.UserId);

modelBuilder.Entity<UserSystemRole>()
    .HasRequired(usr => usr.System)
    .WithMany(s => s.UserSystemRoles)
    .HasForeignKey(usr => usr.SystemId);

modelBuilder.Entity<UserSystemRole>()
    .HasRequired(usr => usr.Role)
    .WithMany(r => r.UserSystemRoles)
    .HasForeignKey(usr => usr.RoleId);

如果您不需要,可以删除其中一个集合属性(使用不带参数的WithMany())。

修改

为了获得一个用户的字典,你可以引入一个帮助属性(readonly而不是映射到数据库),如下所示:

public class User
{
    public int UserId { get; set; }
    //...
    public ICollection<UserSystemRole> UserSystemRoles { get; set; }

    public IDictionary<System, IEnumerable<Role>> SystemRoles
    {
        get
        {
            return UserSystemRoles
                .GroupBy(usr => usr.System)
                .ToDictionary(g => g.Key, g => g.Select(usr => usr.Role));
        }
    }
}

请注意,您需要首先加载UserSystemRoles属性,然后才能访问此词典。或者将UserSystemRoles属性标记为virtual以启用延迟加载。