实体框架多对多映射

时间:2016-09-01 12:48:55

标签: c# entity-framework

我正在转向实体框架,作为我正在开发的ASP.Net MVC应用程序的一部分。使用代码优先,我正在尝试为用户角色列表提供简单的多对多映射。

我有以下类(和相关的数据库表)

public class User 
{
    public int UserID { get; set; }
    public string EmailAddress { get; set; }
    // etc...

    public virtual ICollection<Role> Roles { get; set; }
}

public class Role
{
    public int RoleID { get; set; }
    public string RoleName { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

public class UserRoles
{
    public int UserRoleID { get; set; }
    public int UserID { get; set; }
    public int RoleID { get; set; }
}

OnModelCreating覆盖,用于映射多对多关系...

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasMany<Role>(u => u.Roles)
        .WithMany(r => r.Users)
        .Map(ur => {
            ur.MapLeftKey("UserID");
            ur.MapRightKey("RoleID");
            ur.ToTable("UserRoles");
        });
}

public DbSet<User> Users { get; set; }

对用户进行身份验证后,我会将当前经过身份验证的User对象作为自定义IPrincipal实现的一部分提供。

public class MyPrincipal : IPrincipal
{ 
    // User attached to this custom IPrincipal
    public User User { get; set; }
}

以及User

Global.asax可用的身份验证请求阶段
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    // Get the FormsAuthentication cookie
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

        // If the cookie exists
        if (authCookie != null)
        {
            // Get the authentication ticket
            FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            var identity = new GenericIdentity(authTicket.Name, "Forms");
            var principal = new WebStoresPrincipal(identity);

            // Get the userdata from the ticket
            string userData = ((FormsIdentity)(Context.User.Identity)).Ticket.UserData;

            // Deserialize the JSON data
            var serializer = new JavaScriptSerializer();
            principal.User = (User)serializer.Deserialize(userData, typeof(User));

            // Set the context user
            Context.User = principal;
        }

}

然而 - 也许这就是我无法正确理解或完全忽略这一点的地方 - 当我尝试访问分配了Roles的{​​{1}}时,它是一个空集合而我曾期望实体框架填充User集合。

所以,鉴于我有以下数据:

Roles
RoleID,名称
1,管理员
2,贡献者
3,校对读取器

Roles
用户ID,名称等 1,鲍勃史密斯 2,Joe Bloggs

Users
UserRoleID,UserID,RoleID
1,1,1 2,2,3

我希望期待如果我查看为UserRoles 1返回的数据,我会看到User集合包含Roles个角色的单个条目

显然,我在这里遗漏了一些基本的东西,但是已经在数十个网站上搜寻过,除了设置多对多之外没什么可解释的。

1 个答案:

答案 0 :(得分:2)

在我看来,您从故障单反序列化的User对象没有附加到数据库。然后,EF不会将角色表中的角色加载到此对象中。

尝试从DbContext加载用户。

// after "Deserialize the JSON data"
var loadedUser = dbContext.Users.Find(principal.User.UserId);

此对象应具有已填充的角色集合。