changeset 225:94c9908e6aca

removed DatabaseManager member out of class IndexBackend
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 01 Apr 2021 19:18:19 +0200
parents 61c309e06797
children a4918d57435c
files Framework/Plugins/DatabaseBackendAdapterV2.cpp Framework/Plugins/DatabaseBackendAdapterV3.cpp Framework/Plugins/DatabaseBackendAdapterV3.h Framework/Plugins/IDatabaseBackend.h Framework/Plugins/IndexBackend.cpp Framework/Plugins/IndexBackend.h Framework/Plugins/IndexUnitTests.h MySQL/Plugins/MySQLIndex.cpp MySQL/Plugins/MySQLIndex.h MySQL/UnitTests/UnitTestsMain.cpp PostgreSQL/Plugins/PostgreSQLIndex.cpp PostgreSQL/Plugins/PostgreSQLIndex.h PostgreSQL/UnitTests/PostgreSQLTests.cpp PostgreSQL/UnitTests/UnitTestsMain.cpp SQLite/Plugins/SQLiteIndex.cpp SQLite/Plugins/SQLiteIndex.h SQLite/UnitTests/UnitTestsMain.cpp
diffstat 17 files changed, 949 insertions(+), 653 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Plugins/DatabaseBackendAdapterV2.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV2.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -54,8 +54,8 @@
   {
   private:
     std::unique_ptr<IDatabaseBackend>  backend_;
-    boost::mutex                       databaseMutex_;
-    std::unique_ptr<DatabaseManager>   database_;
+    boost::mutex                       managerMutex_;
+    std::unique_ptr<DatabaseManager>   manager_;
 
   public:
     Adapter(IDatabaseBackend* backend) :
@@ -74,12 +74,12 @@
 
     void OpenConnection()
     {
-      boost::mutex::scoped_lock  lock(databaseMutex_);
+      boost::mutex::scoped_lock  lock(managerMutex_);
 
-      if (database_.get() == NULL)
+      if (manager_.get() == NULL)
       {
-        database_.reset(new DatabaseManager(backend_->CreateDatabaseFactory()));
-        database_->Open();
+        manager_.reset(new DatabaseManager(backend_->CreateDatabaseFactory()));
+        manager_->Open();
       }
       else
       {
@@ -89,16 +89,16 @@
 
     void CloseConnection()
     {
-      boost::mutex::scoped_lock  lock(databaseMutex_);
+      boost::mutex::scoped_lock  lock(managerMutex_);
 
-      if (database_.get() == NULL)
+      if (manager_.get() == NULL)
       {
         throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
       }
       else
       {
-        database_->Close();
-        database_.reset(NULL);
+        manager_->Close();
+        manager_.reset(NULL);
       }
     }
 
@@ -106,23 +106,23 @@
     {
     private:
       boost::mutex::scoped_lock  lock_;
-      DatabaseManager*           database_;
+      DatabaseManager*           manager_;
       
     public:
       DatabaseAccessor(Adapter& adapter) :
-        lock_(adapter.databaseMutex_),
-        database_(adapter.database_.get())
+        lock_(adapter.managerMutex_),
+        manager_(adapter.manager_.get())
       {
-        if (database_ == NULL)
+        if (manager_ == NULL)
         {
           throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
         }
       }
 
-      DatabaseManager& GetDatabase() const
+      DatabaseManager& GetManager() const
       {
-        assert(database_ != NULL);
-        return *database_;
+        assert(manager_ != NULL);
+        return *manager_;
       }
     };
   };
@@ -351,9 +351,8 @@
 
     try
     {
-      //DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);    // TODO
-      
-      adapter->GetBackend().AddAttachment(id, *attachment);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().AddAttachment(accessor.GetManager(), id, *attachment);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -368,7 +367,8 @@
 
     try
     {
-      adapter->GetBackend().AttachChild(parent, child);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().AttachChild(accessor.GetManager(), parent, child);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -381,7 +381,8 @@
 
     try
     {
-      adapter->GetBackend().ClearChanges();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().ClearChanges(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -394,7 +395,8 @@
 
     try
     {
-      adapter->GetBackend().ClearExportedResources();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().ClearExportedResources(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -410,7 +412,9 @@
 
     try
     {
-      *id = adapter->GetBackend().CreateResource(publicId, resourceType);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      
+      *id = adapter->GetBackend().CreateResource(accessor.GetManager(), publicId, resourceType);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -427,7 +431,8 @@
 
     try
     {
-      adapter->GetBackend().DeleteAttachment(*output, id, contentType);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().DeleteAttachment(*output, accessor.GetManager(), id, contentType);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -442,7 +447,8 @@
 
     try
     {
-      adapter->GetBackend().DeleteMetadata(id, metadataType);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().DeleteMetadata(accessor.GetManager(), id, metadataType);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -458,7 +464,8 @@
 
     try
     {
-      adapter->GetBackend().DeleteResource(*output, id);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().DeleteResource(*output, accessor.GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -475,8 +482,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<int64_t> target;
-      adapter->GetBackend().GetAllInternalIds(target, resourceType);
+      adapter->GetBackend().GetAllInternalIds(target, accessor.GetManager(), resourceType);
 
       for (std::list<int64_t>::const_iterator
              it = target.begin(); it != target.end(); ++it)
@@ -501,8 +510,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+
       std::list<std::string> ids;
-      adapter->GetBackend().GetAllPublicIds(ids, resourceType);
+      adapter->GetBackend().GetAllPublicIds(ids, accessor.GetManager(), resourceType);
 
       for (std::list<std::string>::const_iterator
              it = ids.begin(); it != ids.end(); ++it)
@@ -530,8 +541,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<std::string> ids;
-      adapter->GetBackend().GetAllPublicIds(ids, resourceType, since, limit);
+      adapter->GetBackend().GetAllPublicIds(ids, accessor.GetManager(), resourceType, since, limit);
 
       for (std::list<std::string>::const_iterator
              it = ids.begin(); it != ids.end(); ++it)
@@ -558,8 +571,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       bool done;
-      adapter->GetBackend().GetChanges(*output, done, since, maxResult);
+      adapter->GetBackend().GetChanges(*output, done, accessor.GetManager(), since, maxResult);
         
       if (done)
       {
@@ -583,8 +598,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<int64_t> target;
-      adapter->GetBackend().GetChildrenInternalId(target, id);
+      adapter->GetBackend().GetChildrenInternalId(target, accessor.GetManager(), id);
 
       for (std::list<int64_t>::const_iterator
              it = target.begin(); it != target.end(); ++it)
@@ -609,8 +626,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<std::string> ids;
-      adapter->GetBackend().GetChildrenPublicId(ids, id);
+      adapter->GetBackend().GetChildrenPublicId(ids, accessor.GetManager(), id);
 
       for (std::list<std::string>::const_iterator
              it = ids.begin(); it != ids.end(); ++it)
@@ -637,8 +656,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       bool done;
-      adapter->GetBackend().GetExportedResources(*output, done, since, maxResult);
+      adapter->GetBackend().GetExportedResources(*output, done, accessor.GetManager(), since, maxResult);
 
       if (done)
       {
@@ -660,7 +681,8 @@
 
     try
     {
-      adapter->GetBackend().GetLastChange(*output);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().GetLastChange(*output, accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -676,7 +698,8 @@
 
     try
     {
-      adapter->GetBackend().GetLastExportedResource(*output);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().GetLastExportedResource(*output, accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -693,7 +716,8 @@
 
     try
     {
-      adapter->GetBackend().GetMainDicomTags(*output, id);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().GetMainDicomTags(*output, accessor.GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -710,7 +734,9 @@
 
     try
     {
-      std::string s = adapter->GetBackend().GetPublicId(id);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
+      std::string s = adapter->GetBackend().GetPublicId(accessor.GetManager(), id);
       OrthancPluginDatabaseAnswerString(adapter->GetBackend().GetContext(),
                                         output->GetDatabase(),
                                         s.c_str());
@@ -729,7 +755,8 @@
 
     try
     {
-      *target = adapter->GetBackend().GetResourcesCount(resourceType);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      *target = adapter->GetBackend().GetResourcesCount(accessor.GetManager(), resourceType);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -744,7 +771,8 @@
 
     try
     {
-      *resourceType = adapter->GetBackend().GetResourceType(id);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      *resourceType = adapter->GetBackend().GetResourceType(accessor.GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -758,7 +786,8 @@
 
     try
     {
-      *target = adapter->GetBackend().GetTotalCompressedSize();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      *target = adapter->GetBackend().GetTotalCompressedSize(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -772,7 +801,8 @@
 
     try
     {
-      *target = adapter->GetBackend().GetTotalUncompressedSize();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      *target = adapter->GetBackend().GetTotalUncompressedSize(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -787,7 +817,8 @@
 
     try
     {
-      *existing = adapter->GetBackend().IsExistingResource(id);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      *existing = adapter->GetBackend().IsExistingResource(accessor.GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -802,7 +833,8 @@
 
     try
     {
-      *isProtected = adapter->GetBackend().IsProtectedPatient(id);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      *isProtected = adapter->GetBackend().IsProtectedPatient(accessor.GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -819,8 +851,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<int32_t> target;
-      adapter->GetBackend().ListAvailableMetadata(target, id);
+      adapter->GetBackend().ListAvailableMetadata(target, accessor.GetManager(), id);
 
       for (std::list<int32_t>::const_iterator
              it = target.begin(); it != target.end(); ++it)
@@ -846,8 +880,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<int32_t> target;
-      adapter->GetBackend().ListAvailableAttachments(target, id);
+      adapter->GetBackend().ListAvailableAttachments(target, accessor.GetManager(), id);
 
       for (std::list<int32_t>::const_iterator
              it = target.begin(); it != target.end(); ++it)
@@ -870,16 +906,18 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       int64_t id;
       OrthancPluginResourceType type;
-      if (!adapter->GetBackend().LookupResource(id, type, change->publicId) ||
+      if (!adapter->GetBackend().LookupResource(id, type, accessor.GetManager(), change->publicId) ||
           type != change->resourceType)
       {
         throw Orthanc::OrthancException(Orthanc::ErrorCode_Database);
       }
       else
       {
-        adapter->GetBackend().LogChange(change->changeType, id, type, change->date);
+        adapter->GetBackend().LogChange(accessor.GetManager(), change->changeType, id, type, change->date);
       }
       
       return OrthancPluginErrorCode_Success;
@@ -895,7 +933,8 @@
 
     try
     {
-      adapter->GetBackend().LogExportedResource(*exported);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().LogExportedResource(accessor.GetManager(), *exported);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -913,7 +952,8 @@
 
     try
     {
-      adapter->GetBackend().LookupAttachment(*output, id, contentType);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().LookupAttachment(*output, accessor.GetManager(), id, contentType);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -930,8 +970,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::string s;
-      if (adapter->GetBackend().LookupGlobalProperty(s, MISSING_SERVER_IDENTIFIER, property))
+      if (adapter->GetBackend().LookupGlobalProperty(s, accessor.GetManager(), MISSING_SERVER_IDENTIFIER, property))
       {
         OrthancPluginDatabaseAnswerString(adapter->GetBackend().GetContext(),
                                           output->GetDatabase(),
@@ -956,8 +998,11 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<int64_t> target;
-      adapter->GetBackend().LookupIdentifier(target, resourceType, tag->group, tag->element, constraint, tag->value);
+      adapter->GetBackend().LookupIdentifier(target, accessor.GetManager(), resourceType,
+                                             tag->group, tag->element, constraint, tag->value);
 
       for (std::list<int64_t>::const_iterator
              it = target.begin(); it != target.end(); ++it)
@@ -986,8 +1031,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::list<int64_t> target;
-      adapter->GetBackend().LookupIdentifierRange(target, resourceType, group, element, start, end);
+      adapter->GetBackend().LookupIdentifierRange(target, accessor.GetManager(), resourceType, group, element, start, end);
 
       for (std::list<int64_t>::const_iterator
              it = target.begin(); it != target.end(); ++it)
@@ -1013,8 +1060,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       std::string s;
-      if (adapter->GetBackend().LookupMetadata(s, id, metadata))
+      if (adapter->GetBackend().LookupMetadata(s, accessor.GetManager(), id, metadata))
       {
         OrthancPluginDatabaseAnswerString(adapter->GetBackend().GetContext(),
                                           output->GetDatabase(), s.c_str());
@@ -1036,8 +1085,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       int64_t parent;
-      if (adapter->GetBackend().LookupParent(parent, id))
+      if (adapter->GetBackend().LookupParent(parent, accessor.GetManager(), id))
       {
         OrthancPluginDatabaseAnswerInt64(adapter->GetBackend().GetContext(),
                                          output->GetDatabase(), parent);
@@ -1059,9 +1110,11 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       int64_t id;
       OrthancPluginResourceType type;
-      if (adapter->GetBackend().LookupResource(id, type, publicId))
+      if (adapter->GetBackend().LookupResource(id, type, accessor.GetManager(), publicId))
       {
         OrthancPluginDatabaseAnswerResource(adapter->GetBackend().GetContext(),
                                             output->GetDatabase(), 
@@ -1083,8 +1136,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       int64_t id;
-      if (adapter->GetBackend().SelectPatientToRecycle(id))
+      if (adapter->GetBackend().SelectPatientToRecycle(id, accessor.GetManager()))
       {
         OrthancPluginDatabaseAnswerInt64(adapter->GetBackend().GetContext(),
                                          output->GetDatabase(), id);
@@ -1106,8 +1161,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+
       int64_t id;
-      if (adapter->GetBackend().SelectPatientToRecycle(id, patientIdToAvoid))
+      if (adapter->GetBackend().SelectPatientToRecycle(id, accessor.GetManager(), patientIdToAvoid))
       {
         OrthancPluginDatabaseAnswerInt64(adapter->GetBackend().GetContext(),
                                          output->GetDatabase(), id);
@@ -1127,7 +1184,8 @@
 
     try
     {
-      adapter->GetBackend().SetGlobalProperty(MISSING_SERVER_IDENTIFIER, property, value);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().SetGlobalProperty(accessor.GetManager(), MISSING_SERVER_IDENTIFIER, property, value);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1142,7 +1200,8 @@
 
     try
     {
-      adapter->GetBackend().SetMainDicomTag(id, tag->group, tag->element, tag->value);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().SetMainDicomTag(accessor.GetManager(), id, tag->group, tag->element, tag->value);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1157,7 +1216,8 @@
 
     try
     {
-      adapter->GetBackend().SetIdentifierTag(id, tag->group, tag->element, tag->value);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().SetIdentifierTag(accessor.GetManager(), id, tag->group, tag->element, tag->value);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1173,7 +1233,8 @@
 
     try
     {
-      adapter->GetBackend().SetMetadata(id, metadata, value);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().SetMetadata(accessor.GetManager(), id, metadata, value);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1188,7 +1249,8 @@
 
     try
     {
-      adapter->GetBackend().SetProtectedPatient(id, (isProtected != 0));
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);      
+      adapter->GetBackend().SetProtectedPatient(accessor.GetManager(), id, (isProtected != 0));
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1201,7 +1263,8 @@
 
     try
     {
-      adapter->GetBackend().StartTransaction(TransactionType_ReadWrite);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      accessor.GetManager().StartTransaction(TransactionType_ReadWrite);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1214,7 +1277,8 @@
 
     try
     {
-      adapter->GetBackend().RollbackTransaction();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      accessor.GetManager().RollbackTransaction();
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1227,7 +1291,8 @@
 
     try
     {
-      adapter->GetBackend().CommitTransaction();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      accessor.GetManager().CommitTransaction();
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1240,8 +1305,7 @@
 
     try
     {
-      //adapter->OpenConnection();  // TODO
-      adapter->GetBackend().Open();
+      adapter->OpenConnection();
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1254,8 +1318,7 @@
 
     try
     {
-      adapter->GetBackend().Close();
-      //adapter->CloseConnection();  // TODO
+      adapter->CloseConnection();
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1269,7 +1332,8 @@
       
     try
     {
-      *version = adapter->GetBackend().GetDatabaseVersion();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      *version = adapter->GetBackend().GetDatabaseVersion(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1284,7 +1348,8 @@
       
     try
     {
-      adapter->GetBackend().UpgradeDatabase(targetVersion, storageArea);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().UpgradeDatabase(accessor.GetManager(), targetVersion, storageArea);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1298,7 +1363,8 @@
       
     try
     {
-      adapter->GetBackend().ClearMainDicomTags(internalId);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().ClearMainDicomTags(accessor.GetManager(), internalId);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1322,6 +1388,8 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+
       std::vector<Orthanc::DatabaseConstraint> lookup;
       lookup.reserve(constraintsCount);
 
@@ -1330,7 +1398,7 @@
         lookup.push_back(Orthanc::DatabaseConstraint(constraints[i]));
       }
         
-      adapter->GetBackend().LookupResources(*output, lookup, queryLevel, limit, (requestSomeInstance != 0));
+      adapter->GetBackend().LookupResources(*output, accessor.GetManager(), lookup, queryLevel, limit, (requestSomeInstance != 0));
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;
@@ -1350,7 +1418,8 @@
 
     try
     {
-      adapter->GetBackend().CreateInstance(*target, hashPatient, hashStudy, hashSeries, hashInstance);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().CreateInstance(*target, accessor.GetManager(), hashPatient, hashStudy, hashSeries, hashInstance);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;      
@@ -1372,9 +1441,9 @@
 
     try
     {
-      adapter->GetBackend().SetResourcesContent(countIdentifierTags, identifierTags,
-                                   countMainDicomTags, mainDicomTags,
-                                   countMetadata, metadata);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().SetResourcesContent(accessor.GetManager(), countIdentifierTags, identifierTags,
+                                                countMainDicomTags, mainDicomTags, countMetadata, metadata);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;      
@@ -1394,8 +1463,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+
       std::list<std::string> values;
-      adapter->GetBackend().GetChildrenMetadata(values, resourceId, metadata);
+      adapter->GetBackend().GetChildrenMetadata(values, accessor.GetManager(), resourceId, metadata);
 
       for (std::list<std::string>::const_iterator
              it = values.begin(); it != values.end(); ++it)
@@ -1419,7 +1490,8 @@
 
     try
     {
-      *result = adapter->GetBackend().GetLastChangeIndex();
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      *result = adapter->GetBackend().GetLastChangeIndex(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;      
@@ -1434,7 +1506,8 @@
 
     try
     {
-      adapter->GetBackend().TagMostRecentPatient(patientId);
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().TagMostRecentPatient(accessor.GetManager(), patientId);
       return OrthancPluginErrorCode_Success;
     }
     ORTHANC_PLUGINS_DATABASE_CATCH;      
@@ -1454,8 +1527,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+
       std::map<int32_t, std::string> result;
-      adapter->GetBackend().GetAllMetadata(result, resourceId);
+      adapter->GetBackend().GetAllMetadata(result, accessor.GetManager(), resourceId);
 
       for (std::map<int32_t, std::string>::const_iterator
              it = result.begin(); it != result.end(); ++it)
@@ -1489,8 +1564,10 @@
 
     try
     {
+      DatabaseBackendAdapterV2::Adapter::DatabaseAccessor accessor(*adapter);
+
       std::string parent;
-      if (adapter->GetBackend().LookupResourceAndParent(*id, *type, parent, publicId))
+      if (adapter->GetBackend().LookupResourceAndParent(*id, *type, parent, accessor.GetManager(), publicId))
       {
         *isExisting = 1;
 
--- a/Framework/Plugins/DatabaseBackendAdapterV3.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV3.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -56,6 +56,86 @@
 {
   static bool isBackendInUse_ = false;  // Only for sanity checks
   
+
+  // TODO - TURN THIS INTO A CONNECTION POOL
+  class DatabaseBackendAdapterV3::Adapter : public boost::noncopyable
+  {
+  private:
+    std::unique_ptr<IndexBackend>  backend_;
+    boost::mutex                       managerMutex_;
+    std::unique_ptr<DatabaseManager>   manager_;
+
+  public:
+    Adapter(IndexBackend* backend) :
+      backend_(backend)
+    {
+      if (backend == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      }
+    }
+
+    IndexBackend& GetBackend() const
+    {
+      return *backend_;
+    }
+
+    void OpenConnection()
+    {
+      boost::mutex::scoped_lock  lock(managerMutex_);
+
+      if (manager_.get() == NULL)
+      {
+        manager_.reset(new DatabaseManager(backend_->CreateDatabaseFactory()));
+        manager_->Open();
+      }
+      else
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      }
+    }
+
+    void CloseConnection()
+    {
+      boost::mutex::scoped_lock  lock(managerMutex_);
+
+      if (manager_.get() == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      }
+      else
+      {
+        manager_->Close();
+        manager_.reset(NULL);
+      }
+    }
+
+    class DatabaseAccessor : public boost::noncopyable
+    {
+    private:
+      boost::mutex::scoped_lock  lock_;
+      DatabaseManager*           manager_;
+      
+    public:
+      DatabaseAccessor(Adapter& adapter) :
+        lock_(adapter.managerMutex_),
+        manager_(adapter.manager_.get())
+      {
+        if (manager_ == NULL)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+        }
+      }
+
+      DatabaseManager& GetManager() const
+      {
+        assert(manager_ != NULL);
+        return *manager_;
+      }
+    };
+  };
+
+
   class DatabaseBackendAdapterV3::Output : public IDatabaseBackendOutput
   {
   private:
@@ -616,20 +696,14 @@
   class DatabaseBackendAdapterV3::Transaction : public boost::noncopyable
   {
   private:
-    boost::mutex::scoped_lock  lock_;    // TODO - REMOVE
-    IndexBackend&          backend_;
+    Adapter&   adapter_;
+    std::unique_ptr<Adapter::DatabaseAccessor>  accessor_;
     std::unique_ptr<Output>    output_;
 
-    static boost::mutex& GetMutex()   // TODO - REMOVE
-    {
-      static boost::mutex mutex_;
-      return mutex_;
-    }
-    
   public:
-    Transaction(IndexBackend& backend) :
-      lock_(GetMutex()),
-      backend_(backend),
+    Transaction(Adapter& adapter) :
+      adapter_(adapter),
+      accessor_(new Adapter::DatabaseAccessor(adapter)),
       output_(new Output)
     {
     }
@@ -640,7 +714,7 @@
 
     IndexBackend& GetBackend() const
     {
-      return backend_;
+      return adapter_.GetBackend();
     }
 
     Output& GetOutput() const
@@ -648,9 +722,9 @@
       return *output_;
     }
 
-    OrthancPluginContext* GetContext() const
+    DatabaseManager& GetManager() const
     {
-      return backend_.GetContext();
+      return accessor_->GetManager();
     }
   };
 
@@ -781,35 +855,35 @@
     
   static OrthancPluginErrorCode Open(void* database)
   {
-    IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
+    DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database);
 
     try
     {
-      backend->Open();
+      adapter->OpenConnection();
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetBackend().GetContext());
   }
 
   
   static OrthancPluginErrorCode Close(void* database)
   {
-    IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
+    DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database);
 
     try
     {
-      backend->Close();
+      adapter->CloseConnection();
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetBackend().GetContext());
   }
 
   
   static OrthancPluginErrorCode DestructDatabase(void* database)
   {
-    IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
+    DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database);
 
-    if (backend == NULL)
+    if (adapter == NULL)
     {
       return OrthancPluginErrorCode_InternalError;
     }
@@ -821,10 +895,10 @@
       }
       else
       {
-        OrthancPluginLogError(backend->GetContext(), "More than one index backend was registered, internal error");
+        OrthancPluginLogError(adapter->GetBackend().GetContext(), "More than one index backend was registered, internal error");
       }
       
-      delete backend;
+      delete adapter;
 
       return OrthancPluginErrorCode_Success;
     }
@@ -834,14 +908,15 @@
   static OrthancPluginErrorCode GetDatabaseVersion(void* database,
                                                    uint32_t* version)
   {
-    IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
+    DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database);
       
     try
     {
-      *version = backend->GetDatabaseVersion();
+      DatabaseBackendAdapterV3::Adapter::DatabaseAccessor accessor(*adapter);
+      *version = adapter->GetBackend().GetDatabaseVersion(accessor.GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetBackend().GetContext());
   }
 
 
@@ -849,14 +924,15 @@
                                                 OrthancPluginStorageArea* storageArea,
                                                 uint32_t  targetVersion)
   {
-    IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
+    DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database);
       
     try
     {
-      backend->UpgradeDatabase(targetVersion, storageArea);
+      DatabaseBackendAdapterV3::Adapter::DatabaseAccessor accessor(*adapter);
+      adapter->GetBackend().UpgradeDatabase(accessor.GetManager(), targetVersion, storageArea);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetBackend().GetContext());
   }
 
 
@@ -864,20 +940,20 @@
                                                  OrthancPluginDatabaseTransaction** target /* out */,
                                                  OrthancPluginDatabaseTransactionType type)
   {
-    IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
+    DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database);
       
     try
     {
-      std::unique_ptr<DatabaseBackendAdapterV3::Transaction> transaction(new DatabaseBackendAdapterV3::Transaction(*backend));
+      std::unique_ptr<DatabaseBackendAdapterV3::Transaction> transaction(new DatabaseBackendAdapterV3::Transaction(*adapter));
       
       switch (type)
       {
         case OrthancPluginDatabaseTransactionType_ReadOnly:
-          backend->StartTransaction(TransactionType_ReadOnly);
+          transaction->GetManager().StartTransaction(TransactionType_ReadOnly);
           break;
 
         case OrthancPluginDatabaseTransactionType_ReadWrite:
-          backend->StartTransaction(TransactionType_ReadWrite);
+          transaction->GetManager().StartTransaction(TransactionType_ReadWrite);
           break;
 
         default:
@@ -888,7 +964,7 @@
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetBackend().GetContext());
   }
 
   
@@ -913,10 +989,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().RollbackTransaction();
+      t->GetManager().RollbackTransaction();
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -928,10 +1004,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().CommitTransaction();
+      t->GetManager().CommitTransaction();
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -944,10 +1020,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().AddAttachment(id, *attachment);
+      t->GetBackend().AddAttachment(t->GetManager(), id, *attachment);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -958,10 +1034,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().ClearChanges();
+      t->GetBackend().ClearChanges(t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -972,10 +1048,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().ClearExportedResources();
+      t->GetBackend().ClearExportedResources(t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -987,10 +1063,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().ClearMainDicomTags(resourceId);
+      t->GetBackend().ClearMainDicomTags(t->GetManager(), resourceId);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1009,16 +1085,16 @@
 
       if (t->GetBackend().HasCreateInstance())
       {
-        t->GetBackend().CreateInstance(*target, hashPatient, hashStudy, hashSeries, hashInstance);
+        t->GetBackend().CreateInstance(*target, t->GetManager(), hashPatient, hashStudy, hashSeries, hashInstance);
       }
       else
       {
-        t->GetBackend().CreateInstanceGeneric(*target, hashPatient, hashStudy, hashSeries, hashInstance);
+        t->GetBackend().CreateInstanceGeneric(*target, t->GetManager(), hashPatient, hashStudy, hashSeries, hashInstance);
       }
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1031,10 +1107,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().DeleteAttachment(t->GetOutput(), id, contentType);
+      t->GetBackend().DeleteAttachment(t->GetOutput(), t->GetManager(), id, contentType);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1047,10 +1123,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().DeleteMetadata(id, metadataType);
+      t->GetBackend().DeleteMetadata(t->GetManager(), id, metadataType);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1062,10 +1138,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().DeleteResource(t->GetOutput(), id);
+      t->GetBackend().DeleteResource(t->GetOutput(), t->GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1079,7 +1155,7 @@
       t->GetOutput().Clear();
 
       std::map<int32_t, std::string> values;
-      t->GetBackend().GetAllMetadata(values, id);
+      t->GetBackend().GetAllMetadata(values, t->GetManager(), id);
 
       for (std::map<int32_t, std::string>::const_iterator it = values.begin(); it != values.end(); ++it)
       {
@@ -1088,7 +1164,7 @@
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1102,12 +1178,12 @@
       t->GetOutput().Clear();
 
       std::list<std::string> values;
-      t->GetBackend().GetAllPublicIds(values, resourceType);
+      t->GetBackend().GetAllPublicIds(values, t->GetManager(), resourceType);
       t->GetOutput().AnswerStrings(values);
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1123,12 +1199,12 @@
       t->GetOutput().Clear();
 
       std::list<std::string> values;
-      t->GetBackend().GetAllPublicIds(values, resourceType, since, limit);
+      t->GetBackend().GetAllPublicIds(values, t->GetManager(), resourceType, since, limit);
       t->GetOutput().AnswerStrings(values);
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1144,12 +1220,12 @@
       t->GetOutput().Clear();
 
       bool done;
-      t->GetBackend().GetChanges(t->GetOutput(), done, since, maxResults);
+      t->GetBackend().GetChanges(t->GetOutput(), done, t->GetManager(), since, maxResults);
       *targetDone = (done ? 1 : 0);
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1163,12 +1239,12 @@
       t->GetOutput().Clear();
 
       std::list<int64_t> values;
-      t->GetBackend().GetChildrenInternalId(values, id);
+      t->GetBackend().GetChildrenInternalId(values, t->GetManager(), id);
       t->GetOutput().AnswerIntegers64(values);
         
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1183,12 +1259,12 @@
       t->GetOutput().Clear();
 
       std::list<std::string> values;
-      t->GetBackend().GetChildrenMetadata(values, resourceId, metadata);
+      t->GetBackend().GetChildrenMetadata(values, t->GetManager(), resourceId, metadata);
       t->GetOutput().AnswerStrings(values);
         
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1202,12 +1278,12 @@
       t->GetOutput().Clear();
 
       std::list<std::string> values;
-      t->GetBackend().GetChildrenPublicId(values, id);
+      t->GetBackend().GetChildrenPublicId(values, t->GetManager(), id);
       t->GetOutput().AnswerStrings(values);
         
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1223,12 +1299,12 @@
       t->GetOutput().Clear();
 
       bool done;
-      t->GetBackend().GetExportedResources(t->GetOutput(), done, since, maxResults);
+      t->GetBackend().GetExportedResources(t->GetOutput(), done, t->GetManager(), since, maxResults);
       *targetDone = (done ? 1 : 0);
         
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1239,10 +1315,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().GetLastChange(t->GetOutput());
+      t->GetBackend().GetLastChange(t->GetOutput(), t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1254,10 +1330,10 @@
     try
     {
       t->GetOutput().Clear();
-      *target = t->GetBackend().GetLastChangeIndex();
+      *target = t->GetBackend().GetLastChangeIndex(t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1268,10 +1344,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().GetLastExportedResource(t->GetOutput());
+      t->GetBackend().GetLastExportedResource(t->GetOutput(), t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1283,10 +1359,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().GetMainDicomTags(t->GetOutput(), id);
+      t->GetBackend().GetMainDicomTags(t->GetOutput(), t->GetManager(), id);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1298,10 +1374,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetOutput().AnswerString(t->GetBackend().GetPublicId(id));
+      t->GetOutput().AnswerString(t->GetBackend().GetPublicId(t->GetManager(), id));
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1314,10 +1390,10 @@
     try
     {
       t->GetOutput().Clear();
-      *target = t->GetBackend().GetResourcesCount(resourceType);
+      *target = t->GetBackend().GetResourcesCount(t->GetManager(), resourceType);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1330,10 +1406,10 @@
     try
     {
       t->GetOutput().Clear();
-      *target = t->GetBackend().GetResourceType(resourceId);
+      *target = t->GetBackend().GetResourceType(t->GetManager(), resourceId);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1345,10 +1421,10 @@
     try
     {
       t->GetOutput().Clear();
-      *target = t->GetBackend().GetTotalCompressedSize();
+      *target = t->GetBackend().GetTotalCompressedSize(t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1360,10 +1436,10 @@
     try
     {
       t->GetOutput().Clear();
-      *target = t->GetBackend().GetTotalUncompressedSize();
+      *target = t->GetBackend().GetTotalUncompressedSize(t->GetManager());
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1376,11 +1452,11 @@
     try
     {
       t->GetOutput().Clear();
-      bool above = (t->GetBackend().GetTotalCompressedSize() >= threshold);
+      bool above = (t->GetBackend().GetTotalCompressedSize(t->GetManager()) >= threshold);
       *target = (above ? 1 : 0);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1393,11 +1469,11 @@
     try
     {
       t->GetOutput().Clear();
-      bool exists = t->GetBackend().IsExistingResource(resourceId);
+      bool exists = t->GetBackend().IsExistingResource(t->GetManager(), resourceId);
       *target = (exists ? 1 : 0);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1410,11 +1486,11 @@
     try
     {
       t->GetOutput().Clear();
-      bool isProtected = t->GetBackend().IsProtectedPatient(resourceId);
+      bool isProtected = t->GetBackend().IsProtectedPatient(t->GetManager(), resourceId);
       *target = (isProtected ? 1 : 0);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1428,11 +1504,11 @@
       t->GetOutput().Clear();
 
       std::list<int32_t> values;
-      t->GetBackend().ListAvailableAttachments(values, resourceId);
+      t->GetBackend().ListAvailableAttachments(values, t->GetManager(), resourceId);
       t->GetOutput().AnswerIntegers32(values);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1447,10 +1523,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().LogChange(changeType, resourceId, resourceType, date);
+      t->GetBackend().LogChange(t->GetManager(), changeType, resourceId, resourceType, date);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
   
 
@@ -1480,10 +1556,10 @@
       exported.sopInstanceUid = sopInstanceUid;
         
       t->GetOutput().Clear();
-      t->GetBackend().LogExportedResource(exported);
+      t->GetBackend().LogExportedResource(t->GetManager(), exported);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1496,10 +1572,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().LookupAttachment(t->GetOutput(), resourceId, contentType);
+      t->GetBackend().LookupAttachment(t->GetOutput(), t->GetManager(), resourceId, contentType);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1514,14 +1590,14 @@
       t->GetOutput().Clear();
 
       std::string s;
-      if (t->GetBackend().LookupGlobalProperty(s, serverIdentifier, property))
+      if (t->GetBackend().LookupGlobalProperty(s, t->GetManager(), serverIdentifier, property))
       {
         t->GetOutput().AnswerString(s);
       }
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1536,14 +1612,14 @@
       t->GetOutput().Clear();
 
       std::string s;
-      if (t->GetBackend().LookupMetadata(s, id, metadata))
+      if (t->GetBackend().LookupMetadata(s, t->GetManager(), id, metadata))
       {
         t->GetOutput().AnswerString(s);
       }
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1557,14 +1633,14 @@
       t->GetOutput().Clear();
 
       int64_t parentId;
-      if (t->GetBackend().LookupParent(parentId, id))
+      if (t->GetBackend().LookupParent(parentId, t->GetManager(), id))
       {
         t->GetOutput().AnswerInteger64(parentId);
       }
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1580,7 +1656,7 @@
     {
       t->GetOutput().Clear();
 
-      if (t->GetBackend().LookupResource(*id, *type, publicId))
+      if (t->GetBackend().LookupResource(*id, *type, t->GetManager(), publicId))
       {
         *isExisting = 1;
       }
@@ -1591,7 +1667,7 @@
         
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1616,10 +1692,10 @@
         lookup.push_back(Orthanc::DatabaseConstraint(constraints[i]));
       }
         
-      t->GetBackend().LookupResources(t->GetOutput(), lookup, queryLevel, limit, (requestSomeInstanceId != 0));
+      t->GetBackend().LookupResources(t->GetOutput(), t->GetManager(), lookup, queryLevel, limit, (requestSomeInstanceId != 0));
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
 
@@ -1636,7 +1712,7 @@
       t->GetOutput().Clear();
 
       std::string parent;
-      if (t->GetBackend().LookupResourceAndParent(*id, *type, parent, publicId))
+      if (t->GetBackend().LookupResourceAndParent(*id, *type, parent, t->GetManager(), publicId))
       {
         *isExisting = 1;
 
@@ -1652,7 +1728,7 @@
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
   
@@ -1665,14 +1741,14 @@
       t->GetOutput().Clear();
       
       int64_t id;
-      if (t->GetBackend().SelectPatientToRecycle(id))
+      if (t->GetBackend().SelectPatientToRecycle(id, t->GetManager()))
       {
         t->GetOutput().AnswerInteger64(id);
       }
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
     
@@ -1686,14 +1762,14 @@
       t->GetOutput().Clear();
       
       int64_t id;
-      if (t->GetBackend().SelectPatientToRecycle(id, patientIdToAvoid))
+      if (t->GetBackend().SelectPatientToRecycle(id, t->GetManager(), patientIdToAvoid))
       {
         t->GetOutput().AnswerInteger64(id);
       }
       
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
     
@@ -1707,10 +1783,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().SetGlobalProperty(serverIdentifier, property, value);
+      t->GetBackend().SetGlobalProperty(t->GetManager(), serverIdentifier, property, value);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
     
@@ -1724,10 +1800,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().SetMetadata(id, metadata, value);
+      t->GetBackend().SetMetadata(t->GetManager(), id, metadata, value);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
     
@@ -1740,10 +1816,10 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().SetProtectedPatient(id, (isProtected != 0));
+      t->GetBackend().SetProtectedPatient(t->GetManager(), id, (isProtected != 0));
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
     
@@ -1760,12 +1836,11 @@
     try
     {
       t->GetOutput().Clear();
-      t->GetBackend().SetResourcesContent(countIdentifierTags, identifierTags,
-                                          countMainDicomTags, mainDicomTags,
-                                          countMetadata, metadata);
+      t->GetBackend().SetResourcesContent(t->GetManager(), countIdentifierTags, identifierTags,
+                                          countMainDicomTags, mainDicomTags, countMetadata, metadata);
       return OrthancPluginErrorCode_Success;
     }
-    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
+    ORTHANC_PLUGINS_DATABASE_CATCH(t->GetBackend().GetContext());
   }
 
     
@@ -1855,7 +1930,7 @@
 
     OrthancPluginContext* context = backend->GetContext();
  
-    if (OrthancPluginRegisterDatabaseBackendV3(context, &params, sizeof(params), backend) != OrthancPluginErrorCode_Success)
+    if (OrthancPluginRegisterDatabaseBackendV3(context, &params, sizeof(params), new Adapter(backend)) != OrthancPluginErrorCode_Success)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend");
     }
--- a/Framework/Plugins/DatabaseBackendAdapterV3.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/DatabaseBackendAdapterV3.h	Thu Apr 01 19:18:19 2021 +0200
@@ -48,6 +48,7 @@
     }
 
   public:
+    class Adapter;
     class Transaction;
 
     class Factory : public IDatabaseBackendOutput::IFactory
--- a/Framework/Plugins/IDatabaseBackend.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/IDatabaseBackend.h	Thu Apr 01 19:18:19 2021 +0200
@@ -24,7 +24,7 @@
 
 #include "IDatabaseBackendOutput.h"
 #include "../Common/DatabasesEnumerations.h"
-#include "../Common/IDatabaseFactory.h"
+#include "../Common/DatabaseManager.h"
 
 #include <list>
 
@@ -45,40 +45,45 @@
                         
     virtual IDatabaseBackendOutput* CreateOutput() = 0;
 
-    virtual void Open() = 0;
-
-    virtual void Close() = 0;
-
-    virtual void AddAttachment(int64_t id,
+    virtual void AddAttachment(DatabaseManager& manager,
+                               int64_t id,
                                const OrthancPluginAttachment& attachment) = 0;
 
-    virtual void AttachChild(int64_t parent,
+    virtual void AttachChild(DatabaseManager& manager,
+                             int64_t parent,
                              int64_t child) = 0;
 
-    virtual void ClearChanges() = 0;
+    virtual void ClearChanges(DatabaseManager& manager) = 0;
 
-    virtual void ClearExportedResources() = 0;
+    virtual void ClearExportedResources(DatabaseManager& manager) = 0;
 
-    virtual int64_t CreateResource(const char* publicId,
+    virtual int64_t CreateResource(DatabaseManager& manager,
+                                   const char* publicId,
                                    OrthancPluginResourceType type) = 0;
 
     virtual void DeleteAttachment(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id,
                                   int32_t attachment) = 0;
 
-    virtual void DeleteMetadata(int64_t id,
+    virtual void DeleteMetadata(DatabaseManager& manager,
+                                int64_t id,
                                 int32_t metadataType) = 0;
 
     virtual void DeleteResource(IDatabaseBackendOutput& output,
+                                DatabaseManager& manager,
                                 int64_t id) = 0;
 
     virtual void GetAllInternalIds(std::list<int64_t>& target,
+                                   DatabaseManager& manager,
                                    OrthancPluginResourceType resourceType) = 0;
 
     virtual void GetAllPublicIds(std::list<std::string>& target,
+                                 DatabaseManager& manager,
                                  OrthancPluginResourceType resourceType) = 0;
 
     virtual void GetAllPublicIds(std::list<std::string>& target,
+                                 DatabaseManager& manager,
                                  OrthancPluginResourceType resourceType,
                                  uint64_t since,
                                  uint64_t limit) = 0;
@@ -86,68 +91,87 @@
     /* Use GetOutput().AnswerChange() */
     virtual void GetChanges(IDatabaseBackendOutput& output,
                             bool& done /*out*/,
+                            DatabaseManager& manager,
                             int64_t since,
                             uint32_t maxResults) = 0;
 
     virtual void GetChildrenInternalId(std::list<int64_t>& target /*out*/,
+                                       DatabaseManager& manager,
                                        int64_t id) = 0;
 
     virtual void GetChildrenPublicId(std::list<std::string>& target /*out*/,
+                                     DatabaseManager& manager,
                                      int64_t id) = 0;
 
     /* Use GetOutput().AnswerExportedResource() */
     virtual void GetExportedResources(IDatabaseBackendOutput& output,
                                       bool& done /*out*/,
+                                      DatabaseManager& manager,
                                       int64_t since,
                                       uint32_t maxResults) = 0;
 
     /* Use GetOutput().AnswerChange() */
-    virtual void GetLastChange(IDatabaseBackendOutput& output) = 0;
+    virtual void GetLastChange(IDatabaseBackendOutput& output,
+                               DatabaseManager& manager) = 0;
 
     /* Use GetOutput().AnswerExportedResource() */
-    virtual void GetLastExportedResource(IDatabaseBackendOutput& output) = 0;
+    virtual void GetLastExportedResource(IDatabaseBackendOutput& output,
+                                         DatabaseManager& manager) = 0;
 
     /* Use GetOutput().AnswerDicomTag() */
     virtual void GetMainDicomTags(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id) = 0;
 
-    virtual std::string GetPublicId(int64_t resourceId) = 0;
+    virtual std::string GetPublicId(DatabaseManager& manager,
+                                    int64_t resourceId) = 0;
 
-    virtual uint64_t GetResourcesCount(OrthancPluginResourceType resourceType) = 0;
+    virtual uint64_t GetResourcesCount(DatabaseManager& manager,
+                                       OrthancPluginResourceType resourceType) = 0;
 
-    virtual OrthancPluginResourceType GetResourceType(int64_t resourceId) = 0;
+    virtual OrthancPluginResourceType GetResourceType(DatabaseManager& manager,
+                                                      int64_t resourceId) = 0;
 
-    virtual uint64_t GetTotalCompressedSize() = 0;
+    virtual uint64_t GetTotalCompressedSize(DatabaseManager& manager) = 0;
     
-    virtual uint64_t GetTotalUncompressedSize() = 0;
+    virtual uint64_t GetTotalUncompressedSize(DatabaseManager& manager) = 0;
 
-    virtual bool IsExistingResource(int64_t internalId) = 0;
+    virtual bool IsExistingResource(DatabaseManager& manager,
+                                    int64_t internalId) = 0;
 
-    virtual bool IsProtectedPatient(int64_t internalId) = 0;
+    virtual bool IsProtectedPatient(DatabaseManager& manager,
+                                    int64_t internalId) = 0;
 
     virtual void ListAvailableMetadata(std::list<int32_t>& target /*out*/,
+                                       DatabaseManager& manager,
                                        int64_t id) = 0;
 
     virtual void ListAvailableAttachments(std::list<int32_t>& target /*out*/,
+                                          DatabaseManager& manager,
                                           int64_t id) = 0;
 
-    virtual void LogChange(int32_t changeType,
+    virtual void LogChange(DatabaseManager& manager,
+                           int32_t changeType,
                            int64_t resourceId,
                            OrthancPluginResourceType resourceType,
                            const char* date) = 0;
     
-    virtual void LogExportedResource(const OrthancPluginExportedResource& resource) = 0;
+    virtual void LogExportedResource(DatabaseManager& manager,
+                                     const OrthancPluginExportedResource& resource) = 0;
     
     /* Use GetOutput().AnswerAttachment() */
     virtual bool LookupAttachment(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id,
                                   int32_t contentType) = 0;
 
     virtual bool LookupGlobalProperty(std::string& target /*out*/,
+                                      DatabaseManager& manager,
                                       const char* serverIdentifier,
                                       int32_t property) = 0;
 
     virtual void LookupIdentifier(std::list<int64_t>& target /*out*/,
+                                  DatabaseManager& manager,
                                   OrthancPluginResourceType resourceType,
                                   uint16_t group,
                                   uint16_t element,
@@ -155,6 +179,7 @@
                                   const char* value) = 0;
 
     virtual void LookupIdentifierRange(std::list<int64_t>& target /*out*/,
+                                       DatabaseManager& manager,
                                        OrthancPluginResourceType resourceType,
                                        uint16_t group,
                                        uint16_t element,
@@ -162,64 +187,71 @@
                                        const char* end) = 0;
 
     virtual bool LookupMetadata(std::string& target /*out*/,
+                                DatabaseManager& manager,
                                 int64_t id,
                                 int32_t metadataType) = 0;
 
     virtual bool LookupParent(int64_t& parentId /*out*/,
+                              DatabaseManager& manager,
                               int64_t resourceId) = 0;
 
     virtual bool LookupResource(int64_t& id /*out*/,
                                 OrthancPluginResourceType& type /*out*/,
+                                DatabaseManager& manager,
                                 const char* publicId) = 0;
 
-    virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/) = 0;
+    virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/,
+                                        DatabaseManager& manager) = 0;
 
     virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/,
+                                        DatabaseManager& manager,
                                         int64_t patientIdToAvoid) = 0;
 
-    virtual void SetGlobalProperty(const char* serverIdentifier,
+    virtual void SetGlobalProperty(DatabaseManager& manager,
+                                   const char* serverIdentifier,
                                    int32_t property,
                                    const char* value) = 0;
 
-    virtual void SetMainDicomTag(int64_t id,
+    virtual void SetMainDicomTag(DatabaseManager& manager,
+                                 int64_t id,
                                  uint16_t group,
                                  uint16_t element,
                                  const char* value) = 0;
 
-    virtual void SetIdentifierTag(int64_t id,
+    virtual void SetIdentifierTag(DatabaseManager& manager,
+                                  int64_t id,
                                   uint16_t group,
                                   uint16_t element,
                                   const char* value) = 0;
 
-    virtual void SetMetadata(int64_t id,
+    virtual void SetMetadata(DatabaseManager& manager,
+                             int64_t id,
                              int32_t metadataType,
                              const char* value) = 0;
 
-    virtual void SetProtectedPatient(int64_t internalId, 
+    virtual void SetProtectedPatient(DatabaseManager& manager,
+                                     int64_t internalId, 
                                      bool isProtected) = 0;
 
-    virtual void StartTransaction(TransactionType type) = 0;
-
-    virtual void RollbackTransaction() = 0;
-
-    virtual void CommitTransaction() = 0;
-
-    virtual uint32_t GetDatabaseVersion() = 0;
+    virtual uint32_t GetDatabaseVersion(DatabaseManager& manager) = 0;
 
     /**
      * Upgrade the database to the specified version of the database
      * schema.  The upgrade script is allowed to make calls to
      * OrthancPluginReconstructMainDicomTags().
      **/
-    virtual void UpgradeDatabase(uint32_t  targetVersion,
+    virtual void UpgradeDatabase(DatabaseManager& manager,
+                                 uint32_t  targetVersion,
                                  OrthancPluginStorageArea* storageArea) = 0;
 
-    virtual void ClearMainDicomTags(int64_t internalId) = 0;
+    virtual void ClearMainDicomTags(DatabaseManager& manager,
+                                    int64_t internalId) = 0;
 
     virtual bool HasCreateInstance() const = 0;
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     virtual void LookupResources(IDatabaseBackendOutput& output,
+                                 DatabaseManager& manager,
                                  const std::vector<Orthanc::DatabaseConstraint>& lookup,
                                  OrthancPluginResourceType queryLevel,
                                  uint32_t limit,
@@ -228,6 +260,7 @@
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     virtual void CreateInstance(OrthancPluginCreateInstanceResult& result,
+                                DatabaseManager& manager,
                                 const char* hashPatient,
                                 const char* hashStudy,
                                 const char* hashSeries,
@@ -237,6 +270,7 @@
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     virtual void SetResourcesContent(
+      DatabaseManager& manager,
       uint32_t countIdentifierTags,
       const OrthancPluginResourcesContentTags* identifierTags,
       uint32_t countMainDicomTags,
@@ -247,12 +281,14 @@
 
     
     virtual void GetChildrenMetadata(std::list<std::string>& target,
+                                     DatabaseManager& manager,
                                      int64_t resourceId,
                                      int32_t metadata) = 0;
 
-    virtual int64_t GetLastChangeIndex() = 0;
+    virtual int64_t GetLastChangeIndex(DatabaseManager& manager) = 0;
 
-    virtual void TagMostRecentPatient(int64_t patientId) = 0;
+    virtual void TagMostRecentPatient(DatabaseManager& manager,
+                                      int64_t patientId) = 0;
 
 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
 #  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
@@ -260,6 +296,7 @@
     virtual bool LookupResourceAndParent(int64_t& id,
                                          OrthancPluginResourceType& type,
                                          std::string& parentPublicId,
+                                         DatabaseManager& manager,
                                          const char* publicId) = 0;
 #  endif
 #endif
@@ -267,6 +304,7 @@
 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
 #  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
     virtual void GetAllMetadata(std::map<int32_t, std::string>& result,
+                                DatabaseManager& manager,
                                 int64_t id) = 0;
 #  endif
 #endif
--- a/Framework/Plugins/IndexBackend.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/IndexBackend.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -175,6 +175,7 @@
 
   void IndexBackend::ReadChangesInternal(IDatabaseBackendOutput& output,
                                          bool& done,
+                                         DatabaseManager& manager,
                                          DatabaseManager::CachedStatement& statement,
                                          const Dictionary& args,
                                          uint32_t maxResults)
@@ -190,7 +191,7 @@
         ReadInteger64(statement, 0),
         ReadInteger32(statement, 1),
         static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 3)),
-        GetPublicId(ReadInteger64(statement, 2)),
+        GetPublicId(manager, ReadInteger64(statement, 2)),
         ReadString(statement, 4));
 
       statement.Next();
@@ -239,30 +240,31 @@
   }
 
 
-  void IndexBackend::ClearDeletedFiles()
+  void IndexBackend::ClearDeletedFiles(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "DELETE FROM DeletedFiles");
 
     statement.Execute();
   }
     
 
-  void IndexBackend::ClearDeletedResources()
+  void IndexBackend::ClearDeletedResources(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "DELETE FROM DeletedResources");
 
     statement.Execute();
   }
     
 
-  void IndexBackend::SignalDeletedFiles(IDatabaseBackendOutput& output)
+  void IndexBackend::SignalDeletedFiles(IDatabaseBackendOutput& output,
+                                        DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM DeletedFiles");
 
     statement.SetReadOnly(true);
@@ -287,10 +289,11 @@
   }
 
 
-  void IndexBackend::SignalDeletedResources(IDatabaseBackendOutput& output)
+  void IndexBackend::SignalDeletedResources(IDatabaseBackendOutput& output,
+                                            DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM DeletedResources");
 
     statement.SetReadOnly(true);
@@ -307,10 +310,8 @@
   }
 
 
-  IndexBackend::IndexBackend(OrthancPluginContext* context,
-                             IDatabaseFactory* factory) :
-    context_(context),
-    manager_(factory)
+  IndexBackend::IndexBackend(OrthancPluginContext* context) :
+    context_(context)
   {
   }
 
@@ -345,11 +346,12 @@
   }
 
   
-  void IndexBackend::AddAttachment(int64_t id,
+  void IndexBackend::AddAttachment(DatabaseManager& manager,
+                                   int64_t id,
                                    const OrthancPluginAttachment& attachment)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO AttachedFiles VALUES(${id}, ${type}, ${uuid}, "
       "${compressed}, ${uncompressed}, ${compression}, ${hash}, ${hash-compressed})");
 
@@ -376,11 +378,12 @@
   }
 
     
-  void IndexBackend::AttachChild(int64_t parent,
+  void IndexBackend::AttachChild(DatabaseManager& manager,
+                                 int64_t parent,
                                  int64_t child)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "UPDATE Resources SET parentId = ${parent} WHERE internalId = ${child}");
 
     statement.SetParameterType("parent", ValueType_Integer64);
@@ -394,20 +397,20 @@
   }
 
     
-  void IndexBackend::ClearChanges()
+  void IndexBackend::ClearChanges(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "DELETE FROM Changes");
 
     statement.Execute();
   }
 
     
-  void IndexBackend::ClearExportedResources()
+  void IndexBackend::ClearExportedResources(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "DELETE FROM ExportedResources");
 
     statement.Execute();
@@ -415,14 +418,15 @@
 
     
   void IndexBackend::DeleteAttachment(IDatabaseBackendOutput& output,
+                                      DatabaseManager& manager,
                                       int64_t id,
                                       int32_t attachment)
   {
-    ClearDeletedFiles();
+    ClearDeletedFiles(manager);
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM AttachedFiles WHERE id=${id} AND fileType=${type}");
 
       statement.SetParameterType("id", ValueType_Integer64);
@@ -435,15 +439,16 @@
       statement.Execute(args);
     }
 
-    SignalDeletedFiles(output);
+    SignalDeletedFiles(output, manager);
   }
 
     
-  void IndexBackend::DeleteMetadata(int64_t id,
+  void IndexBackend::DeleteMetadata(DatabaseManager& manager,
+                                    int64_t id,
                                     int32_t metadataType)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "DELETE FROM Metadata WHERE id=${id} and type=${type}");
 
     statement.SetParameterType("id", ValueType_Integer64);
@@ -458,16 +463,17 @@
 
     
   void IndexBackend::DeleteResource(IDatabaseBackendOutput& output,
+                                    DatabaseManager& manager,
                                     int64_t id)
   {
-    assert(manager_.GetDialect() != Dialect_MySQL);
+    assert(manager.GetDialect() != Dialect_MySQL);
     
-    ClearDeletedFiles();
-    ClearDeletedResources();
+    ClearDeletedFiles(manager);
+    ClearDeletedResources(manager);
     
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM RemainingAncestor");
 
       statement.Execute();
@@ -475,7 +481,7 @@
       
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM Resources WHERE internalId=${id}");
 
       statement.SetParameterType("id", ValueType_Integer64);
@@ -489,7 +495,7 @@
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "SELECT * FROM RemainingAncestor");
 
       statement.Execute();
@@ -505,16 +511,17 @@
       }
     }
     
-    SignalDeletedFiles(output);
-    SignalDeletedResources(output);
+    SignalDeletedFiles(output, manager);
+    SignalDeletedResources(output, manager);
   }
 
 
   void IndexBackend::GetAllInternalIds(std::list<int64_t>& target,
+                                       DatabaseManager& manager,
                                        OrthancPluginResourceType resourceType)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT internalId FROM Resources WHERE resourceType=${type}");
       
     statement.SetReadOnly(true);
@@ -528,10 +535,11 @@
 
     
   void IndexBackend::GetAllPublicIds(std::list<std::string>& target,
+                                     DatabaseManager& manager,
                                      OrthancPluginResourceType resourceType)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT publicId FROM Resources WHERE resourceType=${type}");
       
     statement.SetReadOnly(true);
@@ -545,12 +553,13 @@
 
     
   void IndexBackend::GetAllPublicIds(std::list<std::string>& target,
+                                     DatabaseManager& manager,
                                      OrthancPluginResourceType resourceType,
                                      uint64_t since,
                                      uint64_t limit)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT publicId FROM (SELECT publicId FROM Resources "
       "WHERE resourceType=${type}) AS tmp "
       "ORDER BY tmp.publicId LIMIT ${limit} OFFSET ${since}");
@@ -572,11 +581,12 @@
   /* Use GetOutput().AnswerChange() */
   void IndexBackend::GetChanges(IDatabaseBackendOutput& output,
                                 bool& done /*out*/,
+                                DatabaseManager& manager,
                                 int64_t since,
                                 uint32_t maxResults)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM Changes WHERE seq>${since} ORDER BY seq LIMIT ${limit}");
       
     statement.SetReadOnly(true);
@@ -587,15 +597,16 @@
     args.SetIntegerValue("limit", maxResults + 1);
     args.SetIntegerValue("since", since);
 
-    ReadChangesInternal(output, done, statement, args, maxResults);
+    ReadChangesInternal(output, done, manager, statement, args, maxResults);
   }
 
     
   void IndexBackend::GetChildrenInternalId(std::list<int64_t>& target /*out*/,
+                                           DatabaseManager& manager,
                                            int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT a.internalId FROM Resources AS a, Resources AS b  "
       "WHERE a.parentId = b.internalId AND b.internalId = ${id}");
       
@@ -610,10 +621,11 @@
 
     
   void IndexBackend::GetChildrenPublicId(std::list<std::string>& target /*out*/,
+                                         DatabaseManager& manager,
                                          int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT a.publicId FROM Resources AS a, Resources AS b  "
       "WHERE a.parentId = b.internalId AND b.internalId = ${id}");
       
@@ -630,11 +642,12 @@
   /* Use GetOutput().AnswerExportedResource() */
   void IndexBackend::GetExportedResources(IDatabaseBackendOutput& output,
                                           bool& done /*out*/,
+                                          DatabaseManager& manager,
                                           int64_t since,
                                           uint32_t maxResults)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM ExportedResources WHERE seq>${since} ORDER BY seq LIMIT ${limit}");
       
     statement.SetReadOnly(true);
@@ -650,10 +663,11 @@
 
     
   /* Use GetOutput().AnswerChange() */
-  void IndexBackend::GetLastChange(IDatabaseBackendOutput& output)
+  void IndexBackend::GetLastChange(IDatabaseBackendOutput& output,
+                                   DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1");
 
     statement.SetReadOnly(true);
@@ -661,15 +675,16 @@
     Dictionary args;
 
     bool done;  // Ignored
-    ReadChangesInternal(output, done, statement, args, 1);
+    ReadChangesInternal(output, done, manager, statement, args, 1);
   }
 
     
   /* Use GetOutput().AnswerExportedResource() */
-  void IndexBackend::GetLastExportedResource(IDatabaseBackendOutput& output)
+  void IndexBackend::GetLastExportedResource(IDatabaseBackendOutput& output,
+                                             DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1");
 
     statement.SetReadOnly(true);
@@ -683,10 +698,11 @@
     
   /* Use GetOutput().AnswerDicomTag() */
   void IndexBackend::GetMainDicomTags(IDatabaseBackendOutput& output,
+                                      DatabaseManager& manager,
                                       int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM MainDicomTags WHERE id=${id}");
 
     statement.SetReadOnly(true);
@@ -707,10 +723,11 @@
   }
 
     
-  std::string IndexBackend::GetPublicId(int64_t resourceId)
+  std::string IndexBackend::GetPublicId(DatabaseManager& manager,
+                                        int64_t resourceId)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT publicId FROM Resources WHERE internalId=${id}");
 
     statement.SetReadOnly(true);
@@ -732,27 +749,28 @@
   }
 
     
-  uint64_t IndexBackend::GetResourcesCount(OrthancPluginResourceType resourceType)
+  uint64_t IndexBackend::GetResourcesCount(DatabaseManager& manager,
+                                           OrthancPluginResourceType resourceType)
   {
     std::unique_ptr<DatabaseManager::CachedStatement> statement;
 
-    switch (manager_.GetDialect())
+    switch (manager.GetDialect())
     {
       case Dialect_MySQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COUNT(*) AS UNSIGNED INT) FROM Resources WHERE resourceType=${type}"));
         break;
 
       case Dialect_PostgreSQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COUNT(*) AS BIGINT) FROM Resources WHERE resourceType=${type}"));
         break;
 
       case Dialect_SQLite:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT COUNT(*) FROM Resources WHERE resourceType=${type}"));
         break;
 
@@ -772,10 +790,11 @@
   }
 
     
-  OrthancPluginResourceType IndexBackend::GetResourceType(int64_t resourceId)
+  OrthancPluginResourceType IndexBackend::GetResourceType(DatabaseManager& manager,
+                                                          int64_t resourceId)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT resourceType FROM Resources WHERE internalId=${id}");
 
     statement.SetReadOnly(true);
@@ -797,29 +816,29 @@
   }
 
     
-  uint64_t IndexBackend::GetTotalCompressedSize()
+  uint64_t IndexBackend::GetTotalCompressedSize(DatabaseManager& manager)
   {
     std::unique_ptr<DatabaseManager::CachedStatement> statement;
 
     // NB: "COALESCE" is used to replace "NULL" by "0" if the number of rows is empty
 
-    switch (manager_.GetDialect())
+    switch (manager.GetDialect())
     {
       case Dialect_MySQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COALESCE(SUM(compressedSize), 0) AS UNSIGNED INTEGER) FROM AttachedFiles"));
         break;
         
       case Dialect_PostgreSQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COALESCE(SUM(compressedSize), 0) AS BIGINT) FROM AttachedFiles"));
         break;
 
       case Dialect_SQLite:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT COALESCE(SUM(compressedSize), 0) FROM AttachedFiles"));
         break;
 
@@ -834,29 +853,29 @@
   }
 
     
-  uint64_t IndexBackend::GetTotalUncompressedSize()
+  uint64_t IndexBackend::GetTotalUncompressedSize(DatabaseManager& manager)
   {
     std::unique_ptr<DatabaseManager::CachedStatement> statement;
 
     // NB: "COALESCE" is used to replace "NULL" by "0" if the number of rows is empty
 
-    switch (manager_.GetDialect())
+    switch (manager.GetDialect())
     {
       case Dialect_MySQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COALESCE(SUM(uncompressedSize), 0) AS UNSIGNED INTEGER) FROM AttachedFiles"));
         break;
         
       case Dialect_PostgreSQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COALESCE(SUM(uncompressedSize), 0) AS BIGINT) FROM AttachedFiles"));
         break;
 
       case Dialect_SQLite:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT COALESCE(SUM(uncompressedSize), 0) FROM AttachedFiles"));
         break;
 
@@ -871,10 +890,11 @@
   }
 
     
-  bool IndexBackend::IsExistingResource(int64_t internalId)
+  bool IndexBackend::IsExistingResource(DatabaseManager& manager,
+                                        int64_t internalId)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM Resources WHERE internalId=${id}");
 
     statement.SetReadOnly(true);
@@ -889,10 +909,11 @@
   }
 
     
-  bool IndexBackend::IsProtectedPatient(int64_t internalId)
+  bool IndexBackend::IsProtectedPatient(DatabaseManager& manager,
+                                        int64_t internalId)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM PatientRecyclingOrder WHERE patientId = ${id}");
 
     statement.SetReadOnly(true);
@@ -908,10 +929,11 @@
 
     
   void IndexBackend::ListAvailableMetadata(std::list<int32_t>& target /*out*/,
+                                           DatabaseManager& manager,
                                            int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT type FROM Metadata WHERE id=${id}");
       
     statement.SetReadOnly(true);
@@ -925,10 +947,11 @@
 
     
   void IndexBackend::ListAvailableAttachments(std::list<int32_t>& target /*out*/,
+                                              DatabaseManager& manager,
                                               int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT fileType FROM AttachedFiles WHERE id=${id}");
       
     statement.SetReadOnly(true);
@@ -941,13 +964,14 @@
   }
 
     
-  void IndexBackend::LogChange(int32_t changeType,
+  void IndexBackend::LogChange(DatabaseManager& manager,
+                               int32_t changeType,
                                int64_t resourceId,
                                OrthancPluginResourceType resourceType,
                                const char* date)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO Changes VALUES(${}, ${changeType}, ${id}, ${resourceType}, ${date})");
 
     statement.SetParameterType("changeType", ValueType_Integer64);
@@ -965,10 +989,11 @@
   }
 
     
-  void IndexBackend::LogExportedResource(const OrthancPluginExportedResource& resource)
+  void IndexBackend::LogExportedResource(DatabaseManager& manager,
+                                         const OrthancPluginExportedResource& resource)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO ExportedResources VALUES(${}, ${type}, ${publicId}, "
       "${modality}, ${patient}, ${study}, ${series}, ${instance}, ${date})");
 
@@ -997,11 +1022,12 @@
     
   /* Use GetOutput().AnswerAttachment() */
   bool IndexBackend::LookupAttachment(IDatabaseBackendOutput& output,
+                                      DatabaseManager& manager,
                                       int64_t id,
                                       int32_t contentType)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT uuid, uncompressedSize, compressionType, compressedSize, "
       "uncompressedHash, compressedHash FROM AttachedFiles WHERE id=${id} AND fileType=${type}");
 
@@ -1034,15 +1060,17 @@
 
     
   bool IndexBackend::LookupGlobalProperty(std::string& target /*out*/,
+                                          DatabaseManager& manager,
                                           const char* serverIdentifier,
                                           int32_t property)
   {
-    return ::OrthancDatabases::LookupGlobalProperty(target, manager_, serverIdentifier,
+    return ::OrthancDatabases::LookupGlobalProperty(target, manager, serverIdentifier,
                                                     static_cast<Orthanc::GlobalProperty>(property));
   }
 
     
   void IndexBackend::LookupIdentifier(std::list<int64_t>& target /*out*/,
+                                      DatabaseManager& manager,
                                       OrthancPluginResourceType resourceType,
                                       uint16_t group,
                                       uint16_t element,
@@ -1061,25 +1089,25 @@
       case OrthancPluginIdentifierConstraint_Equal:
         header += "d.value = ${value}";
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, manager_, header.c_str()));
+                          STATEMENT_FROM_HERE, manager, header.c_str()));
         break;
         
       case OrthancPluginIdentifierConstraint_SmallerOrEqual:
         header += "d.value <= ${value}";
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, manager_, header.c_str()));
+                          STATEMENT_FROM_HERE, manager, header.c_str()));
         break;
         
       case OrthancPluginIdentifierConstraint_GreaterOrEqual:
         header += "d.value >= ${value}";
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, manager_, header.c_str()));
+                          STATEMENT_FROM_HERE, manager, header.c_str()));
         break;
         
       case OrthancPluginIdentifierConstraint_Wildcard:
         header += "d.value LIKE ${value}";
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, manager_, header.c_str()));
+                          STATEMENT_FROM_HERE, manager, header.c_str()));
         break;
         
       default:
@@ -1118,6 +1146,7 @@
 
     
   void IndexBackend::LookupIdentifierRange(std::list<int64_t>& target /*out*/,
+                                           DatabaseManager& manager,
                                            OrthancPluginResourceType resourceType,
                                            uint16_t group,
                                            uint16_t element,
@@ -1125,7 +1154,7 @@
                                            const char* end)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE "
       "d.id = r.internalId AND r.resourceType=${type} AND d.tagGroup=${group} "
       "AND d.tagElement=${element} AND d.value>=${start} AND d.value<=${end}");
@@ -1156,11 +1185,12 @@
 
     
   bool IndexBackend::LookupMetadata(std::string& target /*out*/,
+                                    DatabaseManager& manager,
                                     int64_t id,
                                     int32_t metadataType)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT value FROM Metadata WHERE id=${id} and type=${type}");
 
     statement.SetReadOnly(true);
@@ -1186,10 +1216,11 @@
 
     
   bool IndexBackend::LookupParent(int64_t& parentId /*out*/,
+                                  DatabaseManager& manager,
                                   int64_t resourceId)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT parentId FROM Resources WHERE internalId=${id}");
 
     statement.SetReadOnly(true);
@@ -1215,10 +1246,11 @@
     
   bool IndexBackend::LookupResource(int64_t& id /*out*/,
                                     OrthancPluginResourceType& type /*out*/,
+                                    DatabaseManager& manager,
                                     const char* publicId)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT internalId, resourceType FROM Resources WHERE publicId=${id}");
 
     statement.SetReadOnly(true);
@@ -1242,10 +1274,11 @@
   }
 
     
-  bool IndexBackend::SelectPatientToRecycle(int64_t& internalId /*out*/)
+  bool IndexBackend::SelectPatientToRecycle(int64_t& internalId /*out*/,
+                                            DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT patientId FROM PatientRecyclingOrder ORDER BY seq ASC LIMIT 1");
 
     statement.SetReadOnly(true);
@@ -1264,10 +1297,11 @@
 
     
   bool IndexBackend::SelectPatientToRecycle(int64_t& internalId /*out*/,
+                                            DatabaseManager& manager,
                                             int64_t patientIdToAvoid)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT patientId FROM PatientRecyclingOrder "
       "WHERE patientId != ${id} ORDER BY seq ASC LIMIT 1");
 
@@ -1291,12 +1325,13 @@
   }
 
     
-  void IndexBackend::SetGlobalProperty(const char* serverIdentifier,
+  void IndexBackend::SetGlobalProperty(DatabaseManager& manager,
+                                       const char* serverIdentifier,
                                        int32_t property,
                                        const char* value)
   {
     return ::OrthancDatabases::SetGlobalProperty(
-      manager_, serverIdentifier, static_cast<Orthanc::GlobalProperty>(property), value);
+      manager, serverIdentifier, static_cast<Orthanc::GlobalProperty>(property), value);
   }
 
 
@@ -1321,40 +1356,43 @@
   }
 
     
-  void IndexBackend::SetMainDicomTag(int64_t id,
+  void IndexBackend::SetMainDicomTag(DatabaseManager& manager,
+                                     int64_t id,
                                      uint16_t group,
                                      uint16_t element,
                                      const char* value)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO MainDicomTags VALUES(${id}, ${group}, ${element}, ${value})");
 
     ExecuteSetTag(statement, id, group, element, value);
   }
 
     
-  void IndexBackend::SetIdentifierTag(int64_t id,
+  void IndexBackend::SetIdentifierTag(DatabaseManager& manager,
+                                      int64_t id,
                                       uint16_t group,
                                       uint16_t element,
                                       const char* value)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO DicomIdentifiers VALUES(${id}, ${group}, ${element}, ${value})");
         
     ExecuteSetTag(statement, id, group, element, value);
   } 
 
     
-  void IndexBackend::SetMetadata(int64_t id,
+  void IndexBackend::SetMetadata(DatabaseManager& manager,
+                                 int64_t id,
                                  int32_t metadataType,
                                  const char* value)
   {
-    if (manager_.GetDialect() == Dialect_SQLite)
+    if (manager.GetDialect() == Dialect_SQLite)
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "INSERT OR REPLACE INTO Metadata VALUES (${id}, ${type}, ${value})");
         
       statement.SetParameterType("id", ValueType_Integer64);
@@ -1372,7 +1410,7 @@
     {
       {
         DatabaseManager::CachedStatement statement(
-          STATEMENT_FROM_HERE, manager_,
+          STATEMENT_FROM_HERE, manager,
           "DELETE FROM Metadata WHERE id=${id} AND type=${type}");
         
         statement.SetParameterType("id", ValueType_Integer64);
@@ -1387,7 +1425,7 @@
 
       {
         DatabaseManager::CachedStatement statement(
-          STATEMENT_FROM_HERE, manager_,
+          STATEMENT_FROM_HERE, manager,
           "INSERT INTO Metadata VALUES (${id}, ${type}, ${value})");
         
         statement.SetParameterType("id", ValueType_Integer64);
@@ -1405,13 +1443,14 @@
   }
 
     
-  void IndexBackend::SetProtectedPatient(int64_t internalId, 
+  void IndexBackend::SetProtectedPatient(DatabaseManager& manager,
+                                         int64_t internalId, 
                                          bool isProtected)
   {
     if (isProtected)
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM PatientRecyclingOrder WHERE patientId=${id}");
         
       statement.SetParameterType("id", ValueType_Integer64);
@@ -1421,10 +1460,10 @@
         
       statement.Execute(args);
     }
-    else if (IsProtectedPatient(internalId))
+    else if (IsProtectedPatient(manager, internalId))
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "INSERT INTO PatientRecyclingOrder VALUES(${}, ${id})");
         
       statement.SetParameterType("id", ValueType_Integer64);
@@ -1441,16 +1480,16 @@
   }
 
     
-  uint32_t IndexBackend::GetDatabaseVersion()
+  uint32_t IndexBackend::GetDatabaseVersion(DatabaseManager& manager)
   {
     // Create a read-only, explicit transaction to read the database
     // version (this was a read-write, implicit transaction in
     // PostgreSQL plugin <= 3.3 and MySQL plugin <= 3.0)
-    DatabaseManager::Transaction transaction(GetManager(), TransactionType_ReadOnly);
+    DatabaseManager::Transaction transaction(manager, TransactionType_ReadOnly);
     
     std::string version = "unknown";
       
-    if (LookupGlobalProperty(version, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion))
+    if (LookupGlobalProperty(version, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion))
     {
       try
       {
@@ -1471,7 +1510,8 @@
    * schema.  The upgrade script is allowed to make calls to
    * OrthancPluginReconstructMainDicomTags().
    **/
-  void IndexBackend::UpgradeDatabase(uint32_t  targetVersion,
+  void IndexBackend::UpgradeDatabase(DatabaseManager& manager,
+                                     uint32_t  targetVersion,
                                      OrthancPluginStorageArea* storageArea)
   {
     LOG(ERROR) << "Upgrading database is not implemented by this plugin";
@@ -1479,11 +1519,12 @@
   }
 
     
-  void IndexBackend::ClearMainDicomTags(int64_t internalId)
+  void IndexBackend::ClearMainDicomTags(DatabaseManager& manager,
+                                        int64_t internalId)
   {
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM MainDicomTags WHERE id=${id}");
         
       statement.SetParameterType("id", ValueType_Integer64);
@@ -1496,7 +1537,7 @@
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM DicomIdentifiers WHERE id=${id}");
         
       statement.SetParameterType("id", ValueType_Integer64);
@@ -1510,27 +1551,27 @@
 
 
   // For unit testing only!
-  uint64_t IndexBackend::GetAllResourcesCount()
+  uint64_t IndexBackend::GetAllResourcesCount(DatabaseManager& manager)
   {
     std::unique_ptr<DatabaseManager::CachedStatement> statement;
 
-    switch (manager_.GetDialect())
+    switch (manager.GetDialect())
     {
       case Dialect_MySQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COUNT(*) AS UNSIGNED INT) FROM Resources"));
         break;
         
       case Dialect_PostgreSQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COUNT(*) AS BIGINT) FROM Resources"));
         break;
 
       case Dialect_SQLite:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT COUNT(*) FROM Resources"));
         break;
 
@@ -1546,27 +1587,27 @@
 
 
   // For unit testing only!
-  uint64_t IndexBackend::GetUnprotectedPatientsCount()
+  uint64_t IndexBackend::GetUnprotectedPatientsCount(DatabaseManager& manager)
   {
     std::unique_ptr<DatabaseManager::CachedStatement> statement;
 
-    switch (manager_.GetDialect())
+    switch (manager.GetDialect())
     {
       case Dialect_MySQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COUNT(*) AS UNSIGNED INT) FROM PatientRecyclingOrder"));
         break;
         
       case Dialect_PostgreSQL:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT CAST(COUNT(*) AS BIGINT) FROM PatientRecyclingOrder"));
         break;
 
       case Dialect_SQLite:
         statement.reset(new DatabaseManager::CachedStatement(
-                          STATEMENT_FROM_HERE, GetManager(),
+                          STATEMENT_FROM_HERE, manager,
                           "SELECT COUNT(*) FROM PatientRecyclingOrder"));
         break;
 
@@ -1583,10 +1624,11 @@
 
   // For unit testing only!
   bool IndexBackend::GetParentPublicId(std::string& target,
+                                       DatabaseManager& manager,
                                        int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "SELECT a.publicId FROM Resources AS a, Resources AS b "
       "WHERE a.internalId = b.parentId AND b.internalId = ${id}");
 
@@ -1612,10 +1654,11 @@
 
   // For unit tests only!
   void IndexBackend::GetChildren(std::list<std::string>& childrenPublicIds,
+                                 DatabaseManager& manager,
                                  int64_t id)
   { 
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "SELECT publicId FROM Resources WHERE parentId=${id}");
       
     statement.SetReadOnly(true);
@@ -1700,12 +1743,13 @@
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
   // New primitive since Orthanc 1.5.2
   void IndexBackend::LookupResources(IDatabaseBackendOutput& output,
+                                     DatabaseManager& manager,
                                      const std::vector<Orthanc::DatabaseConstraint>& lookup,
                                      OrthancPluginResourceType queryLevel,
                                      uint32_t limit,
                                      bool requestSomeInstance)
   {
-    LookupFormatter formatter(manager_.GetDialect());
+    LookupFormatter formatter(manager.GetDialect());
 
     std::string sql;
     Orthanc::ISqlLookupFormatter::Apply(sql, formatter, lookup,
@@ -1746,7 +1790,7 @@
       }
     }
 
-    DatabaseManager::StandaloneStatement statement(GetManager(), sql);
+    DatabaseManager::StandaloneStatement statement(manager, sql);
     formatter.PrepareStatement(statement);
 
     statement.Execute(formatter.GetDictionary());
@@ -1884,6 +1928,7 @@
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
   // New primitive since Orthanc 1.5.2
   void IndexBackend::SetResourcesContent(
+    DatabaseManager& manager,
     uint32_t countIdentifierTags,
     const OrthancPluginResourcesContentTags* identifierTags,
     uint32_t countMainDicomTags,
@@ -1898,24 +1943,25 @@
      * same limitation, to check.
      **/
     
-    ExecuteSetResourcesContentTags(GetManager(), "DicomIdentifiers", "i",
+    ExecuteSetResourcesContentTags(manager, "DicomIdentifiers", "i",
                                    countIdentifierTags, identifierTags);
 
-    ExecuteSetResourcesContentTags(GetManager(), "MainDicomTags", "t",
+    ExecuteSetResourcesContentTags(manager, "MainDicomTags", "t",
                                    countMainDicomTags, mainDicomTags);
 
-    ExecuteSetResourcesContentMetadata(GetManager(), countMetadata, metadata);
+    ExecuteSetResourcesContentMetadata(manager, countMetadata, metadata);
   }
 #endif
 
 
   // New primitive since Orthanc 1.5.2
   void IndexBackend::GetChildrenMetadata(std::list<std::string>& target,
+                                         DatabaseManager& manager,
                                          int64_t resourceId,
                                          int32_t metadata)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT value FROM Metadata WHERE type=${metadata} AND "
       "id IN (SELECT internalId FROM Resources WHERE parentId=${id})");
       
@@ -1932,13 +1978,14 @@
 
 
   // New primitive since Orthanc 1.5.2
-  void IndexBackend::TagMostRecentPatient(int64_t patient)
+  void IndexBackend::TagMostRecentPatient(DatabaseManager& manager,
+                                          int64_t patient)
   {
     int64_t seq;
     
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "SELECT * FROM PatientRecyclingOrder WHERE seq >= "
         "(SELECT seq FROM PatientRecyclingOrder WHERE patientid=${id}) ORDER BY seq LIMIT 2");
 
@@ -1972,7 +2019,7 @@
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM PatientRecyclingOrder WHERE seq=${seq}");
         
       statement.SetParameterType("seq", ValueType_Integer64);
@@ -1987,7 +2034,7 @@
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, manager_,
+        STATEMENT_FROM_HERE, manager,
         "INSERT INTO PatientRecyclingOrder VALUES(${}, ${id})");
         
       statement.SetParameterType("id", ValueType_Integer64);
@@ -2006,10 +2053,11 @@
 bool IndexBackend::LookupResourceAndParent(int64_t& id,
                                            OrthancPluginResourceType& type,
                                            std::string& parentPublicId,
+                                           DatabaseManager& manager,
                                            const char* publicId)
 {
   DatabaseManager::CachedStatement statement(
-    STATEMENT_FROM_HERE, manager_,
+    STATEMENT_FROM_HERE, manager,
     "SELECT resource.internalId, resource.resourceType, parent.publicId "
     "FROM Resources AS resource LEFT JOIN Resources parent ON parent.internalId=resource.parentId "
     "WHERE resource.publicId=${id}");
@@ -2067,10 +2115,11 @@
 #  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
   // New primitive since Orthanc 1.5.4
   void IndexBackend::GetAllMetadata(std::map<int32_t, std::string>& result,
+                                    DatabaseManager& manager,
                                     int64_t id)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, manager_,
+      STATEMENT_FROM_HERE, manager,
       "SELECT type, value FROM Metadata WHERE id=${id}");
       
     statement.SetReadOnly(true);
@@ -2105,6 +2154,7 @@
 
 
   void IndexBackend::CreateInstanceGeneric(OrthancPluginCreateInstanceResult& result,
+                                           DatabaseManager& manager,
                                            const char* hashPatient,
                                            const char* hashStudy,
                                            const char* hashSeries,
@@ -2116,7 +2166,7 @@
       OrthancPluginResourceType type;
       int64_t tmp;
         
-      if (LookupResource(tmp, type, hashInstance))
+      if (LookupResource(tmp, type, manager, hashInstance))
       {
         // The instance already exists
         assert(type == OrthancPluginResourceType_Instance);
@@ -2126,7 +2176,7 @@
       }
     }
 
-    result.instanceId = CreateResource(hashInstance, OrthancPluginResourceType_Instance);
+    result.instanceId = CreateResource(manager, hashInstance, OrthancPluginResourceType_Instance);
     result.isNewInstance = true;
 
     result.isNewPatient = false;
@@ -2142,28 +2192,28 @@
     {
       OrthancPluginResourceType dummy;
 
-      if (LookupResource(result.seriesId, dummy, hashSeries))
+      if (LookupResource(result.seriesId, dummy, manager, hashSeries))
       {
         assert(dummy == OrthancPluginResourceType_Series);
         // The patient, the study and the series already exist
 
-        bool ok = (LookupResource(result.patientId, dummy, hashPatient) &&
-                   LookupResource(result.studyId, dummy, hashStudy));
+        bool ok = (LookupResource(result.patientId, dummy, manager, hashPatient) &&
+                   LookupResource(result.studyId, dummy, manager, hashStudy));
         (void) ok;  // Remove warning about unused variable in release builds
         assert(ok);
       }
-      else if (LookupResource(result.studyId, dummy, hashStudy))
+      else if (LookupResource(result.studyId, dummy, manager, hashStudy))
       {
         assert(dummy == OrthancPluginResourceType_Study);
 
         // New series: The patient and the study already exist
         result.isNewSeries = true;
 
-        bool ok = LookupResource(result.patientId, dummy, hashPatient);
+        bool ok = LookupResource(result.patientId, dummy, manager, hashPatient);
         (void) ok;  // Remove warning about unused variable in release builds
         assert(ok);
       }
-      else if (LookupResource(result.patientId, dummy, hashPatient))
+      else if (LookupResource(result.patientId, dummy, manager, hashPatient))
       {
         assert(dummy == OrthancPluginResourceType_Patient);
 
@@ -2183,35 +2233,35 @@
     // Create the series if needed
     if (result.isNewSeries)
     {
-      result.seriesId = CreateResource(hashSeries, OrthancPluginResourceType_Series);
+      result.seriesId = CreateResource(manager, hashSeries, OrthancPluginResourceType_Series);
     }
 
     // Create the study if needed
     if (result.isNewStudy)
     {
-      result.studyId = CreateResource(hashStudy, OrthancPluginResourceType_Study);
+      result.studyId = CreateResource(manager, hashStudy, OrthancPluginResourceType_Study);
     }
 
     // Create the patient if needed
     if (result.isNewPatient)
     {
-      result.patientId = CreateResource(hashPatient, OrthancPluginResourceType_Patient);
+      result.patientId = CreateResource(manager, hashPatient, OrthancPluginResourceType_Patient);
     }
 
     // Create the parent-to-child links
-    AttachChild(result.seriesId, result.instanceId);
+    AttachChild(manager, result.seriesId, result.instanceId);
 
     if (result.isNewSeries)
     {
-      AttachChild(result.studyId, result.seriesId);
+      AttachChild(manager, result.studyId, result.seriesId);
     }
 
     if (result.isNewStudy)
     {
-      AttachChild(result.patientId, result.studyId);
+      AttachChild(manager, result.patientId, result.studyId);
     }
 
-    TagMostRecentPatient(result.patientId);
+    TagMostRecentPatient(manager, result.patientId);
       
     // Sanity checks
     assert(result.patientId != -1);
--- a/Framework/Plugins/IndexBackend.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/IndexBackend.h	Thu Apr 01 19:18:19 2021 +0200
@@ -21,7 +21,6 @@
 
 #pragma once
 
-#include "../Common/DatabaseManager.h"
 #include "IDatabaseBackend.h"
 
 #include <OrthancException.h>
@@ -35,16 +34,10 @@
     class LookupFormatter;
 
     OrthancPluginContext*  context_;
-    DatabaseManager        manager_;
 
     std::unique_ptr<IDatabaseBackendOutput::IFactory>  outputFactory_;
     
   protected:
-    DatabaseManager& GetManager()
-    {
-      return manager_;
-    }
-    
     static int64_t ReadInteger64(const DatabaseManager::StatementBase& statement,
                                  size_t field);
 
@@ -63,17 +56,20 @@
                                   DatabaseManager::CachedStatement& statement,
                                   const Dictionary& args);
 
-    void ClearDeletedFiles();
+    void ClearDeletedFiles(DatabaseManager& manager);
 
-    void ClearDeletedResources();
+    void ClearDeletedResources(DatabaseManager& manager);
 
-    void SignalDeletedFiles(IDatabaseBackendOutput& output);
+    void SignalDeletedFiles(IDatabaseBackendOutput& output,
+                            DatabaseManager& manager);
 
-    void SignalDeletedResources(IDatabaseBackendOutput& output);
+    void SignalDeletedResources(IDatabaseBackendOutput& output,
+                                DatabaseManager& manager);
 
   private:
     void ReadChangesInternal(IDatabaseBackendOutput& output,
                              bool& done,
+                             DatabaseManager& manager,
                              DatabaseManager::CachedStatement& statement,
                              const Dictionary& args,
                              uint32_t maxResults);
@@ -85,8 +81,7 @@
                                        uint32_t maxResults);
 
   public:
-    IndexBackend(OrthancPluginContext* context,
-                 IDatabaseFactory* factory);
+    IndexBackend(OrthancPluginContext* context);
 
     virtual OrthancPluginContext* GetContext() ORTHANC_OVERRIDE
     {
@@ -97,106 +92,123 @@
     
     virtual IDatabaseBackendOutput* CreateOutput() ORTHANC_OVERRIDE;
     
-    virtual void Open() ORTHANC_OVERRIDE
-    {
-      manager_.Open();
-    }
-    
-    virtual void Close() ORTHANC_OVERRIDE
-    {
-      manager_.Close();
-    }
-    
-    virtual void AddAttachment(int64_t id,
+    virtual void AddAttachment(DatabaseManager& manager,
+                               int64_t id,
                                const OrthancPluginAttachment& attachment) ORTHANC_OVERRIDE;
     
-    virtual void AttachChild(int64_t parent,
+    virtual void AttachChild(DatabaseManager& manager,
+                             int64_t parent,
                              int64_t child) ORTHANC_OVERRIDE;
     
-    virtual void ClearChanges() ORTHANC_OVERRIDE;
+    virtual void ClearChanges(DatabaseManager& manager) ORTHANC_OVERRIDE;
     
-    virtual void ClearExportedResources() ORTHANC_OVERRIDE;
+    virtual void ClearExportedResources(DatabaseManager& manager) ORTHANC_OVERRIDE;
 
     virtual void DeleteAttachment(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id,
                                   int32_t attachment) ORTHANC_OVERRIDE;
     
-    virtual void DeleteMetadata(int64_t id,
+    virtual void DeleteMetadata(DatabaseManager& manager,
+                                int64_t id,
                                 int32_t metadataType) ORTHANC_OVERRIDE;
     
     virtual void DeleteResource(IDatabaseBackendOutput& output,
+                                DatabaseManager& manager,
                                 int64_t id) ORTHANC_OVERRIDE;
 
     virtual void GetAllInternalIds(std::list<int64_t>& target,
+                                   DatabaseManager& manager,
                                    OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE;
     
     virtual void GetAllPublicIds(std::list<std::string>& target,
+                                 DatabaseManager& manager,
                                  OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE;
     
     virtual void GetAllPublicIds(std::list<std::string>& target,
+                                 DatabaseManager& manager,
                                  OrthancPluginResourceType resourceType,
                                  uint64_t since,
                                  uint64_t limit) ORTHANC_OVERRIDE;
     
     virtual void GetChanges(IDatabaseBackendOutput& output,
                             bool& done /*out*/,
+                            DatabaseManager& manager,
                             int64_t since,
                             uint32_t maxResults) ORTHANC_OVERRIDE;
     
     virtual void GetChildrenInternalId(std::list<int64_t>& target /*out*/,
+                                       DatabaseManager& manager,
                                        int64_t id) ORTHANC_OVERRIDE;
     
     virtual void GetChildrenPublicId(std::list<std::string>& target /*out*/,
+                                     DatabaseManager& manager,
                                      int64_t id) ORTHANC_OVERRIDE;
     
     virtual void GetExportedResources(IDatabaseBackendOutput& output,
                                       bool& done /*out*/,
+                                      DatabaseManager& manager,
                                       int64_t since,
                                       uint32_t maxResults) ORTHANC_OVERRIDE;
     
-    virtual void GetLastChange(IDatabaseBackendOutput& output) ORTHANC_OVERRIDE;
+    virtual void GetLastChange(IDatabaseBackendOutput& output,
+                               DatabaseManager& manager) ORTHANC_OVERRIDE;
     
-    virtual void GetLastExportedResource(IDatabaseBackendOutput& output) ORTHANC_OVERRIDE;
+    virtual void GetLastExportedResource(IDatabaseBackendOutput& output,
+                                         DatabaseManager& manager) ORTHANC_OVERRIDE;
     
     virtual void GetMainDicomTags(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id) ORTHANC_OVERRIDE;
     
-    virtual std::string GetPublicId(int64_t resourceId) ORTHANC_OVERRIDE;
+    virtual std::string GetPublicId(DatabaseManager& manager,
+                                    int64_t resourceId) ORTHANC_OVERRIDE;
     
-    virtual uint64_t GetResourcesCount(OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE;
+    virtual uint64_t GetResourcesCount(DatabaseManager& manager,
+                                       OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE;
     
-    virtual OrthancPluginResourceType GetResourceType(int64_t resourceId) ORTHANC_OVERRIDE;
+    virtual OrthancPluginResourceType GetResourceType(DatabaseManager& manager,
+                                                      int64_t resourceId) ORTHANC_OVERRIDE;
     
-    virtual uint64_t GetTotalCompressedSize() ORTHANC_OVERRIDE;
+    virtual uint64_t GetTotalCompressedSize(DatabaseManager& manager) ORTHANC_OVERRIDE;
     
-    virtual uint64_t GetTotalUncompressedSize() ORTHANC_OVERRIDE;
+    virtual uint64_t GetTotalUncompressedSize(DatabaseManager& manager) ORTHANC_OVERRIDE;
     
-    virtual bool IsExistingResource(int64_t internalId) ORTHANC_OVERRIDE;
+    virtual bool IsExistingResource(DatabaseManager& manager,
+                                    int64_t internalId) ORTHANC_OVERRIDE;
     
-    virtual bool IsProtectedPatient(int64_t internalId) ORTHANC_OVERRIDE;
+    virtual bool IsProtectedPatient(DatabaseManager& manager,
+                                    int64_t internalId) ORTHANC_OVERRIDE;
     
     virtual void ListAvailableMetadata(std::list<int32_t>& target /*out*/,
+                                       DatabaseManager& manager,
                                        int64_t id) ORTHANC_OVERRIDE;
     
     virtual void ListAvailableAttachments(std::list<int32_t>& target /*out*/,
+                                          DatabaseManager& manager,
                                           int64_t id) ORTHANC_OVERRIDE;
     
-    virtual void LogChange(int32_t changeType,
+    virtual void LogChange(DatabaseManager& manager,
+                           int32_t changeType,
                            int64_t resourceId,
                            OrthancPluginResourceType resourceType,
                            const char* date) ORTHANC_OVERRIDE;
     
-    virtual void LogExportedResource(const OrthancPluginExportedResource& resource) ORTHANC_OVERRIDE;
+    virtual void LogExportedResource(DatabaseManager& manager,
+                                     const OrthancPluginExportedResource& resource) ORTHANC_OVERRIDE;
     
     virtual bool LookupAttachment(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id,
                                   int32_t contentType) ORTHANC_OVERRIDE;
     
     virtual bool LookupGlobalProperty(std::string& target /*out*/,
+                                      DatabaseManager& manager,
                                       const char* serverIdentifier,
                                       int32_t property) ORTHANC_OVERRIDE;
     
     virtual void LookupIdentifier(std::list<int64_t>& target /*out*/,
+                                  DatabaseManager& manager,
                                   OrthancPluginResourceType resourceType,
                                   uint16_t group,
                                   uint16_t element,
@@ -204,6 +216,7 @@
                                   const char* value) ORTHANC_OVERRIDE;
     
     virtual void LookupIdentifierRange(std::list<int64_t>& target /*out*/,
+                                       DatabaseManager& manager,
                                        OrthancPluginResourceType resourceType,
                                        uint16_t group,
                                        uint16_t element,
@@ -211,84 +224,81 @@
                                        const char* end) ORTHANC_OVERRIDE;
 
     virtual bool LookupMetadata(std::string& target /*out*/,
+                                DatabaseManager& manager,
                                 int64_t id,
                                 int32_t metadataType) ORTHANC_OVERRIDE;
 
     virtual bool LookupParent(int64_t& parentId /*out*/,
+                              DatabaseManager& manager,
                               int64_t resourceId) ORTHANC_OVERRIDE;
     
     virtual bool LookupResource(int64_t& id /*out*/,
                                 OrthancPluginResourceType& type /*out*/,
+                                DatabaseManager& manager,
                                 const char* publicId) ORTHANC_OVERRIDE;
     
-    virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/) ORTHANC_OVERRIDE;
+    virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/,
+                                        DatabaseManager& manager) ORTHANC_OVERRIDE;
     
     virtual bool SelectPatientToRecycle(int64_t& internalId /*out*/,
+                                        DatabaseManager& manager,
                                         int64_t patientIdToAvoid) ORTHANC_OVERRIDE;
     
-    virtual void SetGlobalProperty(const char* serverIdentifier,
+    virtual void SetGlobalProperty(DatabaseManager& manager,
+                                   const char* serverIdentifier,
                                    int32_t property,
                                    const char* value) ORTHANC_OVERRIDE;
 
-    virtual void SetMainDicomTag(int64_t id,
+    virtual void SetMainDicomTag(DatabaseManager& manager,
+                                 int64_t id,
                                  uint16_t group,
                                  uint16_t element,
                                  const char* value) ORTHANC_OVERRIDE;
     
-    virtual void SetIdentifierTag(int64_t id,
+    virtual void SetIdentifierTag(DatabaseManager& manager,
+                                  int64_t id,
                                   uint16_t group,
                                   uint16_t element,
                                   const char* value) ORTHANC_OVERRIDE;
 
-    virtual void SetMetadata(int64_t id,
+    virtual void SetMetadata(DatabaseManager& manager,
+                             int64_t id,
                              int32_t metadataType,
                              const char* value) ORTHANC_OVERRIDE;
     
-    virtual void SetProtectedPatient(int64_t internalId, 
+    virtual void SetProtectedPatient(DatabaseManager& manager,
+                                     int64_t internalId, 
                                      bool isProtected) ORTHANC_OVERRIDE;
     
-    virtual void StartTransaction(TransactionType type) ORTHANC_OVERRIDE
-    {
-      manager_.StartTransaction(type);
-    }
-
+    virtual uint32_t GetDatabaseVersion(DatabaseManager& manager) ORTHANC_OVERRIDE;
     
-    virtual void RollbackTransaction() ORTHANC_OVERRIDE
-    {
-      manager_.RollbackTransaction();
-    }
-
-    
-    virtual void CommitTransaction() ORTHANC_OVERRIDE
-    {
-      manager_.CommitTransaction();
-    }
-
-    
-    virtual uint32_t GetDatabaseVersion() ORTHANC_OVERRIDE;
-    
-    virtual void UpgradeDatabase(uint32_t  targetVersion,
+    virtual void UpgradeDatabase(DatabaseManager& manager,
+                                 uint32_t  targetVersion,
                                  OrthancPluginStorageArea* storageArea) ORTHANC_OVERRIDE;
     
-    virtual void ClearMainDicomTags(int64_t internalId) ORTHANC_OVERRIDE;
+    virtual void ClearMainDicomTags(DatabaseManager& manager,
+                                    int64_t internalId) ORTHANC_OVERRIDE;
 
     // For unit testing only!
-    virtual uint64_t GetAllResourcesCount();
+    virtual uint64_t GetAllResourcesCount(DatabaseManager& manager);
 
     // For unit testing only!
-    virtual uint64_t GetUnprotectedPatientsCount();
+    virtual uint64_t GetUnprotectedPatientsCount(DatabaseManager& manager);
 
     // For unit testing only!
     virtual bool GetParentPublicId(std::string& target,
+                                   DatabaseManager& manager,
                                    int64_t id);
 
     // For unit tests only!
     virtual void GetChildren(std::list<std::string>& childrenPublicIds,
+                             DatabaseManager& manager,
                              int64_t id);
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     // New primitive since Orthanc 1.5.2
     virtual void LookupResources(IDatabaseBackendOutput& output,
+                                 DatabaseManager& manager,
                                  const std::vector<Orthanc::DatabaseConstraint>& lookup,
                                  OrthancPluginResourceType queryLevel,
                                  uint32_t limit,
@@ -298,6 +308,7 @@
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     // New primitive since Orthanc 1.5.2
     virtual void SetResourcesContent(
+      DatabaseManager& manager,
       uint32_t countIdentifierTags,
       const OrthancPluginResourcesContentTags* identifierTags,
       uint32_t countMainDicomTags,
@@ -308,10 +319,12 @@
 
     // New primitive since Orthanc 1.5.2
     virtual void GetChildrenMetadata(std::list<std::string>& target,
+                                     DatabaseManager& manager,
                                      int64_t resourceId,
                                      int32_t metadata) ORTHANC_OVERRIDE;
 
-    virtual void TagMostRecentPatient(int64_t patient) ORTHANC_OVERRIDE;
+    virtual void TagMostRecentPatient(DatabaseManager& manager,
+                                      int64_t patient) ORTHANC_OVERRIDE;
 
 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE)      // Macro introduced in 1.3.1
 #  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
@@ -319,6 +332,7 @@
     virtual bool LookupResourceAndParent(int64_t& id,
                                          OrthancPluginResourceType& type,
                                          std::string& parentPublicId,
+                                         DatabaseManager& manager,
                                          const char* publicId) ORTHANC_OVERRIDE;
 #  endif
 #endif
@@ -327,6 +341,7 @@
 #  if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 4)
     // New primitive since Orthanc 1.5.4
     virtual void GetAllMetadata(std::map<int32_t, std::string>& result,
+                                DatabaseManager& manager,
                                 int64_t id) ORTHANC_OVERRIDE;
 #  endif
 #endif
@@ -340,6 +355,7 @@
       
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     virtual void CreateInstance(OrthancPluginCreateInstanceResult& result,
+                                DatabaseManager& manager,
                                 const char* hashPatient,
                                 const char* hashStudy,
                                 const char* hashSeries,
@@ -352,6 +368,7 @@
     // This function corresponds to
     // "Orthanc::Compatibility::ICreateInstance::Apply()"
     void CreateInstanceGeneric(OrthancPluginCreateInstanceResult& result,
+                               DatabaseManager& manager,
                                const char* hashPatient,
                                const char* hashStudy,
                                const char* hashSeries,
--- a/Framework/Plugins/IndexUnitTests.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/Framework/Plugins/IndexUnitTests.h	Thu Apr 01 19:18:19 2021 +0200
@@ -181,128 +181,129 @@
 #endif
 
   db.SetOutputFactory(new DatabaseBackendAdapterV2::Factory(&context, NULL));
-  db.Open();
 
+  DatabaseManager manager(db.CreateDatabaseFactory());
+  manager.Open();
+  
   std::unique_ptr<IDatabaseBackendOutput> output(db.CreateOutput());
-  
 
   std::string s;
-  ASSERT_TRUE(db.LookupGlobalProperty(s, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion));
+  ASSERT_TRUE(db.LookupGlobalProperty(s, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion));
   ASSERT_EQ("6", s);
 
-  ASSERT_FALSE(db.LookupGlobalProperty(s, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence));
-  db.SetGlobalProperty(MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence, "Hello");
-  ASSERT_TRUE(db.LookupGlobalProperty(s, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence));
+  ASSERT_FALSE(db.LookupGlobalProperty(s, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence));
+  db.SetGlobalProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence, "Hello");
+  ASSERT_TRUE(db.LookupGlobalProperty(s, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence));
   ASSERT_EQ("Hello", s);
-  db.SetGlobalProperty(MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence, "HelloWorld");
-  ASSERT_TRUE(db.LookupGlobalProperty(s, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence));
+  db.SetGlobalProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence, "HelloWorld");
+  ASSERT_TRUE(db.LookupGlobalProperty(s, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_AnonymizationSequence));
   ASSERT_EQ("HelloWorld", s);
 
-  int64_t a = db.CreateResource("study", OrthancPluginResourceType_Study);
-  ASSERT_TRUE(db.IsExistingResource(a));
-  ASSERT_FALSE(db.IsExistingResource(a + 1));
+  int64_t a = db.CreateResource(manager, "study", OrthancPluginResourceType_Study);
+  ASSERT_TRUE(db.IsExistingResource(manager, a));
+  ASSERT_FALSE(db.IsExistingResource(manager, a + 1));
 
   int64_t b;
   OrthancPluginResourceType t;
-  ASSERT_FALSE(db.LookupResource(b, t, "world"));
-  ASSERT_TRUE(db.LookupResource(b, t, "study"));
+  ASSERT_FALSE(db.LookupResource(b, t, manager, "world"));
+  ASSERT_TRUE(db.LookupResource(b, t, manager, "study"));
   ASSERT_EQ(a, b);
   ASSERT_EQ(OrthancPluginResourceType_Study, t);
   
-  b = db.CreateResource("series", OrthancPluginResourceType_Series);
+  b = db.CreateResource(manager, "series", OrthancPluginResourceType_Series);
   ASSERT_NE(a, b);
 
-  ASSERT_EQ("study", db.GetPublicId(a));
-  ASSERT_EQ("series", db.GetPublicId(b));
-  ASSERT_EQ(OrthancPluginResourceType_Study, db.GetResourceType(a));
-  ASSERT_EQ(OrthancPluginResourceType_Series, db.GetResourceType(b));
+  ASSERT_EQ("study", db.GetPublicId(manager, a));
+  ASSERT_EQ("series", db.GetPublicId(manager, b));
+  ASSERT_EQ(OrthancPluginResourceType_Study, db.GetResourceType(manager, a));
+  ASSERT_EQ(OrthancPluginResourceType_Series, db.GetResourceType(manager, b));
 
-  db.AttachChild(a, b);
+  db.AttachChild(manager, a, b);
 
   int64_t c;
-  ASSERT_FALSE(db.LookupParent(c, a));
-  ASSERT_TRUE(db.LookupParent(c, b));
+  ASSERT_FALSE(db.LookupParent(c, manager, a));
+  ASSERT_TRUE(db.LookupParent(c, manager, b));
   ASSERT_EQ(a, c);
 
-  c = db.CreateResource("series2", OrthancPluginResourceType_Series);
-  db.AttachChild(a, c);
+  c = db.CreateResource(manager, "series2", OrthancPluginResourceType_Series);
+  db.AttachChild(manager, a, c);
 
-  ASSERT_EQ(3u, db.GetAllResourcesCount());
-  ASSERT_EQ(0u, db.GetResourcesCount(OrthancPluginResourceType_Patient));
-  ASSERT_EQ(1u, db.GetResourcesCount(OrthancPluginResourceType_Study));
-  ASSERT_EQ(2u, db.GetResourcesCount(OrthancPluginResourceType_Series));
+  ASSERT_EQ(3u, db.GetAllResourcesCount(manager));
+  ASSERT_EQ(0u, db.GetResourcesCount(manager, OrthancPluginResourceType_Patient));
+  ASSERT_EQ(1u, db.GetResourcesCount(manager, OrthancPluginResourceType_Study));
+  ASSERT_EQ(2u, db.GetResourcesCount(manager, OrthancPluginResourceType_Series));
 
-  ASSERT_FALSE(db.GetParentPublicId(s, a));
-  ASSERT_TRUE(db.GetParentPublicId(s, b));  ASSERT_EQ("study", s);
-  ASSERT_TRUE(db.GetParentPublicId(s, c));  ASSERT_EQ("study", s);
+  ASSERT_FALSE(db.GetParentPublicId(s, manager, a));
+  ASSERT_TRUE(db.GetParentPublicId(s, manager, b));  ASSERT_EQ("study", s);
+  ASSERT_TRUE(db.GetParentPublicId(s, manager, c));  ASSERT_EQ("study", s);
 
   std::list<std::string> children;
-  db.GetChildren(children, a);
+  db.GetChildren(children, manager, a);
   ASSERT_EQ(2u, children.size());
-  db.GetChildren(children, b);
+  db.GetChildren(children, manager, b);
   ASSERT_EQ(0u, children.size());
-  db.GetChildren(children, c);
+  db.GetChildren(children, manager, c);
   ASSERT_EQ(0u, children.size());
 
   std::list<std::string> cp;
-  db.GetChildrenPublicId(cp, a);
+  db.GetChildrenPublicId(cp, manager, a);
   ASSERT_EQ(2u, cp.size());
   ASSERT_TRUE(cp.front() == "series" || cp.front() == "series2");
   ASSERT_TRUE(cp.back() == "series" || cp.back() == "series2");
   ASSERT_NE(cp.front(), cp.back());
 
   std::list<std::string> pub;
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Patient);
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Patient);
   ASSERT_EQ(0u, pub.size());
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Study);
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Study);
   ASSERT_EQ(1u, pub.size());
   ASSERT_EQ("study", pub.front());
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Series);
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Series);
   ASSERT_EQ(2u, pub.size());
   ASSERT_TRUE(pub.front() == "series" || pub.front() == "series2");
   ASSERT_TRUE(pub.back() == "series" || pub.back() == "series2");
   ASSERT_NE(pub.front(), pub.back());
 
   std::list<int64_t> ci;
-  db.GetChildrenInternalId(ci, a);
+  db.GetChildrenInternalId(ci, manager, a);
   ASSERT_EQ(2u, ci.size());
   ASSERT_TRUE(ci.front() == b || ci.front() == c);
   ASSERT_TRUE(ci.back() == b || ci.back() == c);
   ASSERT_NE(ci.front(), ci.back());
 
-  db.SetMetadata(a, Orthanc::MetadataType_ModifiedFrom, "modified");
-  db.SetMetadata(a, Orthanc::MetadataType_LastUpdate, "update2");
-  ASSERT_FALSE(db.LookupMetadata(s, b, Orthanc::MetadataType_LastUpdate));
-  ASSERT_TRUE(db.LookupMetadata(s, a, Orthanc::MetadataType_LastUpdate));
+  db.SetMetadata(manager, a, Orthanc::MetadataType_ModifiedFrom, "modified");
+  db.SetMetadata(manager, a, Orthanc::MetadataType_LastUpdate, "update2");
+  ASSERT_FALSE(db.LookupMetadata(s, manager, b, Orthanc::MetadataType_LastUpdate));
+  ASSERT_TRUE(db.LookupMetadata(s, manager, a, Orthanc::MetadataType_LastUpdate));
   ASSERT_EQ("update2", s);
-  db.SetMetadata(a, Orthanc::MetadataType_LastUpdate, "update");
-  ASSERT_TRUE(db.LookupMetadata(s, a, Orthanc::MetadataType_LastUpdate));
+  db.SetMetadata(manager, a, Orthanc::MetadataType_LastUpdate, "update");
+  ASSERT_TRUE(db.LookupMetadata(s, manager, a, Orthanc::MetadataType_LastUpdate));
   ASSERT_EQ("update", s);
 
   std::list<int32_t> md;
-  db.ListAvailableMetadata(md, a);
+  db.ListAvailableMetadata(md, manager, a);
   ASSERT_EQ(2u, md.size());
   ASSERT_TRUE(md.front() == Orthanc::MetadataType_ModifiedFrom || md.back() == Orthanc::MetadataType_ModifiedFrom);
   ASSERT_TRUE(md.front() == Orthanc::MetadataType_LastUpdate || md.back() == Orthanc::MetadataType_LastUpdate);
   std::string mdd;
-  ASSERT_TRUE(db.LookupMetadata(mdd, a, Orthanc::MetadataType_ModifiedFrom));
+  ASSERT_TRUE(db.LookupMetadata(mdd, manager, a, Orthanc::MetadataType_ModifiedFrom));
   ASSERT_EQ("modified", mdd);
-  ASSERT_TRUE(db.LookupMetadata(mdd, a, Orthanc::MetadataType_LastUpdate));
+  ASSERT_TRUE(db.LookupMetadata(mdd, manager, a, Orthanc::MetadataType_LastUpdate));
   ASSERT_EQ("update", mdd);
 
-  db.ListAvailableMetadata(md, b);
+  db.ListAvailableMetadata(md, manager, b);
   ASSERT_EQ(0u, md.size());
 
-  db.DeleteMetadata(a, Orthanc::MetadataType_LastUpdate);
-  db.DeleteMetadata(b, Orthanc::MetadataType_LastUpdate);
-  ASSERT_FALSE(db.LookupMetadata(s, a, Orthanc::MetadataType_LastUpdate));
+  db.DeleteMetadata(manager, a, Orthanc::MetadataType_LastUpdate);
+  db.DeleteMetadata(manager, b, Orthanc::MetadataType_LastUpdate);
+  ASSERT_FALSE(db.LookupMetadata(s, manager, a, Orthanc::MetadataType_LastUpdate));
 
-  db.ListAvailableMetadata(md, a);
+  db.ListAvailableMetadata(md, manager, a);
   ASSERT_EQ(1u, md.size());
   ASSERT_EQ(Orthanc::MetadataType_ModifiedFrom, md.front());
 
-  ASSERT_EQ(0u, db.GetTotalCompressedSize());
-  ASSERT_EQ(0u, db.GetTotalUncompressedSize());
+  ASSERT_EQ(0u, db.GetTotalCompressedSize(manager));
+  ASSERT_EQ(0u, db.GetTotalUncompressedSize(manager));
 
 
   std::list<int32_t> fc;
@@ -325,17 +326,17 @@
   a2.compressedSize = 4242;
   a2.compressedHash = "md5_2";
     
-  db.AddAttachment(a, a1);
-  db.ListAvailableAttachments(fc, a);
+  db.AddAttachment(manager, a, a1);
+  db.ListAvailableAttachments(fc, manager, a);
   ASSERT_EQ(1u, fc.size());
   ASSERT_EQ(Orthanc::FileContentType_Dicom, fc.front());
-  db.AddAttachment(a, a2);
-  db.ListAvailableAttachments(fc, a);
+  db.AddAttachment(manager, a, a2);
+  db.ListAvailableAttachments(fc, manager, a);
   ASSERT_EQ(2u, fc.size());
-  ASSERT_FALSE(db.LookupAttachment(*output, b, Orthanc::FileContentType_Dicom));
+  ASSERT_FALSE(db.LookupAttachment(*output, manager, b, Orthanc::FileContentType_Dicom));
 
-  ASSERT_EQ(4284u, db.GetTotalCompressedSize());
-  ASSERT_EQ(4284u, db.GetTotalUncompressedSize());
+  ASSERT_EQ(4284u, db.GetTotalCompressedSize(manager));
+  ASSERT_EQ(4284u, db.GetTotalUncompressedSize(manager));
 
   expectedAttachment.reset(new OrthancPluginAttachment);
   expectedAttachment->uuid = "uuid1";
@@ -345,7 +346,7 @@
   expectedAttachment->compressionType = Orthanc::CompressionType_None;
   expectedAttachment->compressedSize = 42;
   expectedAttachment->compressedHash = "md5_1";
-  ASSERT_TRUE(db.LookupAttachment(*output, a, Orthanc::FileContentType_Dicom));
+  ASSERT_TRUE(db.LookupAttachment(*output, manager, a, Orthanc::FileContentType_Dicom));
 
   expectedAttachment.reset(new OrthancPluginAttachment);
   expectedAttachment->uuid = "uuid2";
@@ -355,21 +356,21 @@
   expectedAttachment->compressionType = Orthanc::CompressionType_None;
   expectedAttachment->compressedSize = 4242;
   expectedAttachment->compressedHash = "md5_2";
-  ASSERT_TRUE(db.LookupAttachment(*output, a, Orthanc::FileContentType_DicomAsJson));
+  ASSERT_TRUE(db.LookupAttachment(*output, manager, a, Orthanc::FileContentType_DicomAsJson));
 
-  db.ListAvailableAttachments(fc, b);
+  db.ListAvailableAttachments(fc, manager, b);
   ASSERT_EQ(0u, fc.size());
-  db.DeleteAttachment(*output, a, Orthanc::FileContentType_Dicom);
-  db.ListAvailableAttachments(fc, a);
+  db.DeleteAttachment(*output, manager, a, Orthanc::FileContentType_Dicom);
+  db.ListAvailableAttachments(fc, manager, a);
   ASSERT_EQ(1u, fc.size());
   ASSERT_EQ(Orthanc::FileContentType_DicomAsJson, fc.front());
-  db.DeleteAttachment(*output, a, Orthanc::FileContentType_DicomAsJson);
-  db.ListAvailableAttachments(fc, a);
+  db.DeleteAttachment(*output, manager, a, Orthanc::FileContentType_DicomAsJson);
+  db.ListAvailableAttachments(fc, manager, a);
   ASSERT_EQ(0u, fc.size());
 
 
-  db.SetIdentifierTag(a, 0x0010, 0x0020, "patient");
-  db.SetIdentifierTag(a, 0x0020, 0x000d, "study");
+  db.SetIdentifierTag(manager, a, 0x0010, 0x0020, "patient");
+  db.SetIdentifierTag(manager, a, 0x0020, 0x000d, "study");
 
   expectedDicomTags.clear();
   expectedDicomTags.push_back(OrthancPluginDicomTag());
@@ -380,14 +381,14 @@
   expectedDicomTags.back().group = 0x0020;
   expectedDicomTags.back().element = 0x000d;
   expectedDicomTags.back().value = "study";
-  db.GetMainDicomTags(*output, a);
+  db.GetMainDicomTags(*output, manager, a);
 
 
-  db.LookupIdentifier(ci, OrthancPluginResourceType_Study, 0x0010, 0x0020, 
+  db.LookupIdentifier(ci, manager, OrthancPluginResourceType_Study, 0x0010, 0x0020, 
                       OrthancPluginIdentifierConstraint_Equal, "patient");
   ASSERT_EQ(1u, ci.size());
   ASSERT_EQ(a, ci.front());
-  db.LookupIdentifier(ci, OrthancPluginResourceType_Study, 0x0010, 0x0020, 
+  db.LookupIdentifier(ci, manager, OrthancPluginResourceType_Study, 0x0010, 0x0020, 
                       OrthancPluginIdentifierConstraint_Equal, "study");
   ASSERT_EQ(0u, ci.size());
 
@@ -402,65 +403,67 @@
   exp.studyInstanceUid = "study";
   exp.seriesInstanceUid = "series";
   exp.sopInstanceUid = "instance";
-  db.LogExportedResource(exp);
+  db.LogExportedResource(manager, exp);
 
   expectedExported.reset(new OrthancPluginExportedResource());
   *expectedExported = exp;
   expectedExported->seq = 1;
 
   bool done;
-  db.GetExportedResources(*output, done, 0, 10);
+  db.GetExportedResources(*output, done, manager, 0, 10);
   
 
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Patient); ASSERT_EQ(0u, pub.size());
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Study); ASSERT_EQ(1u, pub.size());
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Series); ASSERT_EQ(2u, pub.size());
-  db.GetAllPublicIds(pub, OrthancPluginResourceType_Instance); ASSERT_EQ(0u, pub.size());
-  ASSERT_EQ(3u, db.GetAllResourcesCount());
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Patient); ASSERT_EQ(0u, pub.size());
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Study); ASSERT_EQ(1u, pub.size());
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Series); ASSERT_EQ(2u, pub.size());
+  db.GetAllPublicIds(pub, manager, OrthancPluginResourceType_Instance); ASSERT_EQ(0u, pub.size());
+  ASSERT_EQ(3u, db.GetAllResourcesCount(manager));
 
-  ASSERT_EQ(0u, db.GetUnprotectedPatientsCount());  // No patient was inserted
-  ASSERT_TRUE(db.IsExistingResource(c));
+  ASSERT_EQ(0u, db.GetUnprotectedPatientsCount(manager));  // No patient was inserted
+  ASSERT_TRUE(db.IsExistingResource(manager, c));
 
   {
     // A transaction is needed here for MySQL, as it was not possible
     // to implement recursive deletion of resources using pure SQL
     // statements
-    db.StartTransaction(TransactionType_ReadWrite);    
-    db.DeleteResource(*output, c);
-    db.CommitTransaction();
+    manager.StartTransaction(TransactionType_ReadWrite);    
+    db.DeleteResource(*output, manager, c);
+    manager.CommitTransaction();
   }
   
-  ASSERT_FALSE(db.IsExistingResource(c));
-  ASSERT_TRUE(db.IsExistingResource(a));
-  ASSERT_TRUE(db.IsExistingResource(b));
-  ASSERT_EQ(2u, db.GetAllResourcesCount());
-  db.DeleteResource(*output, a);
-  ASSERT_EQ(0u, db.GetAllResourcesCount());
-  ASSERT_FALSE(db.IsExistingResource(a));
-  ASSERT_FALSE(db.IsExistingResource(b));
-  ASSERT_FALSE(db.IsExistingResource(c));
+  ASSERT_FALSE(db.IsExistingResource(manager, c));
+  ASSERT_TRUE(db.IsExistingResource(manager, a));
+  ASSERT_TRUE(db.IsExistingResource(manager, b));
+  ASSERT_EQ(2u, db.GetAllResourcesCount(manager));
+  db.DeleteResource(*output, manager, a);
+  ASSERT_EQ(0u, db.GetAllResourcesCount(manager));
+  ASSERT_FALSE(db.IsExistingResource(manager, a));
+  ASSERT_FALSE(db.IsExistingResource(manager, b));
+  ASSERT_FALSE(db.IsExistingResource(manager, c));
 
-  ASSERT_EQ(0u, db.GetAllResourcesCount());
-  ASSERT_EQ(0u, db.GetUnprotectedPatientsCount());
-  int64_t p1 = db.CreateResource("patient1", OrthancPluginResourceType_Patient);
-  int64_t p2 = db.CreateResource("patient2", OrthancPluginResourceType_Patient);
-  int64_t p3 = db.CreateResource("patient3", OrthancPluginResourceType_Patient);
-  ASSERT_EQ(3u, db.GetUnprotectedPatientsCount());
+  ASSERT_EQ(0u, db.GetAllResourcesCount(manager));
+  ASSERT_EQ(0u, db.GetUnprotectedPatientsCount(manager));
+  int64_t p1 = db.CreateResource(manager, "patient1", OrthancPluginResourceType_Patient);
+  int64_t p2 = db.CreateResource(manager, "patient2", OrthancPluginResourceType_Patient);
+  int64_t p3 = db.CreateResource(manager, "patient3", OrthancPluginResourceType_Patient);
+  ASSERT_EQ(3u, db.GetUnprotectedPatientsCount(manager));
   int64_t r;
-  ASSERT_TRUE(db.SelectPatientToRecycle(r));
+  ASSERT_TRUE(db.SelectPatientToRecycle(r, manager));
   ASSERT_EQ(p1, r);
-  ASSERT_TRUE(db.SelectPatientToRecycle(r, p1));
+  ASSERT_TRUE(db.SelectPatientToRecycle(r, manager, p1));
   ASSERT_EQ(p2, r);
-  ASSERT_FALSE(db.IsProtectedPatient(p1));
-  db.SetProtectedPatient(p1, true);
-  ASSERT_TRUE(db.IsProtectedPatient(p1));
-  ASSERT_TRUE(db.SelectPatientToRecycle(r));
+  ASSERT_FALSE(db.IsProtectedPatient(manager, p1));
+  db.SetProtectedPatient(manager, p1, true);
+  ASSERT_TRUE(db.IsProtectedPatient(manager, p1));
+  ASSERT_TRUE(db.SelectPatientToRecycle(r, manager));
   ASSERT_EQ(p2, r);
-  db.SetProtectedPatient(p1, false);
-  ASSERT_FALSE(db.IsProtectedPatient(p1));
-  ASSERT_TRUE(db.SelectPatientToRecycle(r));
+  db.SetProtectedPatient(manager, p1, false);
+  ASSERT_FALSE(db.IsProtectedPatient(manager, p1));
+  ASSERT_TRUE(db.SelectPatientToRecycle(r, manager));
   ASSERT_EQ(p2, r);
-  db.DeleteResource(*output, p2);
-  ASSERT_TRUE(db.SelectPatientToRecycle(r, p3));
+  db.DeleteResource(*output, manager, p2);
+  ASSERT_TRUE(db.SelectPatientToRecycle(r, manager, p3));
   ASSERT_EQ(p1, r);
+
+  manager.Close();
 }
--- a/MySQL/Plugins/MySQLIndex.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/MySQL/Plugins/MySQLIndex.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -269,19 +269,20 @@
 
   MySQLIndex::MySQLIndex(OrthancPluginContext* context,
                          const MySQLParameters& parameters) :
-    IndexBackend(context, new Factory(*this)),
+    IndexBackend(context),
     parameters_(parameters),
     clearAll_(false)
   {
   }
 
 
-  int64_t MySQLIndex::CreateResource(const char* publicId,
+  int64_t MySQLIndex::CreateResource(DatabaseManager& manager,
+                                     const char* publicId,
                                      OrthancPluginResourceType type)
   {
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "INSERT INTO Resources VALUES(${}, ${type}, ${id}, NULL)");
     
       statement.SetParameterType("id", ValueType_Utf8String);
@@ -296,7 +297,7 @@
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "SELECT LAST_INSERT_ID()");
 
       statement.Execute();
@@ -307,9 +308,10 @@
 
 
   void MySQLIndex::DeleteResource(IDatabaseBackendOutput& output,
+                                  DatabaseManager& manager,
                                   int64_t id)
   {
-    ClearDeletedFiles();
+    ClearDeletedFiles(manager);
 
     // Recursive exploration of resources to be deleted, from the "id"
     // resource to the top of the tree of resources
@@ -322,7 +324,7 @@
       
       {
         DatabaseManager::CachedStatement lookupSiblings(
-          STATEMENT_FROM_HERE, GetManager(),
+          STATEMENT_FROM_HERE, manager,
           "SELECT parentId FROM Resources "
           "WHERE parentId = (SELECT parentId FROM Resources WHERE internalId=${id});");
 
@@ -355,7 +357,7 @@
             done = true;
 
             DatabaseManager::CachedStatement parent(
-              STATEMENT_FROM_HERE, GetManager(),
+              STATEMENT_FROM_HERE, manager,
               "SELECT publicId, resourceType FROM Resources WHERE internalId=${id};");
             
             parent.SetParameterType("id", ValueType_Integer64);
@@ -375,7 +377,7 @@
 
     {
       DatabaseManager::CachedStatement deleteHierarchy(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "DELETE FROM Resources WHERE internalId IN (SELECT * FROM (SELECT internalId FROM Resources WHERE internalId=${id} OR parentId=${id} OR parentId IN (SELECT internalId FROM Resources WHERE parentId=${id}) OR parentId IN (SELECT internalId FROM Resources WHERE parentId IN (SELECT internalId FROM Resources WHERE parentId=${id}))) as t);");
       
       deleteHierarchy.SetParameterType("id", ValueType_Integer64);
@@ -386,14 +388,14 @@
       deleteHierarchy.Execute(args);
     }
 
-    SignalDeletedFiles(output);
+    SignalDeletedFiles(output, manager);
   }
 
   
-  int64_t MySQLIndex::GetLastChangeIndex()
+  int64_t MySQLIndex::GetLastChangeIndex(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "SELECT value FROM GlobalIntegers WHERE property = 0");
     
     statement.SetReadOnly(true);
@@ -405,6 +407,7 @@
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
   void MySQLIndex::CreateInstance(OrthancPluginCreateInstanceResult& result,
+                                  DatabaseManager& manager,
                                   const char* hashPatient,
                                   const char* hashStudy,
                                   const char* hashSeries,
@@ -412,7 +415,7 @@
   {
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "CALL CreateInstance(${patient}, ${study}, ${series}, ${instance}, "
         "@isNewPatient, @isNewStudy, @isNewSeries, @isNewInstance, "
         "@patientKey, @studyKey, @seriesKey, @instanceKey)");
@@ -438,7 +441,7 @@
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "SELECT @isNewPatient, @isNewStudy, @isNewSeries, @isNewInstance, "
         "@patientKey, @studyKey, @seriesKey, @instanceKey");
 
--- a/MySQL/Plugins/MySQLIndex.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/MySQL/Plugins/MySQLIndex.h	Thu Apr 01 19:18:19 2021 +0200
@@ -76,14 +76,16 @@
       return new Factory(*this);
     }
 
-    virtual int64_t CreateResource(const char* publicId,
+    virtual int64_t CreateResource(DatabaseManager& manager,
+                                   const char* publicId,
                                    OrthancPluginResourceType type)
       ORTHANC_OVERRIDE;
 
     virtual void DeleteResource(IDatabaseBackendOutput& output,
+                                DatabaseManager& manager,
                                 int64_t id) ORTHANC_OVERRIDE;
 
-    virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE;
+    virtual int64_t GetLastChangeIndex(DatabaseManager& manager) ORTHANC_OVERRIDE;
 
     virtual bool HasCreateInstance() const  ORTHANC_OVERRIDE
     {
@@ -92,6 +94,7 @@
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     virtual void CreateInstance(OrthancPluginCreateInstanceResult& result,
+                                DatabaseManager& manager,
                                 const char* hashPatient,
                                 const char* hashStudy,
                                 const char* hashSeries,
--- a/MySQL/UnitTests/UnitTestsMain.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/MySQL/UnitTests/UnitTestsMain.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -49,18 +49,23 @@
 
   OrthancDatabases::MySQLIndex db1(NULL, noLock);
   db1.SetClearAll(true);
-  db1.Open();
+
+  OrthancDatabases::DatabaseManager manager1(db1.CreateDatabaseFactory());
+  manager1.Open();
 
   {
     OrthancDatabases::MySQLIndex db2(NULL, lock);
-    db2.Open();
+    OrthancDatabases::DatabaseManager manager2(db2.CreateDatabaseFactory());
+    manager2.Open();
 
     OrthancDatabases::MySQLIndex db3(NULL, lock);
-    ASSERT_THROW(db3.Open(), Orthanc::OrthancException);
+    OrthancDatabases::DatabaseManager manager3(db3.CreateDatabaseFactory());
+    ASSERT_THROW(manager3.Open(), Orthanc::OrthancException);
   }
 
   OrthancDatabases::MySQLIndex db4(NULL, lock);
-  db4.Open();
+  OrthancDatabases::DatabaseManager manager4(db4.CreateDatabaseFactory());
+  manager4.Open();
 }
 
 
--- a/PostgreSQL/Plugins/PostgreSQLIndex.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/PostgreSQL/Plugins/PostgreSQLIndex.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -259,18 +259,19 @@
 
   PostgreSQLIndex::PostgreSQLIndex(OrthancPluginContext* context,
                                    const PostgreSQLParameters& parameters) :
-    IndexBackend(context, new Factory(*this)),
+    IndexBackend(context),
     parameters_(parameters),
     clearAll_(false)
   {
   }
 
   
-  int64_t PostgreSQLIndex::CreateResource(const char* publicId,
+  int64_t PostgreSQLIndex::CreateResource(DatabaseManager& manager,
+                                          const char* publicId,
                                           OrthancPluginResourceType type)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO Resources VALUES(${}, ${type}, ${id}, NULL) RETURNING internalId");
      
     statement.SetParameterType("id", ValueType_Utf8String);
@@ -286,14 +287,14 @@
   }
 
 
-  uint64_t PostgreSQLIndex::GetTotalCompressedSize()
+  uint64_t PostgreSQLIndex::GetTotalCompressedSize(DatabaseManager& manager)
   {
     // Fast version if extension "./FastTotalSize.sql" is installed
     uint64_t result;
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "SELECT value FROM GlobalIntegers WHERE key = 0");
 
       statement.SetReadOnly(true);
@@ -302,19 +303,19 @@
       result = static_cast<uint64_t>(ReadInteger64(statement, 0));
     }
     
-    assert(result == IndexBackend::GetTotalCompressedSize());
+    assert(result == IndexBackend::GetTotalCompressedSize(manager));
     return result;
   }
 
   
-  uint64_t PostgreSQLIndex::GetTotalUncompressedSize()
+  uint64_t PostgreSQLIndex::GetTotalUncompressedSize(DatabaseManager& manager)
   {
     // Fast version if extension "./FastTotalSize.sql" is installed
     uint64_t result;
 
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "SELECT value FROM GlobalIntegers WHERE key = 1");
 
       statement.SetReadOnly(true);
@@ -323,20 +324,21 @@
       result = static_cast<uint64_t>(ReadInteger64(statement, 0));
     }
     
-    assert(result == IndexBackend::GetTotalUncompressedSize());
+    assert(result == IndexBackend::GetTotalUncompressedSize(manager));
     return result;
   }
 
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
   void PostgreSQLIndex::CreateInstance(OrthancPluginCreateInstanceResult& result,
+                                       DatabaseManager& manager,
                                        const char* hashPatient,
                                        const char* hashStudy,
                                        const char* hashSeries,
                                        const char* hashInstance)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "SELECT * FROM CreateInstance(${patient}, ${study}, ${series}, ${instance})");
 
     statement.SetParameterType("patient", ValueType_Utf8String);
@@ -379,7 +381,8 @@
 #endif
 
 
-  uint64_t PostgreSQLIndex::GetResourcesCount(OrthancPluginResourceType resourceType)
+  uint64_t PostgreSQLIndex::GetResourcesCount(DatabaseManager& manager,
+                                              OrthancPluginResourceType resourceType)
   {
     // Optimized version thanks to the "FastCountResources.sql" extension
 
@@ -392,7 +395,7 @@
     
     {
       DatabaseManager::CachedStatement statement(
-        STATEMENT_FROM_HERE, GetManager(),
+        STATEMENT_FROM_HERE, manager,
         "SELECT value FROM GlobalIntegers WHERE key = ${key}");
 
       statement.SetParameterType("key", ValueType_Integer64);
@@ -408,15 +411,15 @@
       result = static_cast<uint64_t>(ReadInteger64(statement, 0));
     }
       
-    assert(result == IndexBackend::GetResourcesCount(resourceType));
+    assert(result == IndexBackend::GetResourcesCount(manager, resourceType));
     return result;
   }
 
 
-  int64_t PostgreSQLIndex::GetLastChangeIndex()
+  int64_t PostgreSQLIndex::GetLastChangeIndex(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "SELECT value FROM GlobalIntegers WHERE key = 6");
 
     statement.SetReadOnly(true);
@@ -426,7 +429,8 @@
   }
 
 
-  void PostgreSQLIndex::TagMostRecentPatient(int64_t patient)
+  void PostgreSQLIndex::TagMostRecentPatient(DatabaseManager& manager,
+                                             int64_t patient)
   {
     // This behavior is implemented in "CreateInstance()", and no
     // backward compatibility is necessary
--- a/PostgreSQL/Plugins/PostgreSQLIndex.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/PostgreSQL/Plugins/PostgreSQLIndex.h	Thu Apr 01 19:18:19 2021 +0200
@@ -76,13 +76,14 @@
       return new Factory(*this);
     }
 
-    virtual int64_t CreateResource(const char* publicId,
+    virtual int64_t CreateResource(DatabaseManager& manager,
+                                   const char* publicId,
                                    OrthancPluginResourceType type)
       ORTHANC_OVERRIDE;
 
-    virtual uint64_t GetTotalCompressedSize() ORTHANC_OVERRIDE;
+    virtual uint64_t GetTotalCompressedSize(DatabaseManager& manager) ORTHANC_OVERRIDE;
 
-    virtual uint64_t GetTotalUncompressedSize() ORTHANC_OVERRIDE;
+    virtual uint64_t GetTotalUncompressedSize(DatabaseManager& manager) ORTHANC_OVERRIDE;
     
     virtual bool HasCreateInstance() const  ORTHANC_OVERRIDE
     {
@@ -91,6 +92,7 @@
 
 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1
     virtual void CreateInstance(OrthancPluginCreateInstanceResult& result,
+                                DatabaseManager& manager,
                                 const char* hashPatient,
                                 const char* hashStudy,
                                 const char* hashSeries,
@@ -98,10 +100,12 @@
       ORTHANC_OVERRIDE;
 #endif
 
-    virtual uint64_t GetResourcesCount(OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE;
+    virtual uint64_t GetResourcesCount(DatabaseManager& manager,
+                                       OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE;
 
-    virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE;
+    virtual int64_t GetLastChangeIndex(DatabaseManager& manager) ORTHANC_OVERRIDE;
 
-    virtual void TagMostRecentPatient(int64_t patient) ORTHANC_OVERRIDE;
+    virtual void TagMostRecentPatient(DatabaseManager& manager,
+                                      int64_t patient) ORTHANC_OVERRIDE;
   };
 }
--- a/PostgreSQL/UnitTests/PostgreSQLTests.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/PostgreSQL/UnitTests/PostgreSQLTests.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -455,32 +455,34 @@
 {
   OrthancDatabases::PostgreSQLIndex db(NULL, globalParameters_);
   db.SetClearAll(true);
-  db.Open();
+
+  OrthancDatabases::DatabaseManager manager(db.CreateDatabaseFactory());
+  manager.Open();
 
   std::string s;
-  ASSERT_TRUE(db.LookupGlobalProperty(s, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseInternal1));
+  ASSERT_TRUE(db.LookupGlobalProperty(s, manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseInternal1));
   ASSERT_EQ("2", s);
 
   OrthancPluginCreateInstanceResult r1, r2;
   
   memset(&r1, 0, sizeof(r1));
-  db.CreateInstance(r1, "a", "b", "c", "d");
+  db.CreateInstance(r1, manager, "a", "b", "c", "d");
   ASSERT_TRUE(r1.isNewInstance);
   ASSERT_TRUE(r1.isNewSeries);
   ASSERT_TRUE(r1.isNewStudy);
   ASSERT_TRUE(r1.isNewPatient);
 
   memset(&r2, 0, sizeof(r2));
-  db.CreateInstance(r2, "a", "b", "c", "d");
+  db.CreateInstance(r2, manager, "a", "b", "c", "d");
   ASSERT_FALSE(r2.isNewInstance);
   ASSERT_EQ(r1.instanceId, r2.instanceId);
 
   // Breaking the hierarchy
   memset(&r2, 0, sizeof(r2));
-  ASSERT_THROW(db.CreateInstance(r2, "a", "e", "c", "f"), Orthanc::OrthancException);
+  ASSERT_THROW(db.CreateInstance(r2, manager, "a", "e", "c", "f"), Orthanc::OrthancException);
 
   memset(&r2, 0, sizeof(r2));
-  db.CreateInstance(r2, "a", "b", "c", "e");
+  db.CreateInstance(r2, manager, "a", "b", "c", "e");
   ASSERT_TRUE(r2.isNewInstance);
   ASSERT_FALSE(r2.isNewSeries);
   ASSERT_FALSE(r2.isNewStudy);
@@ -491,7 +493,7 @@
   ASSERT_NE(r1.instanceId, r2.instanceId);
 
   memset(&r2, 0, sizeof(r2));
-  db.CreateInstance(r2, "a", "b", "f", "g");
+  db.CreateInstance(r2, manager, "a", "b", "f", "g");
   ASSERT_TRUE(r2.isNewInstance);
   ASSERT_TRUE(r2.isNewSeries);
   ASSERT_FALSE(r2.isNewStudy);
@@ -502,7 +504,7 @@
   ASSERT_NE(r1.instanceId, r2.instanceId);
 
   memset(&r2, 0, sizeof(r2));
-  db.CreateInstance(r2, "a", "h", "i", "j");
+  db.CreateInstance(r2, manager, "a", "h", "i", "j");
   ASSERT_TRUE(r2.isNewInstance);
   ASSERT_TRUE(r2.isNewSeries);
   ASSERT_TRUE(r2.isNewStudy);
@@ -513,7 +515,7 @@
   ASSERT_NE(r1.instanceId, r2.instanceId);
 
   memset(&r2, 0, sizeof(r2));
-  db.CreateInstance(r2, "k", "l", "m", "n");
+  db.CreateInstance(r2, manager, "k", "l", "m", "n");
   ASSERT_TRUE(r2.isNewInstance);
   ASSERT_TRUE(r2.isNewSeries);
   ASSERT_TRUE(r2.isNewStudy);
--- a/PostgreSQL/UnitTests/UnitTestsMain.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/PostgreSQL/UnitTests/UnitTestsMain.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -91,18 +91,23 @@
 
   OrthancDatabases::PostgreSQLIndex db1(NULL, noLock);
   db1.SetClearAll(true);
-  db1.Open();
+
+  OrthancDatabases::DatabaseManager manager1(db1.CreateDatabaseFactory());
+  manager1.Open();
 
   {
     OrthancDatabases::PostgreSQLIndex db2(NULL, lock);
-    db2.Open();
+    OrthancDatabases::DatabaseManager manager2(db2.CreateDatabaseFactory());
+    manager2.Open();
 
     OrthancDatabases::PostgreSQLIndex db3(NULL, lock);
-    ASSERT_THROW(db3.Open(), Orthanc::OrthancException);
+    OrthancDatabases::DatabaseManager manager3(db3.CreateDatabaseFactory());
+    ASSERT_THROW(manager3.Open(), Orthanc::OrthancException);
   }
 
   OrthancDatabases::PostgreSQLIndex db4(NULL, lock);
-  db4.Open();
+  OrthancDatabases::DatabaseManager manager4(db4.CreateDatabaseFactory());
+  manager4.Open();
 }
 
 
--- a/SQLite/Plugins/SQLiteIndex.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/SQLite/Plugins/SQLiteIndex.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -134,7 +134,7 @@
 
   SQLiteIndex::SQLiteIndex(OrthancPluginContext* context,
                            const std::string& path) :
-    IndexBackend(context, new Factory(*this)),
+    IndexBackend(context),
     path_(path),
     fast_(true)
   {
@@ -146,17 +146,18 @@
 
 
   SQLiteIndex::SQLiteIndex(OrthancPluginContext* context) :
-    IndexBackend(context, new Factory(*this)),
+    IndexBackend(context),
     fast_(true)
   {
   }
 
 
-  int64_t SQLiteIndex::CreateResource(const char* publicId,
+  int64_t SQLiteIndex::CreateResource(DatabaseManager& manager,
+                                      const char* publicId,
                                       OrthancPluginResourceType type)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "INSERT INTO Resources VALUES(NULL, ${type}, ${id}, NULL)");
     
     statement.SetParameterType("id", ValueType_Utf8String);
@@ -172,10 +173,10 @@
   }
 
 
-  int64_t SQLiteIndex::GetLastChangeIndex()
+  int64_t SQLiteIndex::GetLastChangeIndex(DatabaseManager& manager)
   {
     DatabaseManager::CachedStatement statement(
-      STATEMENT_FROM_HERE, GetManager(),
+      STATEMENT_FROM_HERE, manager,
       "SELECT seq FROM sqlite_sequence WHERE name='Changes'");
 
     statement.SetReadOnly(true);
--- a/SQLite/Plugins/SQLiteIndex.h	Thu Apr 01 16:09:59 2021 +0200
+++ b/SQLite/Plugins/SQLiteIndex.h	Thu Apr 01 19:18:19 2021 +0200
@@ -79,10 +79,11 @@
       return new Factory(*this);
     }
     
-    virtual int64_t CreateResource(const char* publicId,
+    virtual int64_t CreateResource(DatabaseManager& manager,
+                                   const char* publicId,
                                    OrthancPluginResourceType type);
 
     // New primitive since Orthanc 1.5.2
-    virtual int64_t GetLastChangeIndex();
+    virtual int64_t GetLastChangeIndex(DatabaseManager& manager);
   };
 }
--- a/SQLite/UnitTests/UnitTestsMain.cpp	Thu Apr 01 16:09:59 2021 +0200
+++ b/SQLite/UnitTests/UnitTestsMain.cpp	Thu Apr 01 19:18:19 2021 +0200
@@ -37,25 +37,32 @@
   {
     // No locking if using memory backend
     OrthancDatabases::SQLiteIndex db1(NULL);
-    OrthancDatabases::SQLiteIndex db2(NULL);
+    OrthancDatabases::DatabaseManager manager1(db1.CreateDatabaseFactory());
 
-    db1.Open();
-    db2.Open();
+    OrthancDatabases::SQLiteIndex db2(NULL);
+    OrthancDatabases::DatabaseManager manager2(db2.CreateDatabaseFactory());
+    
+    manager1.Open();
+    manager2.Open();
   }
 
   Orthanc::SystemToolbox::RemoveFile("index.db");
 
   {
     OrthancDatabases::SQLiteIndex db1(NULL, "index.db");
-    OrthancDatabases::SQLiteIndex db2(NULL, "index.db");
+    OrthancDatabases::DatabaseManager manager1(db1.CreateDatabaseFactory());
 
-    db1.Open();
-    ASSERT_THROW(db2.Open(), Orthanc::OrthancException);
+    OrthancDatabases::SQLiteIndex db2(NULL, "index.db");
+    OrthancDatabases::DatabaseManager manager2(db2.CreateDatabaseFactory());
+
+    manager1.Open();
+    ASSERT_THROW(manager2.Open(), Orthanc::OrthancException);
   }
 
   {
     OrthancDatabases::SQLiteIndex db3(NULL, "index.db");
-    db3.Open();
+    OrthancDatabases::DatabaseManager manager3(db3.CreateDatabaseFactory());
+    manager3.Open();
   }
 }