LINQ: идентификаторы цепочек от одного ряда к другому - PullRequest
1 голос
/ 03 сентября 2011

У меня есть таблица, в которой есть своего рода child-> child-> parent. (Это исправление, которое я использую в существующей старой базе данных, поэтому оно немного хитро).

Класс для таблицы:

public class Foo
{
    int ID {get;set;}
    int ParentID  {get;set;}
    int BaseParentID {get;set;}
}

Допустим, у меня там есть несколько записей

ID: 10, ParentID: 5, BaseParentID: 5
ID: 05, ParentID: 1, BaseParentID: 5
ID: 01, ParentID: 1, BaseParentID: 0

Что я хочу сделать, так это получить каждый из ParentID до тех пор, пока baseparentid не станет равным 0. Так что, в некотором смысле, он перебирает таблицу из одной записи в другую и извлекает ее в список идентификаторов.

Конечным результатом должен быть список: { 10, 5, 1 }

Это то, что я делаю сейчас (на данный момент есть ограничение в 4, но я бы предпочел, чтобы не было предела):

var list = new List<int?>();
var id = 10; // The first ID is given when this method is started.
list.Add(id);
int? pid = db.Foo.Where(w => w.ID == id).Single().BaseParentID; // i have this as a compiled query function
if (pid != 0) {
    list.Add(pid);
    pid = db.Foo.Where(w => w.ID == pid).Single().BaseParentID; //  for the sake of this example i'm just using the query here
    if (pid != null) {
         list.Add(pid);
         // And so on
    }
}

Как видите, это немного дурацкий способ сделать это. Но я не уверен, есть ли способ сделать это в необычном запросе linq.

пс. Дело в том, что это своего рода структура псевдопапок.

Ответы [ 2 ]

3 голосов
/ 03 сентября 2011

Это хороший пример того, как вы бы написали отдельную функцию итератора :

 IEnumerable<Foo> TraverseParents(Foo foo, IEnumerable<Foo> all)
 {
      while(foo != null) 
      {
          yield return foo;
          foo = (foo.pid == 0) ? null : all.FirstOrDefault(f => f.ID == foo.pid);
      }
 }

 // In the calling code
 var id = 10;
 Foo root = db.Foo.FirstOrDefault(f => f.ID == id);
 List<int> list = TraverseParents(root, db.Foo)
                   .Select(f => f.ID)
                   .ToList();
1 голос
/ 03 сентября 2011

Вы можете использовать следующий метод:

List<int> GetParentHierarchy(int startingId)
{
  List<int> hierarchy = new List<int> { startingId };
  using(Connection db = new Connection()) //change to your context
  {      
      int parentId = startingId;
      while(true)
      {
         var foo = db.Foo(x => x.Id == parentId).SingleOrDefault(); 
         if(foo == null)
           break;
         parentId = foo.ParentId;
         hierarchy.Add(foo.Id);
         if(foo.BaseParentID == 0)
           break;
      }
  }

  return hierarchy;

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