DB4O: необходимо использовать GenericList вне блока использования соединения

#c# #db4o

#c# #db4o

Вопрос:

Я использую DB4O для хранения своих объектов. Пожалуйста, найдите ниже код to retrieve objects из DBO4 DB.

 public IList<T> GetList<T>()
        {
            IList<T> list = null;
            using (IObjectContainer db = Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), fullFilePath))
            {
                list = db.Query<T>(typeof(T));
            }
            return list;
        }
  

Вопрос в том, я НЕ могу применить цикл C # ‘foreach’ вне блока использования. Это выдает мне ошибку «Было вызвано исключение типа ‘Db4objects.Db4o.Ext.DatabaseClosedException'». как только я начинаю просматривать свой список outside of Using block

Я могу применить цикл C # ‘foreach’ внутри блока использования, но я хочу использовать свой общий список для другого уровня кода.Итак, мне, должно быть, нужен мой объект genericlist вне блока использования.

Пожалуйста, дайте мне решение для этого.

Заранее спасибо.

Ответ №1:

Просто добавляю в ответ ‘Femaref’ и комментарии:

1) Да, вам нужна новая конфигурация для каждого соединения. 2) Открытие базы данных занимает некоторое время. db4o необходимо прочитать метаданные, проверить, завершились ли транзакции и т.д.

В общем, вы не должны открывать и закрывать контейнер для каждой операции полностью. Это занимает много времени только для открытия и закрытия базы данных. Я предполагаю, что вы хотите использовать новый контейнер объектов для каждой операции, чтобы иметь транзакцию для каждой операции.

Я рекомендую вам немного изменить реализацию. Откройте контейнер объектов при запуске вашего приложения. И закрывать его при завершении работы приложения. А затем использовать контейнеры сеанса для каждой операции. Это должно быть намного быстрее, поскольку db4o не требуется выполнять всю работу по инициализации.

Вот так:

 // Open the container once for the life-time of your application
IObjectConainer rootContainer = Db4oEmbedded.OpenFile(......)

public IList<T> GetList<T>()
{
    using (IObjectContainer db = rootContainer.Ext().OpenSession())
    {
                    // As Femaref said, use to list to 'eagerly' load all data
        return db.Query<T>(typeof(T)).ToList();
    }
}
  

Комментарии:

1. Большое спасибо Gamlor. Предоставленная вами информация действительно ценна!!

2. Gamlor, в моем случае я сохраняю данные в двух разных файлах базы данных на основе моих бизнес-правил. Не могли бы вы, пожалуйста, сообщить мне, как мне открыть контейнер на время жизни приложения для двух разных файлов БД?

3. Ну, вы можете открыть несколько корневых контейнеров. Просто используйте ‘Db4oEmbedded. Откройте файл’ и назначьте этот контейнер другим полям. Я не знаю ваше приложение и какой способ для вас лучший. Вы могли бы сохранить корневой контейнер в словаре, а затем выбрать правильный контейнер в соответствии с ключом. Или использовать другой способ выбора правильного контейнера. А затем использовать .Ext().OpenSession() для выбранного контейнера.

Ответ №2:

У вас есть две возможности:

  1. обработайте удаление объекта db самостоятельно
  2. извлеките все необходимые данные из базы данных (через ToList , например), которая выполняет итерацию IEnumerable<T> и возвращает это.

Комментарии:

1. Femaref, большое спасибо. Ваш 2-й вариант действительно работает… Еще один момент, который я хочу знать, что: 1) для каждого соединения, нужно ли мне использовать ‘Db4oEmbedded. NewConfiguration()’ в объекте подключения каждый раз, когда я хочу его подключить? Это правильный путь? 2) Я заметил, что всякий раз, когда я выполняю какую-либо операцию в DB4O, похоже, что для возврата ответа из файла DB требуется около 1 секунды (я сохранил простые 5 записей объектов POCO).. Это нормально?

2. У меня нет опыта работы с db4o, извините. Может быть, задать этот другой вопрос?