Entity Framework:有效检索数据(多对多关系)

Entity Framework: retrieving data effectively (many to many relationships)

我正在使用 Entity Framework 构建一个简单的身份验证模型。 我创建了四个 table:UserGroupRoleGroupUsers

结构如下所示(为简单起见,我将从 table 中删除不相关的字段。

用户 table

public class User
{
    public int Id {get; set;}
    public string UserName {get; set;}
    public string Password {get; set;}
    public ICollection<Group> Groups { get; set; }
}

群组 table

public class Group
{
    public int Id {get; set;}
    public string Name {get; set;}
    public ICollection<User> Users{ get; set; }   <- many to amny relationship
    public ICollection<Role> Roles { get; set; }  <- aone to Many relationship
}

角色 table

public class Role
{
    public int Id {get; set;}
    public string Name {get; set;}
    public Group Group {get; set;}
    public int GroupId {get; set;}
}

GroupUsers table(保持多对多关系)

public class GroupUsers
{
    public ICollection<User> Users { get; set; }
    public ICollection<Group> Groups { get; set; }
}

我的目标是检索用户可以执行的角色,因此我使用以下代码:

SOContext.Users
         .Include(g => g.Groups.Select(role => role.Roles))
         .Where(user => user.Id == id)
         .FirstOrDefault();    // here id is the user's id

然而,当我 运行 代码并检查 SQL 分析器时,它导致了一个非常复杂的 SQL!虽然我希望看到一个简单的左连接脚本!

exec sp_executesql N'SELECT 
[Project2].[Id] AS [Id], 
[Project2].[UserName] AS [UserName], 
[Project2].[Password] AS [Password], 
[Project2].[Name] AS [Name], 
[Project2].[Gender] AS [Gender], 
[Project2].[Email] AS [Email], 
[Project2].[EmailConfirmed] AS [EmailConfirmed], 
[Project2].[Mobile] AS [Mobile], 
[Project2].[MobileConfirmed] AS [MobileConfirmed], 
[Project2].[ActiveAccount] AS [ActiveAccount], 
[Project2].[C2] AS [C1], 
[Project2].[GroupId] AS [GroupId], 
[Project2].[UserId] AS [UserId], 
[Project2].[Id1] AS [Id1], 
[Project2].[Name1] AS [Name1], 
[Project2].[Description] AS [Description], 
[Project2].[C1] AS [C2], 
[Project2].[Id2] AS [Id2], 
[Project2].[Name2] AS [Name2], 
[Project2].[Description1] AS [Description1], 
[Project2].[GroupId1] AS [GroupId1]
FROM ( SELECT 
    [Limit1].[Id] AS [Id], 
    [Limit1].[UserName] AS [UserName], 
    [Limit1].[Password] AS [Password], 
    [Limit1].[Name] AS [Name], 
    [Limit1].[Gender] AS [Gender], 
    [Limit1].[Email] AS [Email], 
    [Limit1].[EmailConfirmed] AS [EmailConfirmed], 
    [Limit1].[Mobile] AS [Mobile], 
    [Limit1].[MobileConfirmed] AS [MobileConfirmed], 
    [Limit1].[ActiveAccount] AS [ActiveAccount], 
    [Join2].[GroupId1] AS [GroupId], 
    [Join2].[UserId] AS [UserId], 
    [Join2].[Id1] AS [Id1], 
    [Join2].[Name1] AS [Name1], 
    [Join2].[Description1] AS [Description], 
    [Join2].[Id2] AS [Id2], 
    [Join2].[Name2] AS [Name2], 
    [Join2].[Description2] AS [Description1], 
    [Join2].[GroupId2] AS [GroupId1], 
    CASE WHEN ([Join2].[GroupId1] IS NULL) THEN CAST(NULL AS int) WHEN ([Join2].[Id2] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
    CASE WHEN ([Join2].[GroupId1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
    FROM   (SELECT TOP (1) 
        [Extent1].[Id] AS [Id], 
        [Extent1].[UserName] AS [UserName], 
        [Extent1].[Password] AS [Password], 
        [Extent1].[Name] AS [Name], 
        [Extent1].[Gender] AS [Gender], 
        [Extent1].[Email] AS [Email], 
        [Extent1].[EmailConfirmed] AS [EmailConfirmed], 
        [Extent1].[Mobile] AS [Mobile], 
        [Extent1].[MobileConfirmed] AS [MobileConfirmed], 
        [Extent1].[ActiveAccount] AS [ActiveAccount]
        FROM [dbo].[Users] AS [Extent1]
        WHERE [Extent1].[Id] = @p__linq__0 ) AS [Limit1]
    LEFT OUTER JOIN  (SELECT [Extent2].[GroupId] AS [GroupId1], [Extent2].[UserId] AS [UserId], [Extent3].[Id] AS [Id1], [Extent3].[Name] AS [Name1], [Extent3].[Description] AS [Description1], [Extent4].[Id] AS [Id2], [Extent4].[Name] AS [Name2], [Extent4].[Description] AS [Description2], [Extent4].[GroupId] AS [GroupId2]
        FROM   [dbo].[GroupUsers] AS [Extent2]
        INNER JOIN [dbo].[Groups] AS [Extent3] ON [Extent3].[Id] = [Extent2].[GroupId]
        LEFT OUTER JOIN [dbo].[Roles] AS [Extent4] ON [Extent3].[Id] = [Extent4].[GroupId] ) AS [Join2] ON [Limit1].[Id] = [Join2].[UserId]
)  AS [Project2]
ORDER BY [Project2].[Id] ASC, [Project2].[C2] ASC, [Project2].[GroupId] ASC, [Project2].[UserId] ASC, [Project2].[Id1] ASC, [Project2].[C1] ASC',N'@p__linq__0 int',@p__linq__0= 1

我是不是漏掉了什么?

谁能推荐一种有效(有利于性能)的方法来获取用户的角色?

首先你必须修复 GroupUsers

public class GroupUser
{
    public int UserId {get; set;}
      public int GroupId {get; set;}
    public virtual User User { get; set; }
    public virtual Group> Group { get; set; }
}

和查询

var userRoles=  (from r in  SOContext.Roles
                join gu in SOContext.GroupUsers on r.GroupId equals gu.GroupId
                 where  (gu.UserId == id)
                 select r ).ToList();