如何将这个foreach循环转换为Linq代码?

时间:2010-04-29 11:21:52

标签: c# linq

我是Linq的新手,我想修改旧的c#代码以使用Linq。 这段代码的想法是选择所有未设置的表和引用的字段PrimaryTable等于“myTable”


foreach (Table table in dbServer.Tables)
            {
                if (!table.IsSet)
                {
                    foreach (Reference refer in table.References)
                    {
                        if (refer.PrimaryTable == "myTable")
                        {
                            tables.Add(table);
                        }
                    }
                }
            }

在网上挖掘后我得到了这段代码


var q = from table in dbServer.Tables
                    let refers = from refer in table.References
                                 where refer.PrimaryTable == "myTable"
                                 select refer.ForeignTable
                    where refers.Contains(table.Name)
                    select table;

但它根本不起作用,我需要你的帮助才能使它有效。

提前致谢。

4 个答案:

答案 0 :(得分:18)

var tables = dbServer.Tables
    .Where(t => !t.IsSet)
    .SelectMany(t => t.References)
    .Where(r => r.PrimaryTable == "myTable")
    .ToList();

假设表格为List<T>

编辑:正如评论指出的那样,这与原作不一样 - 看起来你真正想要的是:

var tables = dbServer.Tables
    .Where(t => !t.IsSet && t.References.Any(r => r.PrimaryTable == "myTable"))
    .ToList();

这将为您提供所有具有PrimaryTable为“myTable”的引用的表,该表假定只有一个匹配的引用表。否则,您可以多次添加相同的表格。

答案 1 :(得分:5)

只需要使用两个来自

        var q = from table in dbServer.Tables
                where !table.IsSet
                from refer in table.References
                where refer.PrimaryTable == "myTable"
                select table;

答案 2 :(得分:4)

修改

实际上,我对此代码感到有点困惑。你确定它正在做它的意图吗?特别是,让我失望的是你在table.References上进行枚举的事实,但是当特定条件适用于Reference时(即refer.PrimaryTable == "myTable"),您正在添加Tabletable)而不是Referencerefer

这意味着,如果Table包含多个ReferencePrimaryTable == "myTable"个对象,则您的tables集合可能包含此Table的多个副本。这是对的吗?

我打算走出困境猜测你想要检查的只是Table在其References集合中所拥有的< em>任何带有ReferencePrimaryTable == "myTable"对象。如果是这种情况,请在tables.Add(table)之后的原始代码中添加break以避免重复。 (可能每个集合中只有一个Reference具有相同的PrimaryTable,在这种情况下你会没事;但是你仍然可以在这一点上停止枚举。除非你当然想要重复项。)

在任何情况下,Lee的代码(以及我在下面提到的内容)都没有重复此行为。相反,它将Reference个对象添加到列表中(因为最终的ToList调用位于IEnumerable<Reference>)。

似乎,如果我上面描述的是你所追求的行为,你可能想要这样做:

var tables = dbServer.Tables
    .Where(table => !table.IsSet)
    .Where(
        table => table.References.Any(refer => refer.PrimaryTable == "myTable")
    ).ToList();

原始答案

我将扩展Lee的答案。让我们逐行分析。

// 1. enumerating over a collection
foreach (Table table in dbServer.Tables)
{
    // 2. checking a condition
    if (!table.IsSet)
    {
        // 3. enumerating over another collection
        foreach (Reference refer in table.References)
        {
            // 4. checking a condition
            if (refer.PrimaryTable == "myTable")
            {
                // 5. adding to a collection
                tables.Add(table);
            }
        }
    }
}

行。所以我们得到了:

  1. 枚举 - 简单 - 这就是我们开始的地方
  2. 条件检查 - 我们需要Where
  3. 枚举另一个集合 - SelectMany
  4. 条件检查 - 再次Where
  5. 添加 - 最有可能ToList(取决于您想要的收集类型)
  6. 以下是它的内容:

    var tables = dbServer.Tables                         // step 1
        .Where(table => !table.IsSet)                    // step 2
        .SelectMany(table => table.References)           // step 3
        .Where(refer => refer.PrimaryTable == "myTable") // step 4
        .ToList();                                       // step 5
    

    有意义吗?

答案 3 :(得分:3)

tables.AddRange(dbServer.Tables
    .Where(t => !t.IsSet)
    .SelectMany(t => table.References)
        .Where(r => r.PrimaryTable == "myTable"));