【问题标题】:Concatenate columns from joined table with LINQ使用 LINQ 连接联接表中的列
【发布时间】:2014-02-11 09:53:27
【问题描述】:

我有 3 个 EF 实体:AppealAppealPersonPerson

AppealPerson 实体由 AppealPerson 实体连接(多对多关系)。 我想选择具有串联人员全名的申诉。

+----------+----------+--------------------------------------------------+
| AppealId | Appeal.* | Person.Surname + Person.Name + Person.MiddleName |
+----------+----------+--------------------------------------------------+
| 1        | ..info.. | Aaa Aaa Aaa, Bbb Bbb Bbb, Ccc Ccc Ccc            |
+----------+----------+--------------------------------------------------+
| 2        | ..info.. | Aaa Aaa Aaa, Bbb Bbb Bbb                         |
+----------+----------+--------------------------------------------------+

现在我正在使用这个查询:

context.Appeals
.Select(a => new
{
  Appeal = a,
  Persons = a.AppealPersons
    .Select(ap => ap.Person)
    .Select(p => new { p.Surname, p.Name, p.MiddleName })
    .ToList()
})
.AsEnumerable()
.Select(a => new
{
  Id = a.Appeal.Id,
  Persons = a.Persons.Select(p => string.Format("{0} {1} {2}", p.Surname, p.Name, p.MiddleName).Trim()),
})
.ToList<object>();

这个查询很慢。在 30 秒内生成约 500 行的列表。 请帮助优化查询。

【问题讨论】:

  • 你检查过 sql - profiler 吗?它是生成一个 sql 查询还是为每个上诉做一个查询?

标签: c# sql-server linq entity-framework


【解决方案1】:

尝试使用以下连接:

from a in context.Appeals
join ap in context.AppealPerson
on a.Id equals ap.AppealId
join p in context.Person
on p.Id equals ap.PersonId
...

【讨论】:

  • 连接肯定会更慢?
  • 以及如何连接全名?
  • @James 不一定,他的 LINQ 查询可能会生成多个 SQL 查询,这就是为什么我建议尝试一下。
  • @PiONeeR 我仍然会打电话给.AsEnumerable() 来带来结果,并像你一样用string.Format 执行它。我的目标是基本 SQL 查询。
【解决方案2】:

查看您的关系,我认为您可以使用GroupBy 子句来做到这一点。鉴于格式化必须发生在客户端,如果你有一个函数来包装它,或者更好的是,覆盖 ToString 上的 Person

public partial class Person
{
    ...
    public string override ToString()
    {
        return String.Format("{0} {1} {2}", Surname, Name, MiddleName).Trim();
    }
}
...
context.AppealPersons
    .GroupBy(ap => ap.Appeal.Id, ap => ap,
        (key, g) => new { 
            AppealId = key, 
            Appeal = g.FirstOrDefault().Appeal, 
            Persons = String.Join(",", g.Select(x => x.Person).AsEnumerable()
                .Select(p => p.ToString()))
        })
    .ToList();

【讨论】:

  • 感谢您的回答。我有一个问题:如果上诉没有任何人,这会出现在查询结果中吗?
  • Persons 在这种情况下应该返回一个空字符串,你仍然应该得到Appeal 信息,因为你是按Appeal.Id 分组的,人实际上只是你附加到的额外元数据结果。
  • 你应该知道,如果appeal没有任何人,那么这个Appeal.Id就没有AppealPerson。我也想在没有人的情况下显示上诉。
  • @PiONeeR 如果是这种情况,那么您将得不到任何结果。我们在这里直接查询AppealPerson 表,所以它只会给我们返回存在的记录...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-25
  • 2015-12-07
  • 1970-01-01
  • 1970-01-01
  • 2021-03-26
  • 2015-03-31
  • 1970-01-01
相关资源
最近更新 更多