如何使用 linq to EF 填充我的 class 对象?

How to populate my class object with linq to EF?

我的class,

  public class User
    {
        public string Username
        {
            get;
            set;
        }
        public string Password
        {
            get;
            set;
        }
        public string [] Roles
        {
            get;
            set;
        }
    }

我的查询是,

var innerJoinQuery =
                            (from u
                            in db.Users
                            join ur in db.UserRoles
                                on u.UserID equals ur.UserID
                            join r in db.Roles on ur.RoleID equals r.RoleID
                            select new {
                                Username=u.Username,
                                Password=u.Password,
                                RoleName = r.RoleName 
                            }).ToList();

它在上面的查询中得到的数据就像,

username   password  RoleName
john        123       user
john        123       admin
john        123       super user
David       12345     super user
petter      123456    user

我想使用 Linq 在我的用户class 对象中获取此数据,

应该是,

username   password  RoleName
john        123       { "user", "admin", "super user" }
David       12345     { "super user" }
petter      123456    { "user"}

我已经尝试了很多来自网络的例子,但我没有得到答案。

希望得到您的解决方案。

您正在寻找 GroupBy 方法。不确定你的 ORM 是否支持它,但你总是可以在查询 db:

后分组
var innerJoinQuery =  (....)
    .ToList()
    .GroupBy(u => u.Username)
    .Select(g => new User
    {
      Username=g.Key,
      Password=g.Select(i => i.Password).First(),// can be moved to grouping clause
      Roles = g.Select(i => i.RoleName).ToArray() 
    })      
    .ToList();

要尝试在对数据库的查询中执行分组,您可以查看 this 问题。

您可以尝试使用以下子查询 select 所有角色名称:

var innerJoinQuery = (
    from u in db.Users
    select new User
    {
        Username = u.Username,
        Password = u.Password,
        Roles = (from ur in db.UserRoles
                 join r in db.Roles on ur.RoleID equals r.RoleID
                 where ur.UserID == u.UserID
                 select r.RoleName).ToArray()
    }
).ToList();

或者,您可以使用 group...by...into:

var innerJoinQuery = (
    from u in db.Users
    join ur in db.UserRoles on u.UserID equals ur.UserID 
    join r in db.Roles on ur.RoleID equals r.RoleID
    group r by u into g
    select new User
    {
        Username = g.Key.Username,
        Password = g.Key.Password,
        Roles = g.Select(c => c.RoleName).ToArray()
    }
).ToList();

假设您的 ORM 支持此功能,它 可能 生成比聚合键更好的查询,然后从聚合组中子selecting。

如果 ORM 无法翻译 ToArray/ToList(Linq-To-SQL 不能),您可以

  1. User.Roles 的类型从 string[] 改为 IEnumerable<string>,然后删除上面的 ToArray 调用,或者
  2. select 转换为匿名类型 首先 ,具体化查询 (ToList),然后将结果重新投影到您的 User输入

#2 如下所示:

var innerJoinQuery = (
    from u in db.Users
    select new
    {
        u.Username,
        u.Password,
        Roles = (from ur in db.UserRoles
                 join r in db.Roles on ur.RoleID equals r.RoleID
                 where ur.UserID == u.UserID
                 select r.RoleName)
    }
).ToList();

var users = innerJoinQuery.Select(c => new User { 
     UserName = c.UserName, 
     Password = c.Password,
     Roles = c.Roles.ToArray() 
}); 

或使用 group...by 变体:

var innerJoinQuery= (
    from u in db.Users
    join ur in db.UserRoles on u.UserID equals ur.UserID 
    join r in db.Roles on ur.RoleID equals r.RoleID
    group r by u into g
    select new
    {
        g.Key.Username,
        g.Key.Password,
        Roles = g.Select(c => c.RoleName)
    }
).ToList();

var users = innerJoinQuery.Select(c => new User { 
     UserName = c.UserName, 
     Password = c.Password,
     Roles = c.Roles.ToArray() 
}); 

请注意,所有这些解决方案都有一个优点,即它们执行分组 and/or 子查询 在数据库 ,而另一个答案是 内存中