【问题标题】:Concat or Join list of "names" in Linq连接或加入 Linq 中的“名称”列表
【发布时间】:2013-12-04 14:52:55
【问题描述】:

使用 WCF RIA 我有一个返回名称查询的查询

public class WitnessInfo
{
    [Key]
    public Guid WCFId { get; set; }
    public string witnessName { get; set; }
    public string AllNames {get; set;}

}

这是我的 Linq 查询

[Query]
    public IQueryable<WitnessInfo> getWitnessInfo(int? id)
    {
        IQueryable<WitnessInfo> witnessQuery = from witness in this.Context.witness
                                               where witness.DAFile.Id == id
                                               select new WitnessInfo
                                               {
                                                   WCFId = Guid.NewGuid(),
                                                   witnessName = witness.Person.FirstName,

                                               };
        return witnessQuery;

    }

我想获取所有名称并将它们返回到一个字符串中,即“John,James,Tim,Jones”。尝试使用 AllNames 并循环,但这没有用。有什么建议吗?

【问题讨论】:

  • 在哪里所有这些名字都在哪里?在AllNames?
  • 可以使用AggregateLINQ方法,也可以使用string.Join(", ", yourQuery.Select(i =&gt; i.WitnessName).ToArray())
  • @JeroenVannevel 是的,我想在 AllNames 中添加所有名称
  • @Luaan 从 .NET 4.0 开始,情况并非如此。 Join 接受 IEnumerable&lt;string&gt;
  • @Servy:哦,酷,我不知道。我仍然需要在 ASP.NET 2.0 堆栈上工作,所以我坚持使用 .NET 3.5。在这种情况下,在 4.0+ 上,您的观点是完全有效的,并且您的方法更好。此外,我们似乎都忽略了这一点——这两种方法都不能在数据库服务器上的 IQueryable 中使用——它们需要你首先获取所有数据,这可能不是 OP 想要的。

标签: c# mysql sql linq wcf


【解决方案1】:

首先在单个查询中获取您需要的所有信息,然后使用String.Join 将名称集合映射到单个字符串:

var firstQuery = from witness in Context.witness
    where witness.DAFile.Id == id
    select new
    {
        WCFId = Guid.NewGuid(),
        witnessName = witness.Person.FirstName,
        Names = Context.witness.Select(w => w.FirstName),
    })
    .AsEnumerable(); //do the rest in linq to objects

var finalQuery = from witness in firstQuery
    //do the string manipulation just once
    let allNames = string.Join(", ", witness.Names)
    select new WitnessInfo
    {
        WCFId = witness.WCFId,
        witnessName = witness.witnessName,
        AllNames = allNames,
    });

【讨论】:

  • Names = Context.witness.Select(w =&gt; w.FirstName) 不是内重查询吗?
  • @YairNevet 如果它是对象的 linq,是的,这会很糟糕,但事实并非如此,整个事情只是被编译成一个表达式,它作为 SQL 发送到数据库,然后SQL 中的内部查询,当它不依赖于从外部查询中捕获的标识符时,不会为每个项目执行。它将被执行一次,并且它的结果被重新用于查询中的每个项目。
【解决方案2】:

通过在WitnessInfo 类中使用AllNames 属性,您似乎希望每个WitnessInfo 对象一次又一次地包含所有序列名称,如果这是你的情况,然后这样做:

var names = (from witness in this.Context.witness
                select witness.Person.FirstName).ToArray();

var allNames = string.Join(", ", names);

IQueryable<WitnessInfo> witnessQuery = from witness in this.Context.witness
                                       where witness.DAFile.Id == id
                                       select new WitnessInfo
                                       {
                                           WCFId = Guid.NewGuid(),
                                           witnessName = witness.Person.FirstName,
                                           AllNames = allNames
                                       };

【讨论】:

  • 请注意,这是对数据库执行两次往返。
  • @Servy 不用了,我用ToArray()
  • @YairNevet 你肯定正在进行两次往返。你正在做两个查询;第一个查询,名称,第二个查询,witnessQuery
  • @Servy 好的,还有其他选择吗?
  • @YairNevet 当然;如我的回答所示,在一个查询中获取所有信息。
【解决方案3】:

你可以这样连接:

string.Join(", ", getWithnessInfo(666).Select(wq => wq.witnessName))

【讨论】:

    【解决方案4】:
    this.Context.witness.Select(a => a.Person.Firstname).Aggregate((a, b) => a + ", " + b);
    

    【讨论】:

    • 像这样执行未知数量的字符串连接是非常低效的,并且会浪费大量精力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多