使用多个表对Linq查询进行分组

时间:2016-11-03 13:56:52

标签: c# entity-framework linq

我有两张桌子

Person
__________
PersonID
PersonName
DOB
Status


Notes
__________
NoteID
PersonID
NoteText
Comments
LineNo

这是一些示例内容

 PersonID   PersonName    DOB          Status
   1        Mark Jacobs   07/07/1961    Active

NoteID  PersonID    NoteText    LineNo
 123       1        Line 1      1
 234       1        Line 2      2
 236       1        Line 3      3

因此,作为最终结果,我希望Linq查询显示类似

的内容
PersonID    PersonName    DOB           Note
   1        Mark Jacobs   07/07/1961    Line 1
                                        Line 2
                                        Line 3

到目前为止我找到的所有示例只有一个表,所以我尝试着将Notes表分组如下:

var result = (from n in db.Notes
              group n.NoteText by n.PersonID into g
              select new NoteGrp { 
                  PersonID = g.Key, 
                  Notes = g.ToList().ToString() 
              }).AsEnumerable();

在函数中它是这样的:

public IEnumerable<NoteGrp> GetNotes()
{
    using (MyContext db = new MyContext())
    {               
        var result = (from n in db.Notes
                      group n.NoteText by n.PersonID into g
                     select new NoteGrp { PersonID = g.Key, Note = g.ToList().ToString() }).AsEnumerable();
        return result;
    }
}

它编译好并且在返回结果之前会出错。如果我在监视窗口中查看结果对象并将其展开以显示结果,我会看到The entity or complex type 'NoteGrp' cannot be constructed in a LINQ to Entities query内部异常。 但是如果我让它在浏览器中运行,我得到以下内容:The 'ObjectContent 1'类型无法序列化内容类型'text / html;`

的响应正文

P.S。 NoteGrp是我创建的一个只包含2个成员的类:PersonID为int,Notes为字符串

public class NoteGrp
    {
        [Key]
        public int PersonID { get; set; }
        public string Notes { get; set; }

    }

我也尝试过使用

 var result = db.Notes.GroupBy(n => new { n.PersonID }).Select(g => new NoteGrp{PersonID= g.Key.personID, Notes = string.Join(",", g.Select(x => x.NoteText)) }).ToList();

并得到了同样的错误,即无法构造复杂类型的实体。我可以使用匿名类型:

var result = db.Notes.GroupBy(n => new { n.PersonID }).Select(g => new {PersonID= g.Key.personID, Notes = string.Join(",", g.Select(x => x.NoteText)) }).ToList();

但是我不确定我的函数应该返回什么类型...

2 个答案:

答案 0 :(得分:1)

从我的假设(通过它失败但出现此错误但使用匿名类型)映射NoteGrp类,您无法在查询中实例化EF映射对象。创建一个DTO类(或匿名类型)。

使用.ToList().ToString()可能不是你想要的,但你想要的是string.Join

public IEnumerable<NoteGrp> GetNotes()
{
    using (MyContext db = new MyContext())
    {
        var result = (from n in db.Notes
                      group n.NoteText by n.PersonID into g
                      select new { //Creating anonymous object with only the needed information
                          PersonID = g.Key, 
                          Notes = g.ToList()
                      }).AsEnumerable() //Bringing items to memory so can use string.Join
                     .Select(item => new NoteGroupDTO { //Instantiating new DTO object
                         PersonID = item.PersonID,
                         Notes = string.Join(", ", item.Notes)
                     }).ToList();
        return result;
    }
}

类:

public class NoteGroupDTO
{
    public int PersonId { get; set; }
    public string Notes { get; set; }
}

答案 1 :(得分:1)

您可以在投影(AsEnumerable)之前使用Select更改为 Linq to Objects ,以避免 Linq to Entities 限制,例如{{ 1}}:

String.Join

如果您可以更改var result = db.Notes.GroupBy(n => n.PersonId) .AsEnumerable() .Select(g => new NoteGrp { PersonID = g.Key, Notes = string.Join(", ", g.Select(x => x.NoteText)) }); ,则可以添加其他属性以保留所有NoteGrp并将其加入其他属性:

NoteText