在db4o中使用LINQ时进行“连接”的方法?

时间:2011-02-23 19:11:48

标签: linq db4o

是否有正确的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"

换句话说,如果我选择“APPLE”,然后选择“2010-10-19”,它应该返回“星期五的苹果”。

以下工作(它从符号和日期的每个组合的Cartesian Product中选择)

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。

更新

@Gamlor给出了一个精彩的答案,它就像一个魅力。

我还应该提一下,db4o的当前版本支持对集合进行索引。由于任何形式的1对多层次结构都是使用类似于包含某些子类的IList集合构造的,因此将数据库分解为层次结构可能会减慢速度和维护速度。

2 个答案:

答案 0 :(得分:2)

我希望它看起来更像这样......但是如果没有看到db4o.db的def那么很难说清楚

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 :(得分:1)

Hogan已经回答你需要使用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。您可以使用引用本身来进行连接。您不需要任何ID(如上所示)

然而,没有大问题。目前LINQ to db4o实现根本不支持LINQ-Operator(实际上你可以通过在连接上使用Go To Declaration来看到它)。这意味着它回退到LINQ to Objects。这意味着所有对象都被加载到内存中,然后在这些对象上执行LINQ to Object。那太慢了。

目前无法在db4o上有效执行查询。你通常用db4o做这些东西的方法是在符号上有一个Day-collection。该集合始终包含该符号的所有日期。然后,您可以查询符号,然后获取数据。

另一种方法是拆分查询:

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

编辑:我只想在符号列表中列出其他集合中的TradingDays时添加案例。然后你可以这样做:

            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;