Избавление от вложенных циклов foreach при использовании linq - PullRequest
3 голосов
/ 31 августа 2010

Я всегда нахожу себя создающим выражения linq, которые все еще интенсивно используют вложенные циклы foreach.Ниже приведен простой пример того, о чем я говорю, и я был бы очень признателен, если бы кто-нибудь здесь показал мне, как сжать этот малоэффективный код в одно выражение linq?

Контекст базы данных(БД) имеет три таблицы: блог, тег, 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 ]

4 голосов
/ 31 августа 2010

Вы можете создать запрос, который позволит базе данных найти совпадения для вас.

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 голос
/ 31 августа 2010
var blogsWithGivenTag =
    from blog in db.BlogPosts
    where blog.BlogTags.Any(bt => bt.Tag.Name == tagName)
    select blog;
0 голосов
/ 31 августа 2010

Вы можете поместить блоги в словарь, сгруппировать соединения по идентификатору блога и выполнить цикл по группам:

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

Это также вложенные циклы, но для каждого блога вы только циклически просматриваетесоединения, которые на самом деле принадлежат этому блогу, а не все соединения.

0 голосов
/ 31 августа 2010
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...