【问题标题】:Retrieve an object in one DB4O session, store in another ('disconnected scenario')在一个 DB4O 会话中检索一个对象,存储在另一个中(“断开连接的场景”)
【发布时间】:2011-05-01 14:30:14
【问题描述】:

我试图弄清楚如何在 DB4O 中的客户端会话之间保持对象可用。据我了解,一旦客户端会话关闭,该对象就不再驻留在任何缓存中,尽管我有一个有效的 UUID,但我无法在不插入重复项的情况下对其调用 Store。我搜索了一种手动将其重新添加到缓存中的方法,但没有这种机制。重新检索它将迫使我从现在无用的对象中复制所有值。

这是上面的代码段:

Person person = new Person() { FirstName = "Howdoyu", LastName = "Du" };
Db4oUUID uuid;

 // Store the new person in one session
using (IObjectContainer client = server.OpenClient())
{
    client.Store(person);
    uuid = client.Ext().GetObjectInfo(person).GetUUID();
}

// Guy changed his name, it happens
person.FirstName = "Charlie";

using (var client = server.OpenClient())
{
    // TODO: MISSING SOME WAY TO RE-USE UUID HERE

    client.Store(person); // will create a new person, named charlie, instead of changing Mr. Du's first name
}

最新版本的 Eloquera 通过 [ID] 属性或通过 Store(uid, object) 支持这些场景。

有什么想法吗?

【问题讨论】:

    标签: c# .net db4o object-oriented-database oodb


    【解决方案1】:

    db4o =( 中确实缺少此功能。这使得 db4o 在许多场景中都很难使用。

    您基本上必须通过处理所有属性来编写自己的重新附加方法。也许像 Automapper 这样的库可以提供帮助,但最终你必须自己做。

    另一个问题是您是否真的想使用 db4o UUID 来识别对象。 db4o UUID 很大,不是众所周知的类型。我个人更喜欢常规的 .NET GUID。

    顺便说一句:有一个 db4o .Bind() 方法,它将一个对象绑定到一个现有的 id。然而,它几乎没有你真正想要的。我猜您想存储对对象所做的更改。 Bind 基本上替换了对象并破坏了对象图。例如,如果你有一个部分加载的对象然后绑定它,你就会失去对对象的引用。所以 .Bind 不可用。

    【讨论】:

    • 感谢您的回复,我并没有真正期待解决方案 :( GUID 确实更易于使用,我原本希望使用它们,但我认为如果确实存在解决方案,它很可能会使用 UUID。我现在不得不在一个替代的、不太成熟的 OODB 或(非常可悲地)回到 ORM 的胖臂之间做出选择。
    • Bind() 实际上在我这里的特定场景中是可用的,我完全控制数据访问并且没有外部查询可以检索除我自己之外的对象实例。我在这里发布答案。
    【解决方案2】:

    好的,Gamlor 关于 db4o IExtContainer.Bind() 方法的响应为我指出了解决方案。请注意,此解决方案仅在对数据库的访问受到严格控制且没有外部查询可以检索对象实例的特定情况下有效。

    警告:此解决方案很危险。它可以用各种重复和垃圾对象填充您的数据库,因为它会替换对象并且不会更新其值,因此会破坏对它的任何引用。 Click here for a complete explanation.

    更新:即使在严格控制的场景中,这也可能会导致除了仅具有值类型属性(字符串、整数、 ETC。)。除非您可以将代码设计为在单个 db4o 连接中检索、编辑和保存对象,否则我建议您根本不要使用 db4o。

    Person person = new Person() { FirstName = "Charles", LastName = "The Second" };
    Db4oUUID uuid;
    
    using (IObjectContainer client = server.OpenClient())
    {
        // Store the new object for the first time
        client.Store(person);
    
        // Keep the UUID for later use
        uuid = client.Ext().GetObjectInfo(person).GetUUID();
    }
    
    // Guy changed his name, it happens
    person.FirstName = "Lil' Charlie";
    
    using (var client = server.OpenClient())
    {
        // Get a reference only (not data) to the stored object (server round trip, but lightweight)
        Person inactiveReference = (Person) client.Ext().GetByUUID(uuid);
    
        // Get the temp ID for this object within this client session
        long tempID = client.Ext().GetID(inactiveReference);
    
        // Replace the object the temp ID points to
        client.Ext().Bind(person, tempID);
    
        // Replace the stored object
        client.Store(person);
    }
    

    【讨论】:

    • 我只想说 bind 替换了对象,并没有更新它。这在复杂的对象图中尤其危险,因为它会产生不一致。但如果它对你有用,那就没问题了。
    • 是的,这就是我放大警告的原因:)
    • 我只是想补充一点,检索不需要通过 UUID 来完成。只要在检索 inactiveReference 之前在客户端上将 ActivateDepth 设置为 0,任何其他字段都将起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多