可以打开DB4o文件进行多次查询,插入,更新吗?

时间:2010-06-08 15:29:17

标签: db4o

这是我考虑使用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的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

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

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

您无需担心持续打开数据库文件。 db4o的关键目标之一是(移动)设备中的嵌入式使用。这就是为什么我们编写db4o的原因是你可以随时关闭你的机器而不会有数据库损坏的风险,即使文件仍处于打开状态。

为什么要获得GenericObject而不是Pilot对象的可能原因:

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

答案 1 :(得分:1)

可以多次重新打开数据库。问题在于表现并失去“身份”。此外,您无法保持对查询结果的引用,并在关闭数据库后尝试迭代它(基于您的代码,看起来您想这样做)。

当无法找到类时,会实例化GenericObjects。

你能提供一个完整的,极简主义的样本吗?

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

最佳