2

这就是我正在考虑使用 DB4o 的方式。当我需要查询时,我会打开文件,读取并关闭:

using (IObjectContainer db = Db4oFactory.OpenFile(Db4oFactory.NewConfiguration(), YapFileName))
{
    try
    {
        List<Pilot> pilots = db.Query<Pilot>().ToList<Pilot>();
    }
    finally
    {
       try { db.Close(); }
       catch (Exception) { };
    }
}

稍后,当我需要插入时,然后

using (IObjectContainer db = Db4oFactory.OpenFile(Db4oFactory.NewConfiguration(), YapFileName))
{
    try
    {
        Pilot pilot1 = new Pilot("Michael Schumacher", 100);
        db.Store(pilot1);
    }
    finally
    {
       try { db.Close(); }
       catch (Exception) { };
    }
}

通过这种方式,我想我会保持文件更整洁,只在需要时打开它,并且大部分时间都关闭它。但我不断收到 InvalidCastException

Unable to cast object of type 'Db4objects.Db4o.Reflect.Generic.GenericObject' to type 'Pilot'

使用 DB4o 的正确方法是什么?

4

2 回答 2

5

不,以这种方式工作不是一个好主意。db4o ObjectContainer 旨在在您的应用程序运行时始终保持打开状态。有几个原因:

  • db4o 维护一个参考系统来识别持久对象,因此当您对已存储的对象(而不是存储新对象)调用 #store() 时,它可以进行更新。当您关闭 ObjectContainer 时,此参考系统将关闭,因此无法进行更新。
  • 每次重新打开它时都必须从数据库文件中读取类元数据。当使用所有持久类时,db4o 还必须再次分析它们的结构。虽然这两种操作都非常快,但您可能不希望每次存储单个对象时都会产生这种开销。
  • db4o 为类和字段索引以及数据库文件本身提供了非常有效的缓存。如果您关闭并重新打开文件,您将无法利用它们。
  • 当您使用多个线程时,您设置代码的方式可能会失败。如果两个线程想要同时打开数据库文件怎么办?db4o 数据库文件只能打开一次。可以针对同一个打开的实例运行多个事务和多个线程,如果您需要多个事务,也可以使用客户端/服务器模式。
  • 稍后您可能想尝试透明激活和透明持久性。透明激活在第一次访问对象成员时会延迟加载它们。透明持久性自动存储在事务中修改的所有对象。要使透明激活 (TA) 和透明持久性 (TP) 正常工作,您当然必须保持 ObjectContainer 处于打开状态。

您无需担心不断打开数据库文件。db4o 的主要目标之一是在(移动)设备中的嵌入式使用。这就是为什么我们以这样一种方式编写 db4o,即使文件仍然打开,您也可以随时关闭您的机器而不会冒数据库损坏的风险。

您获得 GenericObject 而不是 Pilot 对象的可能原因:

  • 当包含 Pilot 对象的程序集的程序集名称在两次运行之间发生更改时,可能会发生这种情况,因为您让 VisualStudio 自动生成名称或因为您手动更改了它。
  • 也许“db4o”是您的程序集名称的一部分?最近的版本之一在过滤内部类方面过于激进。这已经在很久以前修复了。您可能想下载并尝试最新版本,“开发”或“生产”都应该没问题。
  • 在我曾经做过的一次演示中,当 db4o ObjectContainers 在“使用”块中打开时,我曾经看到过非常奇怪的症状。无论如何,您可能希望在没有它的情况下工作并始终保持 db4o ObjectContainer 处于打开状态。
于 2010-06-08T20:57:33.070 回答
1

可以多次重新打开数据库。问题将是性能和失去“身份”。此外,您不能保留对查询结果的引用并在关闭数据库后尝试对其进行迭代(根据您的代码,看起来您想要这样做)。

找不到类时会实例化 GenericObjects。

您能否提供一个不适合您的完整、简约的样本?

另外,您使用的是哪个 db4o 版本?

最好的

于 2010-06-08T15:44:25.250 回答