【问题标题】:Grouping in Linq queries with multiple tables在具有多个表的 Linq 查询中进行分组
【发布时间】:2016-11-03 13:56:51
【问题描述】:

我有两张桌子

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 'ObjectContent1' type failed to serialize response body for content type 'text/html;`

附: NoteGrp 是我创建的一个类,它只包含 2 个成员:作为 int 的 PersonID 和作为字符串的 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();

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

【问题讨论】:

  • 请显示NoteGrp的定义
  • 添加了 NoteGrp
  • 人物和笔记是否通过主键和外键关系相关?如果是这样,它非常简单: db.Persons.Include(p => p.Notes).Select(p => new NoteGrp{ });我没有检查语法。但这应该会给你一些想法。
  • 你为什么不在 Person 类上放一组 Notes 让 EF 为你填充呢?

标签: c# entity-framework linq


【解决方案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; }
}

【讨论】:

  • NoteGrp 类没有映射,只是我创建的一个类
  • 我试过了,得到了同样的旧The entity or complex type 'NoteGrp' cannot be constructed in a LINQ to Entities query.
  • @ElenaDBA - 那么[Key] 属性的用途是什么?删除它并尝试
  • 如果我删除 Key 属性,它会显示:EntityType 'NoteGrpl' has no key defined. Define the key for this EntityType
  • @ElenaDBA 如果这个类没有被映射,那么为什么它需要[Key]?它在哪里给你key not specified的错误?
【解决方案2】:

您可以在投影 (Select) 之前使用 AsEnumerable 更改为 Linq to Objects 以避免 Linq to Entities 限制,例如 String.Join: p>

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,并在另一个属性中加入它们:

var result = db.Notes.GroupBy(n => n.PersonId)
                     .Select(g => new NoteGrp
                      {
                          PersonID = g.Key,
                          Notes = g.Select(x => x.NoteText)
                      });

public class NoteGrp
{
    public int PersonID { get; set; }
    public IEnumerable<string> Notes { get; set; }
    ...

    public string Note
    { get { return string.Join(", ", Notes); } }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多