更新字段时,防止DB4O中的孤立对象

时间:2010-03-04 13:56:39

标签: .net db4o orphaned-objects

我想在DB4O中存储Person对象。人员位置字段可以随时间更改。所以我从数据库中检索一个人并调用一个方法将location字段设置为一个新的Location对象。 (我希望Location对象是不可变的,即DDD值对象)。

这样可行,但先前分配的Location对象仍然是数据库。如何配置DB4O以删除这些孤立的Location对象?或者我需要一些自定义过程来进行垃圾收集?

此示例的简化类:

class Person {
    Location location;
    public void Move(Location newLocation) { 
        location = newLocation;
    }
}

class Location {
    public Location(string city) { 
        this.City = city;
        //etc
    }
    public readonly string City;
    /// more fields...
}

编辑:更多信息 - Person应该是DDD聚合根。因此,没有外部引用一个人的内部状态。如果Person更新其位置,则旧位置应该不再存在。

5 个答案:

答案 0 :(得分:1)

我认为没有完美的解决方案。但是通过一些工作,你几乎可以实现这种行为。类似的主题是already discussed here

第一步是激活位置字段上的级联删除。因此,当删除Person时,该位置也将被删除。

configuration.common().objectClass(Person.class).objectField("location").cascadeOnDelete(true);

现在我们需要处理不断变化的位置案例。这个想法是这样的:

  1. 在activate-event上注册。在那里你记得'嵌入了哪个对象
  2. 注册更新事件。在那里你检查它是否仍然是相同的嵌入对象。如果没有,则删除旧的。
  3. 非常重要:永远不要'共享'嵌入对象,否则将被删除给所有人。一个简单的解决方案是在分配时创建Location-object的副本。
  4. implements this behavior的Java-Demo。

    嗯,这只是一个概念,对于一个可接受的解决方案来说还有很长的路要走:

    1. 利用属性或其他配置来指定哪些对象
    2. 构建事件处理程序等的强大实现。
    3. 确保不会删除“共享”位置的可靠解决方案

答案 1 :(得分:0)

如果首先在旧位置使用db4o的delete()然后存储新的位置?

最佳!

德语

答案 2 :(得分:0)

您是否考虑过将其设为值类型?

答案 3 :(得分:0)

这对我来说真的像是一笔交易。

就像德语说的那样,你必须删除旧的,存储并分配新的,并确保这些步骤可以一次性提交。

在RDBMS中,您也必须为此提出交易。但是,许多RDBMS系统通过触发器和事件为您提供支持。请注意,db4o还提供某些回调。

我目前正在为这样的案例进行ref-count抽象,但一般来说处理起来非常棘手。另一方面,您可以编写一个特定的Update方法,为您简化事务并比较旧对象和新对象的引用。如果它们不匹配,并且您可以确定没有其他人引用该类型的地址对象,则可以将其删除。

另请注意,如果您使用的语言没有垃圾回收,您还必须手动跟踪并删除旧对象。

“聚合根”概念对我来说似乎很模糊 - 毕竟,这取决于观点,但这是另一个问题。

答案 4 :(得分:0)

根据 cascadeOnDelete(boolean)的db4o 8.0 API参考,应自动删除旧对象。这是doc的副本,请查看给定的示例。

sets cascaded delete behaviour. 

Setting cascadeOnDelete to true will result in the deletion of all member objects of instances of this class, if they are passed to ObjectContainer.delete(Object). 

Caution !
This setting will also trigger deletion of old member objects, on calls to ObjectContainer.store(Object).

An example of the behaviour:

ObjectContainer con;
Bar bar1 = new Bar();
Bar bar2 = new Bar();
foo.bar = bar1;
con.store(foo); // bar1 is stored as a member of foo
foo.bar = bar2;
con.store(foo); // bar2 is stored as a member of foo 

The last statement will also delete bar1 from the ObjectContainer, no matter how many other stored objects hold references to bar1. 

The default setting is false.

In client-server environment this setting should be used on both client and server. 

This setting can be applied to an open object container. 

Parameters:
flag - whether deletes are to be cascaded to member objects.
See Also:
ObjectField.cascadeOnDelete(boolean), ObjectContainer.delete(Object), Using callbacks

然而它不像打印那样有效,很奇怪。