diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d45312b555df2390d14226a81f05d6e75f72e75..a60110a61278de6979d25c17937617ae79a0cf7e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,40 @@
-# Changelog
+# Changelog #
+
 All notable changes to this project will be documented in this file.
 
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [Unreleased] ##
+
+### Added ###
+
+### Changed ###
+
+### Deprecated ###
+
+### Removed ###
+
+### Fixed ###
+
+### Security ###
+
+## [0.3.0] - 2020-04-24##
 
-## [0.2.4]
+### Added ###
+
+* `apiutils.apply_to_ids` -- a helper which applies a function to all ids which
+  are used by an entity (own entity, parents, properties, references etc.).
+
+### Changed ###
+
+### Deprecated ###
+
+### Fixed ###
+
+* import bugs in apiutils
+
+## [0.2.4] -- 2020-04-23
 
 ### Added
 
@@ -49,7 +78,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Many other fixes
 
 
-## [0.1.0] - 2018-10-09
+## [0.1.0] - 2018-10-09 ##
+
 Tag `v0.1` - Commit 6fc0dcaa
 
 
diff --git a/RELEASE_GUIDELINES.md b/RELEASE_GUIDELINES.md
index 48eb270e6f5dc29b4d9ee85d275d6fe7eba1ffd6..02be5c1ad19f6a3a405fb08d62e23dab350ad445 100644
--- a/RELEASE_GUIDELINES.md
+++ b/RELEASE_GUIDELINES.md
@@ -1,4 +1,4 @@
-# Release Guidelines for the CaosDB MySQL Backend
+# Release Guidelines for the CaosDB Python Client Library
 
 This document specifies release guidelines in addition to the generel release
 guidelines of the CaosDB Project
@@ -28,7 +28,9 @@ guidelines of the CaosDB Project
 
 6. Delete the release branch.
 
-7. Publish the release by executing `./release.sh` with uploads the caosdb
+7. Remove possibly existing `./dist` directory with old release.
+
+8. Publish the release by executing `./release.sh` with uploads the caosdb
    module to the Python Package Index [pypi.org](https://pypi.org).
 
-8. Merge the master branch back into the dev branch.
+9. Merge the master branch back into the dev branch.
diff --git a/release.sh b/release.sh
old mode 100644
new mode 100755
diff --git a/setup.py b/setup.py
index 09144c0b67c4341ca4c0173ab1127493246f93c1..81a0775d0f86c49f5e7564e6192a389c23e54b4f 100755
--- a/setup.py
+++ b/setup.py
@@ -46,10 +46,11 @@ from setuptools import find_packages, setup
 ########################################################################
 
 MAJOR = 0
-MINOR = 2
-MICRO = 4
-PRE = ""  # e.g. rc0, alpha.1, 0.beta-23
+MINOR = 3
+MICRO = 0
+PRE = ""
 ISRELEASED = True
+
 if PRE:
     VERSION = "{}.{}.{}-{}".format(MAJOR, MINOR, MICRO, PRE)
 else:
diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py
index f3887099a93d50740a3b2825bc6e8a9677509079..bd279fcfe5c394b9b5cff787169cff5b9f2d3031 100644
--- a/src/caosdb/apiutils.py
+++ b/src/caosdb/apiutils.py
@@ -5,6 +5,8 @@
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -34,7 +36,8 @@ from subprocess import call
 from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
                                     REFERENCE, TEXT)
 from caosdb.common.models import (Container, Entity, File, Property, Query,
-                                  Record, RecordType, get_config)
+                                  Record, RecordType, get_config,
+                                  execute_query, is_reference)
 
 
 def new_record(record_type, name=None, description=None,
@@ -85,11 +88,11 @@ def new_record(record_type, name=None, description=None,
 def id_query(ids):
     q = "FIND Entity with " + " OR ".join(["id={}".format(id) for id in ids])
 
-    return db.execute_query(q)
+    return execute_query(q)
 
 
 def retrieve_entities_with_ids(entities):
-    collection = db.Container()
+    collection = Container()
     step = 20
 
     for i in range(len(entities)//step+1):
@@ -669,3 +672,36 @@ def describe_diff(olddiff, newdiff, name=None, as_update=True):
                        "version of {}\n\n".format(name))+description
 
     return description
+
+
+def apply_to_ids(entities, func):
+    """ Apply a function to all ids.
+
+    All ids means the ids of the entities themselves but also to all parents,
+    properties and referenced entities.
+
+    Parameters
+    ----------
+    entities : list of Entity
+    func : function with one parameter.
+    """
+    for entity in entities:
+        _apply_to_ids_of_entity(entity, func)
+
+
+def _apply_to_ids_of_entity(entity, func):
+    entity.id = func(entity.id)
+
+    for par in entity.parents:
+        par.id = func(par.id)
+
+    for prop in entity.properties:
+        prop.id = func(prop.id)
+        isref = is_reference(prop.datatype)
+
+        if isref:
+            if isinstance(prop.value, list):
+                prop.value = [func(el) for el in prop.value]
+            else:
+                if prop.value is not None:
+                    prop.value = func(prop.value)
diff --git a/src/caosdb/common/datatype.py b/src/caosdb/common/datatype.py
index 8578574af6cc874550ca3d4a53ab90cd3946e87a..246485c3957462fc98ac83f9d904413ad7518302 100644
--- a/src/caosdb/common/datatype.py
+++ b/src/caosdb/common/datatype.py
@@ -110,7 +110,7 @@ def get_id_of_datatype(datatype):
         raise AmbiguityException(
             "Name {} did not lead to unique result; Missing "
             "implementation".format(datatype))
-    elif len(res) == 1:
+    elif len(res) != 1:
         raise EntityDoesNotExistError(
             "No RecordType named {}".format(datatype))
 
diff --git a/src/caosdb/common/models.py b/src/caosdb/common/models.py
index 84cdb96b4c0ae359dbeb249b9ae0744a06aa87e8..364ff99270294a6be714ddf1db759ac63746daaa 100644
--- a/src/caosdb/common/models.py
+++ b/src/caosdb/common/models.py
@@ -38,8 +38,8 @@ from sys import hexversion
 from tempfile import NamedTemporaryFile
 from warnings import warn
 
-from lxml import etree
-
+from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
+                                    LIST, REFERENCE, TEXT, is_reference)
 from caosdb.common.utils import uuid, xml2str
 from caosdb.configuration import get_config
 from caosdb.connection.connection import get_connection
@@ -51,8 +51,9 @@ from caosdb.exceptions import (AmbiguityException, AuthorizationException,
                                EntityHasNoDatatypeError, TransactionError,
                                UniqueNamesError, UnqualifiedParentsError,
                                UnqualifiedPropertiesError, URITooLongException)
-from caosdb.common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER,
-                                    LIST, REFERENCE, TEXT, is_reference)
+from lxml import etree
+
+from .datatype import is_reference
 
 _ENTITY_URI_SEGMENT = "Entity"
 
