代码之家  ›  专栏  ›  技术社区  ›  Greg

使用linq时去掉嵌套的foreach循环

  •  3
  • Greg  · 技术社区  · 14 年前

    我总是发现自己创建的linq表达式仍然大量使用嵌套的foreach循环。下面是一个简单的例子,我正在谈论什么,我真的很感激,如果有人在这里可以告诉我如何压缩到一个单一的linq表达式这个低效率的代码?

    数据库上下文(db)有三个表:Blog、Tag、Junc\u Tag\u Blog。连接表只存储博客及其标记的记录。

    public static Collection<Blog> GetByTag(string tagName)
    {
        // Get the tag record.
        var tag = (from t in db.Tags
                  where t.Name == tagName
                  select t).Single();
    
        // Get the list of all junction table records.
        var tagJunc = from tj in db.Junc_Tag_Blogs
                      where tj.Fk_Tag_Id == tag.Id
                      select tj;
    
        // Get a list of all blogs.
        var blogs = from b in db.BlogPosts
                    select b;
    
        // Work out if each blog is associated with given tag.
        foreach(var blog in blogs)
        {
            foreach(var junc in tagJunc)
            {
                if(blog.Id == junc.Fk_Blog_Id)
                {
                    // We have a match! - do something with this result.
                }
            }
        }
    }
    

    提前感谢能帮我清理代码的人!

    4 回复  |  直到 14 年前
        1
  •  4
  •   Amy B    14 年前

    您可以构造一个查询,让数据库为您查找匹配项。

    List<Blog> blogs = 
    (
      from t in tag
      where t.Name == tagName
      from tj in t.Junc_Tag_Blogs
      let b = tj.Blog
      select b
    ).ToList();
    
        2
  •  1
  •   Steven    14 年前
    var blogsWithGivenTag =
        from blog in db.BlogPosts
        where blog.BlogTags.Any(bt => bt.Tag.Name == tagName)
        select blog;
    
        3
  •  0
  •   Dmitry Ornatsky    14 年前
        4
  •  0
  •   Guffa    14 年前

    var blogDict = blogs.ToDictionary(b => b.Id);
    
    foreach(var group in tagJunk.GroupBy(j => j.Fk_Blog_Id)) {
      if (blogDict.ContainsKey(group.Key)) {
        var blog = blogDict[group.Key];
        foreach (var junction in group) {
          // here you have the blog and the junction
        }
      }
    }
    

    这也是嵌套循环,但是对于每个blog,只循环实际属于该blog的连接,而不是所有连接。