从EF6中的多对多连接表返回一列

时间:2015-03-15 06:14:28

标签: c# entity-framework entity-framework-6

我需要在EF6

中的多对多关系中从连接表返回单个列
User { Id, Name}
Role { Id, Role}
UserToRole { UserId, RoleId}

这是一个简化的示例,但我需要从User获取RoleId(Role.Id)的列表。

理想情况下,我只是做一些像

这样的事情
context.UserToRole.Where(x => x.UserId == id).Select(r => r.RoleId).ToList();

但EF似乎并没有向我提供该联接表作为查询对象。

我知道我可以将所有角色作为对象拉下来,但在我的实际系统中,这是一个宽表,我想避免将所有数据拉到线上并将其放入内存的开销

3 个答案:

答案 0 :(得分:5)

如果您只需要RolesId中的User,则可以执行此查询:

 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}

正如您所看到的,您所查找的查询是相同的。

答案 1 :(得分:1)

更新

您可以尝试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();

答案 2 :(得分:0)

关系应该已经存在:通常,如果你将多对多关系定义为两种方式的集合,EF将为你生成连接表,这意味着你必须聪明地制作你的LINQ查询就你可以看到的表而言(有时可能有点棘手)。 (我从你的评论中看出“EF似乎没有为你提供联接表”,确实如此。)

所以,根据你给出的例子,它将是这样的:

context.Users.Where(u => u.Id == id).Single().Roles.Select(r => r.Id);

但需要注意的是,如果找不到User Id==id或者找不到多个Id,则会抛出此内容(因此{{1}}不是密钥)。但是,这通常就是您想要的查找方式。