Способ сделать "соединение" при использовании LINQ в db4o? - PullRequest
1 голос
/ 23 февраля 2011

Какой правильный LINQ для перехода к конечному конечному узлу следующей структуры данных?

Root ----Symbol (APPLE)                
   |          |------Day 1: Date: 2010-10-18, string "Apples on Thursday"
   |          |------Day 2: Date: 2010-10-19, string "Apples on Friday"
   |
   |
   |-----Symbol (PEAR)               
              |------Day 1: Date: 2010-10-18, string "Pears on Thursday"
              |------Day 2: Date: 2010-10-19, string "Pears on Friday"

Другими словами, если я выберу «ЯБЛОКО», то «2010-10-19», он должен вернуть «Яблоки в пятницу».

Следующее не работает (оно выбирает из декартово произведение , которое представляет собой каждую отдельную комбинацию) символа и даты):

var daysForSymbolS1 = from Symbol s in db4o.db
                      from Date t in db4o.db
                          where (s.SymbolGlobal == "APPLE" 
                            && t.Date == new DateTime(2010, 10, 18))
                          select new
                          {
                            s.SymbolGlobal,
                            t.Date,
                            t.Meta
                          };

foreach (var d in daysForSymbolS1)
{
  Console.WriteLine("{0} - {1} - {2}", d.SymbolGlobal, d.Date.Date, d.Meta);
} 

Я бы хотел использовать соединение - но db4o - это объектная база данных, и она не позволяет вам ссылаться на ID для каждого объекта.

Обновление:

@ Гамлор дал блестящий ответ, он работает как шарм.

Следует также отметить, что текущая версия db4o не поддерживает индексацию коллекций. Поскольку любая форма иерархии 1-ко-многим построена с использованием чего-то вроде коллекции IList, которая содержит некоторые подклассы, вполне вероятно, что разбиение базы данных на иерархию приведет к замедлению работы как в плане скорости, так и в плане обслуживания.

Ответы [ 2 ]

2 голосов
/ 23 февраля 2011

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

var mySym = from Symbol s in db4o.db
            where (s.SymbolGlobal == "APPLE")

var mySomething = from xxx x in mySym.x
                  where (x.Date == new DateTime(2010, 10, 18)
                  select new
                  {
                    mySym.SymbolGlobal,
                    x.Date,
                    x.Meta
                  };

foreach (var d in mySomething)
{
  Console.WriteLine("{0} - {1} - {2}", d.SymbolGlobal, d.Date.Date, d.Meta);
} 
1 голос
/ 23 февраля 2011

Хоган уже ответил, что вам нужно использовать join: Например, вот так:

       var daysForSymbolS1 = from s in database.Cast<Symbol>()
                                  join t in database.Cast<TradingDay>() on s equals t.SymbolGlobal 
                                  where (s.SymbolGlobal == "IBM" && t.Date == new DateTime(2010, 10, 20))
                                  select new
                                  {
                                      s.SymbolGlobal,
                                      t.Date,
                                      t.Meta
                                  };

Теперь перейдем к db4o-parts.Вы можете просто использовать саму ссылку для объединения.Вам не нужно никакого удостоверения личности (как показано выше)

Однако здесь нет большой проблемы.В настоящее время реализация LINQ to db4o вообще не поддерживает LINQ-оператор (вы можете убедиться в этом, воспользовавшись декларацией перехода к соединению).Это означает, что он возвращается к LINQ to Objects.Это означает, что все объекты загружаются в память, а затем выполняется LINQ to Object для этих объектов.Это очень медленно.

В настоящее время запрос не может быть эффективно выполнен на db4o.То, как вы обычно делаете такие вещи с помощью db4o, - это создание Day-collection для Symbol.Эта коллекция всегда содержит все дни этого символа.Затем вы можете запросить символ и затем получить данные.

Другим методом будет разделение запроса:

    var ibmSymbols = from Symbol s in database
                     where s.SymbolGlobal == "IBM"
                     select s;

    // run the TradingDay selection with the optimized LINQ to db4o implementation
    // do the rest with LINQ to objects
    var allSymbols = ibmSymbols.SelectMany(s => from TradingDay t in database
                               where t.SymbolGlobal==s && t.Date == new DateTime(2010, 10, 20)
                               select t);

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

            var ibmSymbols = from Symbol s in database
                             where s.SymbolGlobal == "IBM"
                             select s;

            var tradingDays = from symbol in ibmSymbols
                              from day in symbol.TradingDays
                              where day.Date == new DateTime(2010, 10, 20)
                              select day;
...