Получить объект в одном сеансе DB4O, сохранить в другом («отключенный сценарий») - PullRequest
1 голос
/ 01 мая 2011

Я пытаюсь выяснить, как сохранить объект пригодным для использования между сеансами клиента в 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).

Есть мысли?

Ответы [ 2 ]

1 голос
/ 03 мая 2011

Хорошо, ответ Gamlor о методе db4o IExtContainer.Bind () указал мне на решение. Обратите внимание, что это решение действительно только в очень специфических ситуациях, когда доступ к БД строго контролируется, и никакие внешние запросы не могут извлечь экземпляры объекта.

Предупреждение: это решение опасно . Он может заполнить вашу базу данных всеми видами дубликатов и ненужных объектов, потому что он заменяет объект и не обновляет его значения, поэтому нарушает любые ссылки на него. Нажмите здесь для полного объяснения .

ОБНОВЛЕНИЕ : Даже в строго контролируемых сценариях это может вызвать бесконечные головные боли (как у меня сейчас) для всего, кроме плоского объекта только со свойствами типа значения (string, int и т. Д.) .). Если вы не можете создать свой код для извлечения, редактирования и сохранения объектов в одном соединении 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);
}
1 голос
/ 02 мая 2011

Эта функция действительно отсутствует в db4o = (. Это делает db4o очень сложным для использования во многих сценариях.

В основном вам нужно написать собственный метод присоединения, скопировав все атрибуты. Может быть, такая библиотека, как Automapper, может помочь, но в конце концов вы должны сделать это сами.

Другой вопрос: действительно ли вы хотите использовать идентификаторы db4o для идентификации объекта. UUID db4o огромные и не очень известного типа. Я лично предпочел бы обычные .NET GUID.

Кстати: есть метод db4o .Bind (), который связывает объект с существующим идентификатором. Однако вряд ли это то, что вы действительно хотите Я предполагаю, что вы хотите сохранить изменения, внесенные в объект. Bind в основном заменяет объект и разрушает граф объекта. Например, если у вас есть частично загруженные объекты, а затем они привязаны, вы теряете ссылки на объекты. Так что .Bind не используется.

...