【问题标题】:Entity Framework: retrieving data effectively (many to many relationships)实体框架:有效检索数据(多对多关系)
【发布时间】:2021-05-02 11:02:33
【问题描述】:

我正在使用实体框架构建一个简单的身份验证模型。 我创建了四个表:UserGroupRoleGroupUsers

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

用户

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

群组表格

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
}

角色

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

GroupUsers 表(保存多对多关系)

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

我错过了什么吗?

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

【问题讨论】:

    标签: c# .net entity-framework relational-database


    【解决方案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();  
    

    【讨论】:

    • 非常感谢,效果很好!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 2017-01-28
    • 2011-12-17
    • 1970-01-01
    相关资源
    最近更新 更多