如何编写LINQ查询,选择一个属性,该属性是一个嵌套实体属性集合的字符串连接

本文关键字:属性 一个 集合 实体 字符串 连接 嵌套 查询 LINQ 何编写 选择 | 更新日期: 2023-09-27 18:11:41

试图提高我的查询效率,但不确定如何将这一切写为一个查询。我有一个域模型:

public class UserReport : Entity
{
    public string Name { get; set; }
    public List<string> Statuses { get; set; }
    public List<GroupModel> Groups { get; set; }
    public string Email { get; set; }
    public string OfficeStates {get; set;} //Comma delimited list
}
public class GroupModel : Entity
{
    public string Name {get; set;}
    public string Type {get; set;
}

这是一个"复合实体",如果你愿意。表示这些集合的标准实体是具有User对象的M2M关系实体:

public class User : Entity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<Status> Statuses { get; set; }
    public ICollection<Group> Groups { get; set; }
    public ICollection<Office> Offices { get; set; }
}
public class Office : Entity
{
    //other properties
    public State State { get; set; }
}
public class State : Entity
{
    public string Name { get; set; }
    public string Abbreviation { get; set; }
}

到目前为止,我得到了:

Context.DbSet<User>.Select(user => new UserReport()
    {
       Name = user.FirstName + ", " + user.LastName,
       Email = user.Email,
       Statuses = user.Statuses.Select(status => status.Name).ToList(),
       Groups = user.Groups.Select(group => new GroupModel(){ Name = group.Name, Type = group.Type.Name}).ToList(),
       OfficeStates = string.Join(",", user.Offices.Select(office => office.State.Abbreviation).ToList())
    }).ToList();

抛出错误:

LINQ to Entities不能识别方法System。字符串连接(系统。字符串,System.Collections.Generic.IEnumerable ' 1[System.String])'方法,此方法不能转换为存储表达式。

我完全明白这是说什么,我知道如果我调用。tolist()之前我的选择它会起作用,但我需要有这是一个查询,所以我仍然可以有一个IQueryable应用过滤以后。当然,LINQ中一定有一些方法可以做到这一点。它可以在SQL中完成:将许多行连接到单个文本字符串中?如何通过LINQ实现?

如何编写LINQ查询,选择一个属性,该属性是一个嵌套实体属性集合的字符串连接

您可以看到,即使在纯SQL中,这也不是微不足道的(for xml,声明变量等)。据我所知,没有办法用纯LINQ做你想做的事情。但是,至少在某些情况下,您可以使用一个查询来完成此操作,尽管此查询与您在纯SQL中执行此操作的方式不同。在你的例子中,应该是这样的:

Context.DbSet<User>.Select(user => new // note, anonymous type here
{
   Name = user.FirstName + ", " + user.LastName,
   Email = user.Email,
   Statuses = user.Statuses.Select(status => status.Name), // no ToList - this won't work
   Groups = user.Groups.Select(group => new GroupModel(){ Name = group.Name, Type = group.Type.Name}), // no ToList()
   OfficeStates = user.Offices.Select(office => office.State.Abbreviation) // no ToList(), no String.Join()
}).ToList() // here we materizized, and now we can concatenate strings by hand
.Select(c => new UserReport {
     Name = c.Name,
     Email = c.Email,
     Statuses = c.Statuses.ToList(),
     Groups = c.Groups.ToList(),
     OfficeStates = String.Join(",", c.Offices)
});

在我测试的简单的情况下,这会生成一个数据库查询,并且该查询只接收您需要的列(尽管正如我所说,生成的查询在概念上与您在SQL中使用的查询不同)。因此,我建议尝试这种方法,看看会生成什么查询(请注意我在上面代码中的注释)。