[英]Return one column from a many-to-many join table in EF6
我需要以EF6中的多对多关系从联接表返回单个列
User { Id, Name}
Role { Id, Role}
UserToRole { UserId, RoleId}
这是一个简化的示例,但是我需要从用户那里获取RoleId的列表(Role.Id)。
理想情况下,我只会做类似的事情
context.UserToRole.Where(x => x.UserId == id).Select(r => r.RoleId).ToList();
但是EF似乎没有向我提供该连接表作为要查询的对象。
我知道我可以将所有角色都作为对象拉下来,但是在我的实际系统中,它是一个宽表,我想避免将所有数据拖入线路并将其放入内存的开销。
如果仅需要User
的RolesId
,则可以执行以下查询:
int userId=1;
var roleIds = db.Users.Where(u => u.Id == userId).SelectMany(u => u.Roles.Select(a=>a.Id));
这将生成一个这样的sql查询:
{SELECT [Extent1].[Role_Id] AS [Role_Id]
FROM [dbo].[UserRoles] AS [Extent1]
WHERE [Extent1].[User_Id] = @p__linq__0}
如您所见,是您要查找的相同查询。
您可以尝试context.Roles.SqlQuery("Select * from Roles where id in (select roleid from usertoroles where userid = @userid")
以避免加载用户。
如果您的问题是将所有角色分配给特定用户,则如下所示定义您的实体:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
//Navigation Property
public List<Role> Roles { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
//Navigation Property
public List<User> Users { get; set; }
}
除非您想控制多对多的表名和列名(这很简单),否则您就已经准备就绪。
创建用户
User k = new User()
{
UserName = "Kishan",
Roles = new List<Role>()
{
new Role() { Name = "Supremo" }
}
}
context.Users.Add(u);
context.SaveChanges();
User r = new User()
{
UserName = "Rama",
Roles = new List<Role>()
{
context.Roles.Single(r => r.Name == "Supremo")
}
}
context.SaveChanges();
查找用户角色
User u = context.Users.Single(u => u.UserName == "Kishan");
List<int> userRoleIdList = u.Roles.Select(r => r.Id).ToList();
关系应该已经存在:通常,如果您将双向的多对多关系定义为集合,则EF会为您生成联接表,这意味着您只需要聪明地设计LINQ查询即可:只是您可以看到的表格(有时会很棘手)。 (我从您的评论中认为“ EF似乎没有为您提供联接表”,确实是这种情况。)
因此,考虑到您给出的示例,结果将是这样的:
context.Users.Where(u => u.Id == id).Single().Roles.Select(r => r.Id);
警告:如果没有找到具有Id==id
或找到多个User
(因此, Id
不是密钥),将引发此警告。 但是,这通常正是您希望通过此类查询获得的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.