Использование LINQ для запроса вложенных классов в db4o?

Столкнулись со сложной проблемой с db4o и простыми вложенными структурами.

Проблема: когда я использую LINQ для извлечения данных из db4o, он извлекает слишком много данных (т. е. кажется, что предложение «где» не работает).

У меня есть несколько вложенных объектов:

Root ----Symbol (SPX)                
   |          |------Day 1: Date: 2010-10-18, string "SPX meta"
   |          |------Day 2: Date: 2010-10-19, string "SPX meta"
   |
   |
   |-----Symbol (IBM)               
              |------Day 1: Date: 2010-10-18, string "IBM meta"
              |------Day 2: Date: 2010-10-19, string "IBM meta"

Я создаю два символа:

  Symbol sym1 = new Symbol("SPX");
  Symbol sym2 = new Symbol("IBM");

Затем я создаю несколько торговых дней:

  // SPX
  TradingDay day1 = new TradingDay(new DateTime(2010, 10, 18), "SPX meta");
  TradingDay day2 = new TradingDay(new DateTime(2010, 10, 19), "SPX meta");

  // IBM
  TradingDay day3 = new TradingDay(new DateTime(2010, 10, 18), "IBM meta");
  TradingDay day4 = new TradingDay(new DateTime(2010, 10, 19), "IBM meta");

Затем я назначаю пару дней каждому символу:

  sym1.AssignTradingDay(day1);
  sym1.AssignTradingDay(day2);

  sym2.AssignTradingDay(day3);
  sym2.AssignTradingDay(day4);

Затем я сохраняю его в объектной базе данных db4o:

  // Store in the database.
  db4o.db.Store(sym1);
  db4o.db.Store(sym2);
  db4o.db.Commit();  

Пока довольно просто.

Я проверяю базу данных с помощью «db4o Object Manager Enterprise», и действительно, там два символа, и если я нажму на каждый символ, каждый из них будет содержать два дня.

Теперь я делаю запрос LINQ для извлечения данных:

 var daysForSymbolS1 = from Symbol s in db4o.db
                       from TradingDay t in db4o.db
                       where (s.SymbolGlobal == "IBM" 
                              && t.Date == new DateTime(2010, 10, 19))
                       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);
 } 

И происходит что-то странное:

IBM - 10/19/2010 12:00:00 AM - SPX meta     // This line should not appear because we have specified "IBM" in the filter.
IBM - 10/19/2010 12:00:00 AM - IBM meta

Несмотря на то, что я указал, что он должен возвращать данные только для «SPX», он также возвращает данные из «IBM».

Я делаю что-то явно не так?


person Contango    schedule 23.02.2011    source источник


Ответы (1)


Вы не опубликовали точное определение своих классов, но в настоящее время вы делаете декартово произведение в своем Запрос Linq - вы создаете все возможные комбинации, тогда как на самом деле вам нужны только «совпадающие» комбинации (поскольку торговый день в вашей схеме по какой-то причине кажется связанным с символом). Вместо этого вы должны сделать соединение, например:

  from TradingDay t in db4o.db
  join Symbol s in db4o.db
  on s.SymbolGlobal equals t.SymbolGlobal 
  where (s.SymbolGlobal == "IBM" 
         && t.Date == new DateTime(2010, 10, 19))
  ...
person BrokenGlass    schedule 23.02.2011
comment
Причина ошибки точно указана. К сожалению, db4o на самом деле не так хорошо поддерживает соединения, поскольку он возвращается к LINQ-to-objects и загружает всю базу данных в память в попытке найти правильное разрешение. Я думаю, что было бы лучше отказаться от LINQ и использовать QBE (Query By Example) для решения проблемы. - person Contango; 23.02.2011