diff --git a/unittests/test_apiutils.py b/unittests/test_apiutils.py
index 5476059344407c0c08e86dc8c15fae73b12a23c6..6d7581478e377ce6b41e8a00a2d47bb404d55a0b 100644
--- a/unittests/test_apiutils.py
+++ b/unittests/test_apiutils.py
@@ -5,6 +5,8 @@
 #
 # Copyright (C) 2018 Research Group Biomedical Physics,
 # Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -25,6 +27,7 @@
 # A. Schlemmer, 02/2018
 
 import caosdb as db
+from caosdb.apiutils import apply_to_ids
 from .record import testrecord
 import pickle
 import tempfile
@@ -42,3 +45,20 @@ def test_pickle_object():
         f.seek(0)
         rn2 = pickle.load(f)
     assert r2.date == rn2.date
+
+
+def test_apply_to_ids():
+    parent = db.RecordType(id=3456)
+    rec = db.Record(id=23)
+    p = db.Property(id=23345, datatype=db.INTEGER)
+    rec.add_parent(parent)
+    rec.add_property(p)
+
+    def invert(id_):
+        return id_ * -1
+    apply_to_ids([rec], invert)
+
+    assert invert(3456) == -3456
+    assert rec.parents[0].id == -3456
+    assert rec.properties[0].id == -23345
+    assert rec.id == -23
diff --git a/unittests/test_entity.py b/unittests/test_entity.py
index c3862ae253b8fa8ad5640ae79c1088a385fb752b..d877e1ab7267977a7e73d65033d6f02c16ea5521 100644
--- a/unittests/test_entity.py
+++ b/unittests/test_entity.py
@@ -22,42 +22,36 @@
 # ** end header
 #
 """Tests for the Entity class."""
+# pylint: disable=missing-docstring
 import unittest
 
-from caosdb import Entity, configure_connection
+from caosdb import (INTEGER, Entity, Property, Record, RecordType,
+                    configure_connection)
 from caosdb.connection.mockup import MockUpServerConnection
-# pylint: disable=missing-docstring
-from nose.tools import assert_equal as eq
-from nose.tools import assert_is_not_none as there
-from nose.tools import assert_true as tru
-
 
-def setup_module():
-    there(Entity)
-    configure_connection(url="unittests", username="testuser",
-                         password="testpassword", timeout=200,
-                         implementation=MockUpServerConnection)
 
+class TestEntity(unittest.TestCase):
 
-def hat(obj, attr):
-    tru(hasattr(obj, attr))
-
+    def setUp(self):
+        self.assertIsNotNone(Entity)
+        configure_connection(url="unittests", username="testuser",
+                             password="testpassword", timeout=200,
+                             implementation=MockUpServerConnection)
 
-class TestEntity(unittest.TestCase):
     def test_instance_variables(self):
         entity = Entity()
-        hat(entity, "role")
-        hat(entity, "id")
-        hat(entity, "name")
-        hat(entity, "description")
-        hat(entity, "parents")
-        hat(entity, "properties")
+        self.assertTrue(hasattr(entity, "role"))
+        self.assertTrue(hasattr(entity, "id"))
+        self.assertTrue(hasattr(entity, "name"))
+        self.assertTrue(hasattr(entity, "description"))
+        self.assertTrue(hasattr(entity, "parents"))
+        self.assertTrue(hasattr(entity, "properties"))
 
     def test_role(self):
         entity = Entity(role="TestRole")
-        eq(entity.role, "TestRole")
+        self.assertEqual(entity.role, "TestRole")
         entity.role = "TestRole2"
-        eq(entity.role, "TestRole2")
+        self.assertEqual(entity.role, "TestRole2")
 
     def test_instanciation(self):
         self.assertRaises(Exception, Entity())