diff --git a/CMakeLists.txt b/CMakeLists.txt
index 39d15c9c54cf933e04bd2827d8175ff91adee090..64fad3282a1796dda04745378feed7bb5c891754 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@
 
 cmake_minimum_required(VERSION 3.13)
 
-set(libcaosdb_VERSION 0.0.9)
+set(libcaosdb_VERSION 0.0.10)
 set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0)
 set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5)
 set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0)
diff --git a/conanfile.py b/conanfile.py
index e2133cea76ce826d168364259d6a519ba28a75d3..0e31f8dfeaae2cd681690324611031bd3017ec67 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools
 
 class CaosdbConan(ConanFile):
     name = "caosdb"
-    version = "0.0.9"
+    version = "0.0.10"
     license = "AGPL-3.0-or-later"
     author = "Timm C. Fitschen <t.fitschen@indiscale.com>"
     url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git"
diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h
index 48762db4396e8996442ef5be287e3965836ecd4e..e2a2ebc2456de8294ce360434331ed4f710b1e75 100644
--- a/include/caosdb/transaction.h
+++ b/include/caosdb/transaction.h
@@ -208,7 +208,7 @@ private:
 class MultiResultSet : public ResultSet {
 public:
   ~MultiResultSet() = default;
-  explicit MultiResultSet(MultiTransactionResponse *response);
+  explicit MultiResultSet(std::vector<std::unique_ptr<Entity>> result_set);
   [[nodiscard]] inline auto Size() const noexcept -> int override {
     return this->entities.size();
   }
@@ -357,6 +357,17 @@ public:
     return *result_set;
   }
 
+  /**
+   * Return the result of a count query
+   *
+   * Only meaningful if there was exactly one COUNT query executed in
+   * this transaction. In all other cases, the return value will be
+   * -1.
+   */
+  [[nodiscard]] inline auto GetCountResult() const -> long {
+    return query_count;
+  }
+
   /**
    * Return the number of sub-requests in this transaction.
    *
@@ -367,6 +378,23 @@ public:
     return this->request->requests_size();
   }
 
+  /**
+   * Get a JSON representation of the response.
+   *
+   * For debugging.
+   */
+  inline auto ResponseToString() const -> const std::string {
+    google::protobuf::util::JsonOptions options;
+    std::string out;
+    google::protobuf::util::MessageToJsonString(*this->response, &out, options);
+    return out;
+  }
+
+  /**
+   * Get a JSON representation of the request.
+   *
+   * For debugging.
+   */
   inline auto RequestToString() const -> const std::string {
     google::protobuf::util::JsonOptions options;
     std::string out;
@@ -383,6 +411,7 @@ private:
   MultiTransactionRequest *request;
   mutable MultiTransactionResponse *response;
   std::string error_message;
+  mutable long query_count;
 };
 
 template <class InputIterator>
diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp
index f946175f3b33397e9398188500cf0ef51cc16d26..61f52786f48594e3182c6101a1be305672e17def 100644
--- a/src/caosdb/transaction.cpp
+++ b/src/caosdb/transaction.cpp
@@ -96,6 +96,8 @@ using caosdb::entity::v1alpha1::MultiTransactionRequest;
 using caosdb::entity::v1alpha1::MultiTransactionResponse;
 using WrappedResponseCase =
   caosdb::entity::v1alpha1::TransactionResponse::WrappedResponseCase;
+using QueryResponseCase =
+  caosdb::entity::v1alpha1::RetrieveResponse::QueryResponseCase;
 using caosdb::utility::get_arena;
 using grpc::ClientAsyncResponseReader;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
@@ -131,28 +133,8 @@ auto ResultSet::end() const -> ResultSet::iterator {
   return ResultSet::iterator(this, Size());
 }
 
