使用linq时摆脱嵌套的foreach循环

时间:2010-08-31 10:29:30

标签: c# linq linq-to-sql optimization foreach

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

数据库上下文(db)有三个表:Blog,Tag,Junc_Tag_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 个答案:

答案 0 :(得分:4)

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

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();

答案 1 :(得分:1)

var blogsWithGivenTag =
    from blog in db.BlogPosts
    where blog.BlogTags.Any(bt => bt.Tag.Name == tagName)
    select blog;

答案 2 :(得分:0)

答案 3 :(得分:0)

您可以将博客放入字典中,将博客ID上的联结分组,然后遍历这些组:

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
    }
  }
}

这也是嵌套循环,但对于每个博客,您只能遍历实际属于该博客的联结,而不是所有联结。