diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h
index 69be0c63b8a12c27fe2c056485d7840d5a5637e1..1c22f9cc2bd59d192100236e78ed92fe83786582 100644
--- a/include/caosdb/entity.h
+++ b/include/caosdb/entity.h
@@ -21,43 +21,126 @@
 
 /**
  * @brief Anything entity-related.
+ * @file caosdb/entity.h
+ * @author Timm Fitchen
+ * @date 2021-07-07
  */
 #ifndef CAOSDB_ENTITY_H
 #define CAOSDB_ENTITY_H
 
-#include <memory>                           // for shared_ptr
-#include <string>                           // for string
+#include <memory> // for shared_ptr
+#include <string> // for string
+#include <google/protobuf/repeated_field.h>
 #include "caosdb/entity/v1alpha1/main.pb.h" // for Entity
 
 namespace caosdb::entity {
-using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 
 /**
- * Entity ID.
+ * Parent of an Entity.
  */
-class EntityID {
+class Parent {
+public:
+  explicit inline Parent(caosdb::entity::v1alpha1::Parent *wrapped)
+    : wrapped(wrapped){};
+  [[nodiscard]] auto GetId() const -> const std::string &;
+  [[nodiscard]] auto GetName() const -> const std::string &;
+  [[nodiscard]] auto GetDescription() const -> const std::string &;
+
 private:
-  std::shared_ptr<std::string> id;
+  caosdb::entity::v1alpha1::Parent *wrapped;
+};
 
+/**
+ * Container for parents of entities.
+ */
+class Parents {
 public:
-  explicit EntityID(const std::string &id);
-  explicit EntityID(const std::shared_ptr<std::string> &id);
+  inline Parents(){};
+  explicit inline Parents(
+    ::google::protobuf::RepeatedField<caosdb::entity::v1alpha1::Parent>
+      *wrapped)
+    : wrapped(wrapped){};
+  [[nodiscard]] auto At(int index) const -> const Parent &;
+
+private:
+  ::google::protobuf::RepeatedField<caosdb::entity::v1alpha1::Parent> *wrapped;
+  friend class Entity;
 };
 
 /**
- * @brief Wrapper for the Protobuf entity.
+ * Property of an Entity.
+ *
+ * This is a property which belongs to another entity. Don't confuse it with an
+ * Entity with the "Property" role.
+ *
+ * @brief Property of an Entity.
  */
-class Entity {
+class Property {
+public:
+  explicit inline Property(caosdb::entity::v1alpha1::Property *wrapped)
+    : wrapped(wrapped){};
+  [[nodiscard]] auto GetId() const -> const std::string &;
+  [[nodiscard]] auto GetName() const -> const std::string &;
+  [[nodiscard]] auto GetDescription() const -> const std::string &;
+  [[nodiscard]] auto GetImportance() const -> const std::string &;
+  [[nodiscard]] auto GetValue() const -> const std::string &;
+  [[nodiscard]] auto GetUnit() const -> const std::string &;
+  [[nodiscard]] auto GetDatatype() const -> const std::string &;
+
+private:
+  caosdb::entity::v1alpha1::Property *wrapped;
+};
+
+/**
+ * Container for Properties of Entities
+ */
+class Properties {
+public:
+  inline Properties(){};
+  explicit inline Properties(
+    ::google::protobuf::RepeatedField<caosdb::entity::v1alpha1::Property>
+      *wrapped)
+    : wrapped(wrapped){};
+  [[nodiscard]] auto At(int index) const -> const Property &;
+
 private:
-  EntityID id;
-  std::shared_ptr<ProtoEntity> delegate;
+  ::google::protobuf::RepeatedField<caosdb::entity::v1alpha1::Property>
+    *wrapped;
+  friend class Entity;
+};
 
+/**
+ * @brief Wrapper for the Protobuf entity.
+ */
+class Entity {
 public:
-  explicit Entity(ProtoEntity *delegate);
-  [[nodiscard]] auto GetId() const -> EntityID;
-  auto SetId(EntityID id) -> void;
-  [[nodiscard]] auto GetName() const -> std::string;
-  [[nodiscard]] auto GetDescription() const -> std::string;
+  explicit inline Entity(caosdb::entity::v1alpha1::Entity *wrapped)
+    : wrapped(wrapped),
+      properties(
+        (::google::protobuf::RepeatedField<caosdb::entity::v1alpha1::Property>
+           *)wrapped->mutable_properties()),
+      parents(
+        (::google::protobuf::RepeatedField<caosdb::entity::v1alpha1::Parent> *)
+          wrapped->mutable_parents()){};
+  [[nodiscard]] auto GetId() const -> const std::string &;
+  [[nodiscard]] auto GetVersion() const -> const std::string &;
+
+  [[nodiscard]] auto GetRole() const -> const std::string &;
+  [[nodiscard]] auto GetName() const -> const std::string &;
+  [[nodiscard]] inline auto GetDescription() const -> const std::string & {
+    return wrapped->description();
+  }
+
+  [[nodiscard]] auto GetDatatype() const -> const std::string &;
+  [[nodiscard]] auto GetUnit() const -> const std::string &;
+
+  [[nodiscard]] auto GetParents() const -> const Parents &;
+  [[nodiscard]] auto GetProperties() const -> const Properties &;
+
+private:
+  std::unique_ptr<caosdb::entity::v1alpha1::Entity> wrapped;
+  Properties properties;
+  Parents parents;
 };
 
 } // namespace caosdb::entity
diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h
index 856f8cab0ed8ed8828624ec347c560b4762c7904..9333957bd1dcf25957b9b2df75a826113e3001ac 100644
--- a/include/caosdb/transaction.h
+++ b/include/caosdb/transaction.h
@@ -33,23 +33,20 @@
 
 namespace caosdb::transaction {
 using caosdb::entity::Entity;
-using caosdb::entity::EntityID;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 using caosdb::entity::v1alpha1::EntityTransactionService;
 using caosdb::entity::v1alpha1::RetrieveRequest;
 
-class ResultSet {
-  // public:
-  //[[nodiscard]] auto GetEntityById(EntityID id) const -> Entity;
-};
+class ResultSet {};
 
 class UniqueResult : public ResultSet {
 private:
-  Entity entity;
+  std::unique_ptr<Entity> entity;
 
 public:
-  UniqueResult(Entity entity);
-  [[nodiscard]] auto GetEntity() const -> Entity;
+  explicit inline UniqueResult(ProtoEntity *protoEntity)
+    : entity(new Entity(protoEntity)){};
+  [[nodiscard]] auto GetEntity() const -> const Entity &;
 };
 
 enum TransactionState { INIT = 10, EXECUTING = 20, SUCCESS = 30, ERROR = 40 };
@@ -66,7 +63,7 @@ private:
 
 public:
   Transaction(std::shared_ptr<EntityTransactionService::Stub> service_stub);
-  auto Retrieve(const EntityID &id) -> void;
+  auto RetrieveById(const std::string &id) -> void;
   auto Execute() -> void;
   [[nodiscard]] auto GetResultSet() const -> std::shared_ptr<ResultSet>;
   auto WaitForIt() const -> void;
diff --git a/proto b/proto
index dd9abe3499367c4eded4774ade1acbc90ef048b3..12f072263c05208464b80c0124bde0396b100d86 160000
--- a/proto
+++ b/proto
@@ -1 +1 @@
-Subproject commit dd9abe3499367c4eded4774ade1acbc90ef048b3
+Subproject commit 12f072263c05208464b80c0124bde0396b100d86
diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp
index 71f480857421b8c013005c9b6247cecd088c930f..b39623a38e9a3883f5b16aa858c0f787cfa46704 100644
--- a/src/caosdb/entity.cpp
+++ b/src/caosdb/entity.cpp
@@ -22,24 +22,4 @@
 #include "caosdb/entity.h"
 #include <utility>
 
-namespace caosdb::entity {
-
-EntityID::EntityID(const std::string &id) {
-  this->id = std::make_shared<std::string>(id);
-}
-
-EntityID::EntityID(const std::shared_ptr<std::string> &id) {
-  this->id = std::make_shared<std::string>(*id);
-}
-
-Entity::Entity(ProtoEntity *delegate)
-  : id(EntityID(delegate->eid())), delegate(delegate) {}
-
-[[nodiscard]] auto Entity::GetDescription() const -> std::string {
-  return this->delegate->description();
-}
-[[nodiscard]] auto Entity::GetId() const -> EntityID { return this->id; }
-
-auto Entity::SetId(EntityID id) -> void { this->id = std::move(id); }
-
-} // namespace caosdb::entity
+namespace caosdb::entity {} // namespace caosdb::entity
diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp
index 8355f7672c843415f8f6e834e988783fe064078d..60713c5a758b08ded0797e5f6ddb4b7e001b4191 100644
--- a/src/caosdb/transaction.cpp
+++ b/src/caosdb/transaction.cpp
@@ -39,10 +39,9 @@ using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 using caosdb::exceptions::AuthenticationError;
 using caosdb::exceptions::ConnectionError;
 
-UniqueResult::UniqueResult(Entity entity) : entity(std::move(entity)) {}
-
-[[nodiscard]] auto UniqueResult::GetEntity() const -> Entity {
-  return this->entity;
+[[nodiscard]] auto UniqueResult::GetEntity() const -> const Entity & {
+  const Entity *result = this->entity.get();
+  return *result;
 }
 
 Transaction::Transaction(
@@ -50,9 +49,9 @@ Transaction::Transaction(
   this->service_stub = std::move(service_stub);
 }
 
-auto Transaction::Retrieve(const EntityID & /*id*/) -> void {
-  // TODO(tf)
+auto Transaction::RetrieveById(const std::string &id) -> void {
   RetrieveRequest request;
+  request.mutable_by_id()->set_id(id);
 
   this->request = request;
 }
@@ -78,7 +77,7 @@ auto Transaction::Execute() -> void {
     }
   }
 
-  auto entity = Entity(response.release_entity());
+  auto *entity = response.release_entity();
   auto result_set = std::make_shared<UniqueResult>(entity);
   this->result_set = result_set;
 }
diff --git a/src/caosdbcli.cpp b/src/caosdbcli.cpp
index d4a01a59a384b1374d5d1a09011115ac63841217..26d86d620e092b2aa593b91be4f514053514fc9a 100644
--- a/src/caosdbcli.cpp
+++ b/src/caosdbcli.cpp
@@ -69,7 +69,7 @@ auto main() -> int {
 
   // retrieve an entity
   auto transaction(connection.CreateTransaction());
-  transaction->Retrieve(caosdb::entity::EntityID("someid"));
+  transaction->RetrieveById("20");
   transaction->Execute();
   auto result_set(std::static_pointer_cast<caosdb::transaction::UniqueResult>(
     transaction->GetResultSet()));