-MultiResultSet::MultiResultSet(MultiTransactionResponse *response) {
-  auto *responses = response->mutable_responses();
-  for (auto sub_response : *responses) {
-    switch (sub_response.wrapped_response_case()) {
-    case WrappedResponseCase::kRetrieveResponse:
-      this->entities.push_back(std::make_unique<Entity>(
-        sub_response.mutable_retrieve_response()->release_entity()));
-      break;
-    case WrappedResponseCase::kInsertResponse:
-      this->entities.push_back(
-        std::make_unique<Entity>(sub_response.release_insert_response()));
-      break;
-    case WrappedResponseCase::kDeleteResponse:
-      this->entities.push_back(
-        std::make_unique<Entity>(sub_response.release_insert_response()));
-      break;
-    default:
-      // TODO(tf) Updates
-      break;
-    }
-  }
-}
+MultiResultSet::MultiResultSet(std::vector<std::unique_ptr<Entity>> result_set)
+  : entities(std::move(result_set)) {}
 
 [[nodiscard]] auto UniqueResult::GetEntity() const -> const Entity & {
   const Entity *result = this->entity.get();
@@ -166,6 +148,7 @@ Transaction::Transaction(
     response(google::protobuf::Arena::CreateMessage<MultiTransactionResponse>(
       get_arena())) {
   this->service_stub = std::move(service_stub);
+  this->query_count = -1;
 }
 
 auto Transaction::RetrieveById(const std::string &id) noexcept -> StatusCode {
@@ -197,7 +180,7 @@ auto Transaction::DeleteById(const std::string &id) noexcept -> StatusCode {
   auto *sub_request = this->request->add_requests();
   sub_request->mutable_delete_request()->set_id(id);
 
-  this->status = TransactionStatus::READY();
+  this->status = TransactionStatus::GO_ON();
   return this->status.GetCode();
 }
 
@@ -300,12 +283,29 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus {
     auto *responses = this->response->mutable_responses(0);
     switch (responses->wrapped_response_case()) {
     case WrappedResponseCase::kRetrieveResponse: {
-      auto *entity = responses->mutable_retrieve_response()->release_entity();
-      if (!entity->errors().empty()) {
-        this->status = TransactionStatus::TRANSACTION_ERROR(
-          "The request returned with errors.");
+      auto *retrieve_response = responses->mutable_retrieve_response();
+      switch (retrieve_response->query_response_case()) {
+      case QueryResponseCase::kEntity: {
+        auto *entity = retrieve_response->release_entity();
+        if (!entity->errors().empty()) {
+          this->status = TransactionStatus::TRANSACTION_ERROR(
+            "The request returned with errors.");
+        }
+        this->result_set = std::make_unique<UniqueResult>(entity);
+      } break;
+      case QueryResponseCase::kSelectResult: {
+        // TODO(tf) Select queries
+      } break;
+      case QueryResponseCase::kCountResult: {
+        this->query_count = retrieve_response->count_result();
+        std::vector<std::unique_ptr<Entity>> entities;
+        this->result_set =
+          std::make_unique<MultiResultSet>(std::move(entities));
+      } break;
+      default:
+        // TODO(tf) Error
+        break;
       }
-      this->result_set = std::make_unique<UniqueResult>(entity);
     } break;
     case WrappedResponseCase::kUpdateResponse: {
       auto *updatedIdResponse = responses->mutable_update_response();
@@ -336,7 +336,28 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus {
       break;
     }
   } else {
-    this->result_set = std::make_unique<MultiResultSet>(this->response);
+    auto *responses = this->response->mutable_responses();
+    std::vector<std::unique_ptr<Entity>> entities;
+    for (auto sub_response : *responses) {
+      switch (sub_response.wrapped_response_case()) {
+      case WrappedResponseCase::kRetrieveResponse:
+        entities.push_back(std::make_unique<Entity>(
+          sub_response.mutable_retrieve_response()->release_entity()));
+        break;
+      case WrappedResponseCase::kInsertResponse:
+        entities.push_back(
+          std::make_unique<Entity>(sub_response.release_insert_response()));
+        break;
+      case WrappedResponseCase::kDeleteResponse:
+        entities.push_back(
+          std::make_unique<Entity>(sub_response.release_insert_response()));
+        break;
+      default:
+        // TODO(tf) Updates
+        break;
+      }
+    }
+    this->result_set = std::make_unique<MultiResultSet>(std::move(entities));
   }
 
   return this->status;
diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp
index 557ded7b87fe9947391bb47f6c37b49ee1824cfb..b062cb8a6372ac5db749cc9b6acd998f8829a14a 100644
--- a/test/test_transaction.cpp
+++ b/test/test_transaction.cpp
@@ -31,6 +31,7 @@
 #include "gtest/gtest_pred_impl.h"     // for Test, TestInfo, TEST
 #include <memory>                      // for allocator, unique_ptr
 #include <string>                      // for string, basic_string
+#include <utility>                     // for move
 #include <vector>                      // for vector
 
 namespace caosdb::transaction {
@@ -39,6 +40,7 @@ using caosdb::connection::Connection;
 using caosdb::exceptions::ConnectionError;
 using caosdb::transaction::UniqueResult;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
+using caosdb::entity::v1alpha1::RetrieveResponse;
 
 TEST(test_transaction, create_transaction) {
   const auto *host = "localhost";
@@ -92,21 +94,18 @@ TEST(test_transaction, test_retrieve_by_ids) {
 }
 
 TEST(test_transaction, test_multi_result_set_empty) {
-  MultiTransactionResponse response;
-
-  MultiResultSet rs(&response);
+  std::vector<std::unique_ptr<Entity>> empty;
+  MultiResultSet rs(std::move(empty));
   EXPECT_EQ(rs.Size(), 0);
 }
 
 TEST(test_transaction, test_multi_result_iterator) {
-  MultiTransactionResponse response;
-
-  response.add_responses()
-    ->mutable_retrieve_response()
-    ->mutable_entity()
-    ->set_id("100");
+  std::vector<std::unique_ptr<Entity>> one_elem;
+  RetrieveResponse response;
+  response.mutable_entity()->set_id("100");
+  one_elem.push_back(std::make_unique<Entity>(response.release_entity()));
 
-  MultiResultSet rs(&response);
+  MultiResultSet rs(std::move(one_elem));
   EXPECT_EQ(rs.Size(), 1);
 
   for (const Entity &entity : rs) {
@@ -126,18 +125,19 @@ TEST(test_transaction, test_unique_result_iterator) {
 }
 
 TEST(test_transaction, test_multi_result_set_one) {
-  MultiTransactionResponse response;
-  response.add_responses()
-    ->mutable_retrieve_response()
-    ->mutable_entity()
-    ->set_id("100");
+  std::vector<std::unique_ptr<Entity>> one_elem;
+  RetrieveResponse response;
+  response.mutable_entity()->set_id("100");
+  one_elem.push_back(std::make_unique<Entity>(response.release_entity()));
 
-  MultiResultSet rs(&response);
+  MultiResultSet rs(std::move(one_elem));
   EXPECT_EQ(rs.Size(), 1);
   EXPECT_EQ(rs.At(0).GetId(), "100");
 }
 
 TEST(test_transaction, test_multi_result_set_three) {
+  std::vector<std::unique_ptr<Entity>> three_elem;
+
   MultiTransactionResponse response;
   response.add_responses()
     ->mutable_retrieve_response()
@@ -152,7 +152,14 @@ TEST(test_transaction, test_multi_result_set_three) {
     ->mutable_entity()
     ->set_id("102");
 
-  MultiResultSet rs(&response);
+  auto *responses = response.mutable_responses();
+  std::vector<std::unique_ptr<Entity>> entities;
+  for (auto sub_response : *responses) {
+    three_elem.push_back(std::make_unique<Entity>(
+      sub_response.mutable_retrieve_response()->release_entity()));
+  }
+
+  MultiResultSet rs(std::move(three_elem));
   EXPECT_EQ(rs.Size(), 3);
   EXPECT_TRUE(rs.At(1).HasErrors());
 }
@@ -170,4 +177,16 @@ TEST(test_transaction, test_update_entity) {
   EXPECT_EQ(error, StatusCode::ORIGINAL_ENTITY_MISSING_ID);
 }
 
+TEST(test_transaction, test_multi_deletion) {
+  const auto *host = "localhost";
+  auto configuration = InsecureConnectionConfiguration(host, 8000);
+  Connection connection(configuration);
+  auto transaction = connection.CreateTransaction();
+  EXPECT_EQ(transaction->GetStatus().GetCode(), StatusCode::INITIAL);
+  for (int i = 0; i < 3; i++) {
+    auto status = transaction->DeleteById("asdf");
+    EXPECT_EQ(status, StatusCode::GO_ON);
+  }
+}
+
 } // namespace caosdb::transaction