Entity Framework:有效检索数据(多对多关系)
Entity Framework: retrieving data effectively (many to many relationships)
我正在使用 Entity Framework 构建一个简单的身份验证模型。
我创建了四个 table:User
、Group
、Role
和 GroupUsers
。
结构如下所示(为简单起见,我将从 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();
我正在使用 Entity Framework 构建一个简单的身份验证模型。
我创建了四个 table:User
、Group
、Role
和 GroupUsers
。
结构如下所示(为简单起见,我将从 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();