diff --git a/src/common/orm/_Database.py b/src/common/orm/Database.py
similarity index 58%
rename from src/common/orm/_Database.py
rename to src/common/orm/Database.py
index c1a0a9065b33adf8309ae5394d7dbf1594abcfbf..9f29e9d617828bc63f9e2238257e4009aee2bfe9 100644
--- a/src/common/orm/_Database.py
+++ b/src/common/orm/Database.py
@@ -1,38 +1,19 @@
 import logging
 from typing import List, Set
 from .backend._Backend import _Backend
-from .model.Model import Model
-from .Exceptions import MutexException
 
 LOGGER = logging.getLogger(__name__)
 
-class _Database(Model):
+class Database:
     def __init__(self, backend : _Backend):
         if not isinstance(backend, _Backend):
             str_class_path = '{}.{}'.format(_Backend.__module__, _Backend.__name__)
             raise AttributeError('backend must inherit from {}'.format(str_class_path))
         self._backend = backend
-        super().__init__(self)
-        self._acquired = False
-        self._owner_key = None
-
-    @property
-    def parent(self) -> '_Database': return self
 
     @property
     def backend(self) -> _Backend: return self._backend
 
-    @property
-    def backend_key(self) -> str: return ''
-
-    #def __enter__(self) -> '_Database':
-    #    self._acquired, self._owner_key = self._backend.lock()
-    #    if not self._acquired: raise MutexException('Unable to acquire database lock')
-    #    return self
-
-    #def __exit__(self, exc_type, exc_val, exc_tb) -> None:
-    #    self._backend.unlock(self._owner_key)
-
     def clear_all(self, keep_keys : Set[str] = set()) -> None:
         for key in self._backend.keys():
             if key in keep_keys: continue
diff --git a/src/common/orm/Exceptions.py b/src/common/orm/Exceptions.py
index 0d4cb33f91be9df3a9e237351312cb666c2a9654..eea0b564e1918cb6a2da0553641c9492a32b1425 100644
--- a/src/common/orm/Exceptions.py
+++ b/src/common/orm/Exceptions.py
@@ -1,2 +1,5 @@
+class ConstraintException(Exception):
+    pass
+
 class MutexException(Exception):
     pass
diff --git a/src/common/orm/backend/_Backend.py b/src/common/orm/backend/_Backend.py
index a8dd7eac293e101605c461ef9131deaf72e54507..a143b411366c3636cd287bfa6f6a4922a7919d0d 100644
--- a/src/common/orm/backend/_Backend.py
+++ b/src/common/orm/backend/_Backend.py
@@ -1,4 +1,4 @@
-from typing import Dict, List, Optional, Tuple
+from typing import Dict, List, Optional, Set, Tuple
 
 class _Backend:
     def __init__(self, **settings) -> None:
@@ -22,7 +22,7 @@ class _Backend:
     def dict_get(self, key : List[str], fields : List[str] = []) -> Dict[str, str]:
         raise NotImplementedError()
 
-    def dict_update(self, key : List[str], fields : Dict[str,str] = {}) -> None:
+    def dict_update(self, key : List[str], fields : Dict[str, str] = {}) -> None:
         raise NotImplementedError()
 
     def dict_delete(self, key : List[str], fields : List[str] = []) -> None:
@@ -43,8 +43,11 @@ class _Backend:
     def set_has(self, key : List[str], item : str) -> bool:
         raise NotImplementedError()
 
+    def set_get_all(self, key : List[str]) -> Set[str]:
+        raise NotImplementedError()
+
     def set_remove(self, key : List[str], item : str) -> None:
         raise NotImplementedError()
 
-    def dump(self) -> List[str]:
+    def dump(self) -> List[Tuple[str, str, str]]:
         raise NotImplementedError()
diff --git a/src/common/orm/backend/inmemory/InMemoryBackend.py b/src/common/orm/backend/inmemory/InMemoryBackend.py
index 13a38027555799e23cabaf32c3d8ef55d826ef15..be1410b95921205b8230679f3cd5e4d3a7b0ff7c 100644
--- a/src/common/orm/backend/inmemory/InMemoryBackend.py
+++ b/src/common/orm/backend/inmemory/InMemoryBackend.py
@@ -9,7 +9,7 @@ import copy, logging, threading, uuid
 from typing import Dict, List, Optional, Set, Tuple, Union
 from .._Backend import _Backend
 from ..Tools import key_to_str
-from .Tools import get_or_create_dict, get_or_create_list, get_or_create_set
+from .Tools import get_dict, get_list, get_or_create_dict, get_or_create_list, get_or_create_set, get_set
 
 LOGGER = logging.getLogger(__name__)
 
@@ -32,11 +32,11 @@ class InMemoryBackend(_Backend):
                         if str_key not in self._keys: continue
                         del self._keys[str_key]
                     return False, None
-                else:
-                    # lock available, temporarily acquire it; locks will be released if some of them for a requested
-                    # key is not available
-                    self._keys[str_key] = owner_key
-                    acquired_lock_keys[str_key] = owner_key
+
+                # lock available, temporarily acquire it; locks will be released if some of them for a requested
+                # key is not available
+                self._keys[str_key] = owner_key
+                acquired_lock_keys[str_key] = owner_key
             return True, owner_key
 
     def unlock(self, keys : List[List[str]], owner_key : str) -> bool:
@@ -69,7 +69,8 @@ class InMemoryBackend(_Backend):
     def dict_get(self, key : List[str], fields : List[str] = []) -> Dict[str, str]:
         str_key = key_to_str(key)
         with self._lock:
-            container = get_or_create_dict(self._keys, str_key)
+            container = get_dict(self._keys, str_key)
+            if container is None: return None
             if len(fields) == 0: fields = container.keys()
             return copy.deepcopy({
                 field_name : field_value for field_name,field_value in container.items() if field_name in fields
@@ -90,11 +91,13 @@ class InMemoryBackend(_Backend):
             else:
                 container = get_or_create_dict(self._keys, str_key)
                 for field in list(fields): container.pop(field, None)
+                if len(container) == 0: self._keys.pop(str_key)
 
     def list_get_all(self, key : List[str]) -> List[str]:
         str_key = key_to_str(key)
         with self._lock:
-            container = get_or_create_list(self._keys, str_key)
+            container = get_list(self._keys, str_key)
+            if container is None: return None
             return copy.deepcopy(container)
 
     def list_push_last(self, key : List[str], item : str) -> None:
@@ -108,6 +111,7 @@ class InMemoryBackend(_Backend):
         with self._lock:
             container = get_or_create_list(self._keys, str_key)
             container.remove(item)
+            if len(container) == 0: self._keys.pop(str_key)
 
     def set_add(self, key : List[str], item : str) -> None:
         str_key = key_to_str(key)
@@ -121,11 +125,19 @@ class InMemoryBackend(_Backend):
             container = get_or_create_set(self._keys, str_key)
             return item in container
 
+    def set_get_all(self, key : List[str]) -> Set[str]:
+        str_key = key_to_str(key)
+        with self._lock:
+            container = get_set(self._keys, str_key)
+            if container is None: return None
+            return copy.deepcopy(container)
+
     def set_remove(self, key : List[str], item : str) -> None:
         str_key = key_to_str(key)
         with self._lock:
             container = get_or_create_set(self._keys, str_key)
             container.discard(item)
+            if len(container) == 0: self._keys.pop(str_key)
 
     def dump(self) -> List[Tuple[str, str, str]]:
         with self._lock:
diff --git a/src/common/orm/backend/inmemory/Tools.py b/src/common/orm/backend/inmemory/Tools.py
index f8fb573504bc6daa9622c79482fc0676a31058f2..fe10506556de36d6f40665c6f59119cbf540d8a4 100644
--- a/src/common/orm/backend/inmemory/Tools.py
+++ b/src/common/orm/backend/inmemory/Tools.py
@@ -1,5 +1,8 @@
 from typing import Dict, List, Set, Union
 
+def get_dict(keys : Dict[str, Union[Dict, List, Set]], str_key : str) -> Dict:
+    return keys.get(str_key, None)
+
 def get_or_create_dict(keys : Dict[str, Union[Dict, List, Set]], str_key : str) -> Dict:
     container = keys.get(str_key, None)
     if container is None: container = keys.setdefault(str_key, dict())
@@ -7,6 +10,9 @@ def get_or_create_dict(keys : Dict[str, Union[Dict, List, Set]], str_key : str)
         raise Exception('Key({:s}, {:s}) is not a dict'.format(str(type(container).__name__), str(str_key)))
     return container
 
+def get_list(keys : Dict[str, Union[Dict, List, Set]], str_key : str) -> List:
+    return keys.get(str_key, None)
+
 def get_or_create_list(keys : Dict[str, Union[Dict, List, Set]], str_key : str) -> List:
     container = keys.get(str_key, None)
     if container is None: container = keys.setdefault(str_key, list())
@@ -14,6 +20,9 @@ def get_or_create_list(keys : Dict[str, Union[Dict, List, Set]], str_key : str)
         raise Exception('Key({:s}, {:s}) is not a list'.format(str(type(container).__name__), str(str_key)))
     return container
 
+def get_set(keys : Dict[str, Union[Dict, List, Set]], str_key : str) -> Set:
+    return keys.get(str_key, None)
+
 def get_or_create_set(keys : Dict[str, Union[Dict, List, Set]], str_key : str) -> Set:
     container = keys.get(str_key, None)
     if container is None: container = keys.setdefault(str_key, set())
diff --git a/src/common/orm/backend/redis/RedisBackend.py b/src/common/orm/backend/redis/RedisBackend.py
index 028c735540950d2f2c58145f595be278934450b7..99ae304c91fa86f94c3674ef41c2f31bc7dda413 100644
--- a/src/common/orm/backend/redis/RedisBackend.py
+++ b/src/common/orm/backend/redis/RedisBackend.py
@@ -1,5 +1,5 @@
 import os, uuid
-from typing import Any, Dict, List, Optional, Tuple, Union
+from typing import Any, Dict, List, Optional, Set, Tuple
 from redis.client import Redis
 from .._Backend import _Backend
 from ..Tools import key_to_str
@@ -41,30 +41,6 @@ class RedisBackend(_Backend):
         str_key = key_to_str(key)
         return self._client.delete(str_key) == 1
 
-    def set_has(self, key : List[str], item : str) -> bool:
-        str_key = key_to_str(key)
-        return self._client.sismember(str_key, item) == 1
-
-    def set_add(self, key : List[str], item : str) -> None:
-        str_key = key_to_str(key)
-        self._client.sadd(str_key, item)
-
-    def set_remove(self, key : List[str], item : str) -> None:
-        str_key = key_to_str(key)
-        self._client.srem(str_key, item)
-
-    def list_push_last(self, key : List[str], item : str) -> None:
-        str_key = key_to_str(key)
-        self._client.rpush(str_key, item)
-
-    def list_get_all(self, key : List[str]) -> List[str]:
-        str_key = key_to_str(key)
-        return list(map(lambda m: m.decode('UTF-8'), self._client.lrange(str_key, 0, -1)))
-
-    def list_remove_first_occurrence(self, key : List[str], item: str) -> None:
-        str_key = key_to_str(key)
-        self._client.lrem(str_key, 1, item)
-
     def dict_get(self, key : List[str], fields : List[str] = []) -> Dict[str, str]:
         str_key = key_to_str(key)
         if len(fields) == 0:
@@ -91,6 +67,34 @@ class RedisBackend(_Backend):
         else:
             self._client.hdel(str_key, set(fields))
 
+    def list_get_all(self, key : List[str]) -> List[str]:
+        str_key = key_to_str(key)
+        return list(map(lambda m: m.decode('UTF-8'), self._client.lrange(str_key, 0, -1)))
+
+    def list_push_last(self, key : List[str], item : str) -> None:
+        str_key = key_to_str(key)
+        self._client.rpush(str_key, item)
+
+    def list_remove_first_occurrence(self, key : List[str], item: str) -> None:
+        str_key = key_to_str(key)
+        self._client.lrem(str_key, 1, item)
+
+    def set_add(self, key : List[str], item : str) -> None:
+        str_key = key_to_str(key)
+        self._client.sadd(str_key, item)
+
+    def set_has(self, key : List[str], item : str) -> bool:
+        str_key = key_to_str(key)
+        return self._client.sismember(str_key, item) == 1
+
+    def set_get_all(self, key : List[str]) -> Set[str]:
+        str_key = key_to_str(key)
+        return set(map(lambda m: m.decode('UTF-8'), self._client.smembers(str_key)))
+
+    def set_remove(self, key : List[str], item : str) -> None:
+        str_key = key_to_str(key)
+        self._client.srem(str_key, item)
+
     def dump(self) -> List[Tuple[str, str, str]]:
         entries = []
         for str_key in self._client.keys():
diff --git a/src/common/orm/fields/BooleanField.py b/src/common/orm/fields/BooleanField.py
index e802b4e4bf1ed6b69b57a2d84b47010618f63bd7..f159ada45d39158eadf4c46150c4b80daa3263f8 100644
--- a/src/common/orm/fields/BooleanField.py
+++ b/src/common/orm/fields/BooleanField.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 from typing import TYPE_CHECKING
-from common.type_checkers.Checkers import chk_boolean, chk_not_none
+from common.type_checkers.Checkers import chk_boolean
 from .Field import Field
 
 if TYPE_CHECKING:
@@ -13,12 +13,15 @@ class BooleanField(Field):
         super().__init__(*args, type_=bool, **kwargs)
 
     def __set__(self, instance : 'Model', value : bool) -> None:
-        if self.required: chk_not_none(self.name, value)
-        if value is None: super().__set__(instance, value)
-        super().__set__(instance, chk_boolean(self.name, value))
+        super().__set__(instance, self.validate(value))
+
+    def validate(self, value):
+        value = super().validate(value)
+        return None if value is None else chk_boolean(self.name, value)
 
     def serialize(self, value : bool) -> str:
-        return str(value)
+        value = self.validate(value)
+        return None if value is None else str(value)
 
     def deserialize(self, value : str) -> bool:
         return (value.upper() in BOOL_TRUE_VALUES)
diff --git a/src/common/orm/fields/Field.py b/src/common/orm/fields/Field.py
index 80ba0a8c8229ce6c68335e1e63627c808f9ec364..995fa9342c6b82a57242cbd1941207a299cdbc13 100644
--- a/src/common/orm/fields/Field.py
+++ b/src/common/orm/fields/Field.py
@@ -1,26 +1,43 @@
 from __future__ import annotations
+from abc import ABC, abstractmethod
+import logging
 from typing import TYPE_CHECKING, Any, List, Set, Tuple, Union
-from common.type_checkers.Checkers import chk_boolean, chk_string, chk_type
+from common.type_checkers.Checkers import chk_boolean, chk_not_none, chk_string, chk_type
 
 if TYPE_CHECKING:
     from ..model.Model import Model
 
-class Field:
+LOGGER = logging.getLogger(__name__)
+
+# Ref: https://docs.python.org/3.9/howto/descriptor.html
+
+class Field(ABC):
     def __init__(
         self, name : str = None, type_ : Union[type, Set[type], Tuple[type], List[type]] = object,
         required : bool = False) -> None:
+
         self.name = None if name is None else chk_string('Field.name', name)
         self.type_ = chk_type('Field.type', type_, (type, set, tuple, list))
         self.required = chk_boolean('Field.required', required)
 
+    def __get__(self, instance : 'Model', objtype=None):
+        if instance is None: return self
+        return instance.__dict__.get(self.name)
+
     def __set__(self, instance : 'Model', value : Any) -> None:
         instance.__dict__[self.name] = value
 
     def __delete__(self, instance : 'Model'):
         raise AttributeError('Attribute "{:s}" cannot be deleted'.format(self.name))
 
+    def validate(self, value):
+        if self.required: chk_not_none(self.name, value, reason='is required. It cannot be None.')
+        return value
+
+    @abstractmethod
     def serialize(self, value : Any) -> str:
         raise NotImplementedError
 
+    @abstractmethod
     def deserialize(self, value : str) -> Any:
         raise NotImplementedError
diff --git a/src/common/orm/fields/FloatField.py b/src/common/orm/fields/FloatField.py
index b1485b33f07d71dd684aa0b1b1dd87a2e3ec7058..1b0cb2da3bf57887041d445ccb54c8684cbe2e70 100644
--- a/src/common/orm/fields/FloatField.py
+++ b/src/common/orm/fields/FloatField.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 from typing import TYPE_CHECKING, Optional
-from common.type_checkers.Checkers import chk_float, chk_not_none
+from common.type_checkers.Checkers import chk_float
 from .Field import Field
 
 if TYPE_CHECKING:
@@ -17,12 +17,16 @@ class FloatField(Field):
             chk_float('{}.max_value'.format(self.name), max_value, min_value=self._min_value)
 
     def __set__(self, instance : 'Model', value : float) -> None:
-        if self.required: chk_not_none(self.name, value)
-        if value is None: super().__set__(instance, value)
-        super().__set__(instance, chk_float(self.name, value, min_value=self._min_value, max_value=self._max_value))
+        super().__set__(instance, self.validate(value))
 
-    def serialize(self, value : float) -> str:
-        return str(value)
+    def validate(self, value):
+        value = super().validate(value)
+        return None if value is None else chk_float(
+            self.name, value, min_value=self._min_value, max_value=self._max_value)
+
+    def serialize(self, value : bool) -> str:
+        value = self.validate(value)
+        return None if value is None else str(value)
 
     def deserialize(self, value : str) -> float:
         return float(value)
diff --git a/src/common/orm/fields/ForeignKeyField.py b/src/common/orm/fields/ForeignKeyField.py
index ac34403d5bd7e6edef98a160e0c2d1d1b71dcb2b..c1cab6245711f01075e66e89c2e6fa81cf52bd74 100644
--- a/src/common/orm/fields/ForeignKeyField.py
+++ b/src/common/orm/fields/ForeignKeyField.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
-from typing import TYPE_CHECKING
-from common.type_checkers.Checkers import chk_issubclass, chk_not_none, chk_type
-from ..backend.Tools import key_to_str
+from typing import TYPE_CHECKING, Union
+from common.orm.Exceptions import ConstraintException
+from common.type_checkers.Checkers import chk_issubclass, chk_type
 from .StringField import StringField
 
 if TYPE_CHECKING:
@@ -13,8 +13,19 @@ class ForeignKeyField(StringField):
         self.foreign_model : Model = chk_issubclass('Field.foreign_model', foreign_model, Model)
         super().__init__(*args, required=required, allow_empty=not required, **kwargs)
 
-    def __set__(self, instance : 'Model', value : 'Model') -> None:
-        if self.required: chk_not_none(self.name, value)
-        if value is None: super().__set__(instance, value)
+    def __set__(self, instance : 'Model', value : Union['Model', str]) -> None:
         model_instance : 'Model' = chk_type('value', value, self.foreign_model)
-        super().__set__(instance, key_to_str(model_instance.backend_key))
+        super().__set__(instance, model_instance.instance_key)
+
+    def __delete__(self, instance: 'Model'):
+        if self.required:
+            msg = 'ForeignKey({}) is required. Unable to clear it.'
+            raise ConstraintException(msg.format(str(self.name)))
+        super().__set__(instance, None)
+
+    def serialize(self, value: str) -> str:
+        if not self.required and value is None: return None
+        if self.required and (value is None or len(value) == 0):
+            msg = 'ForeignKey({}, {}) is required. It cannot be serialized as empty.'
+            raise ConstraintException(msg.format(str(self.name), str(value)))
+        return super().serialize(value)
diff --git a/src/common/orm/fields/IntegerField.py b/src/common/orm/fields/IntegerField.py
index 72cccdac7fd7bad734e9503434764be7c9e797ea..ae86f0c41b33e9a729525aebf9fa65410d8b35c5 100644
--- a/src/common/orm/fields/IntegerField.py
+++ b/src/common/orm/fields/IntegerField.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 from typing import TYPE_CHECKING, Optional
-from common.type_checkers.Checkers import chk_integer, chk_not_none
+from common.type_checkers.Checkers import chk_integer
 from .Field import Field
 
 if TYPE_CHECKING:
@@ -17,12 +17,16 @@ class IntegerField(Field):
             chk_integer('{}.max_value'.format(self.name), max_value, min_value=self._min_value)
 
     def __set__(self, instance : 'Model', value : int) -> None:
-        if self.required: chk_not_none(self.name, value)
-        if value is None: super().__set__(instance, value)
-        super().__set__(instance, chk_integer(self.name, value, min_value=self._min_value, max_value=self._max_value))
+        super().__set__(instance, self.validate(value))
 
-    def serialize(self, value : int) -> str:
-        return str(value)
+    def validate(self, value):
+        value = super().validate(value)
+        return None if value is None else chk_integer(
+            self.name, value, min_value=self._min_value, max_value=self._max_value)
+
+    def serialize(self, value : bool) -> str:
+        value = self.validate(value)
+        return None if value is None else str(value)
 
     def deserialize(self, value : str) -> int:
         return int(value)
diff --git a/src/common/orm/fields/PrimaryKeyField.py b/src/common/orm/fields/PrimaryKeyField.py
index 2111c1b65e9af6f7899a0ee9254ce103d3bb3882..d159071b6cdbf53700da8ff191ba216129c044f1 100644
--- a/src/common/orm/fields/PrimaryKeyField.py
+++ b/src/common/orm/fields/PrimaryKeyField.py
@@ -1,6 +1,5 @@
 from __future__ import annotations
 from typing import TYPE_CHECKING
-from common.type_checkers.Checkers import chk_not_none
 from .StringField import StringField
 
 if TYPE_CHECKING:
@@ -11,7 +10,6 @@ class PrimaryKeyField(StringField):
         super().__init__(*args, required=True, allow_empty=False, min_length=1, **kwargs)
 
     def __set__(self, instance : 'Model', value : str) -> None:
-        chk_not_none(self.name, value) # Always required
         if (self.name in instance.__dict__) and (instance.__dict__[self.name] is not None):
             raise ValueError('PrimaryKeyField cannot be modified')
         super().__set__(instance, value)
diff --git a/src/common/orm/fields/StringField.py b/src/common/orm/fields/StringField.py
index 8a6e260a116aab29c140ff377b7a033248c4dcaa..898a7d5262a0fa9c8b36853806b2237908d819fb 100644
--- a/src/common/orm/fields/StringField.py
+++ b/src/common/orm/fields/StringField.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 import re
 from typing import TYPE_CHECKING, Optional, Pattern, Union
-from common.type_checkers.Checkers import chk_boolean, chk_integer, chk_not_none, chk_string
+from common.type_checkers.Checkers import chk_boolean, chk_integer, chk_string
 from .Field import Field
 
 if TYPE_CHECKING:
@@ -21,14 +21,17 @@ class StringField(Field):
         self._pattern = None if pattern is None else re.compile(pattern)
 
     def __set__(self, instance : 'Model', value : str) -> None:
-        if self.required: chk_not_none(self.name, value)
-        if value is None: super().__set__(instance, value)
-        super().__set__(instance, chk_string(
+        super().__set__(instance, self.validate(value))
+
+    def validate(self, value):
+        value = super().validate(value)
+        return None if value is None else chk_string(
             self.name, value, allow_empty=self._allow_empty, min_length=self._min_length, max_length=self._max_length,
-            pattern=self._pattern))
+            pattern=self._pattern)
 
-    def serialize(self, value : str) -> str:
-        return value
+    def serialize(self, value : bool) -> str:
+        value = self.validate(value)
+        return None if value is None else str(value)
 
     def deserialize(self, value : str) -> str:
         return value
diff --git a/src/common/orm/model/Model.py b/src/common/orm/model/Model.py
index b4950d163208aec8981be13d56c3c6011d47c7c5..3666cffdf7ba79ed3b1ab511d134b9bc8305bbd6 100644
--- a/src/common/orm/model/Model.py
+++ b/src/common/orm/model/Model.py
@@ -1,73 +1,75 @@
 from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Set, Tuple, Type
+import logging, re
+from typing import Any, Dict, List, Mapping, Optional, Set, Tuple
+from common.orm.Database import Database
 from common.orm.backend.Tools import key_to_str
 from common.orm.fields.ForeignKeyField import ForeignKeyField
-from common.type_checkers.Checkers import chk_none
-from ..Exceptions import MutexException
-from ..backend._Backend import _Backend
+from ..Exceptions import ConstraintException, MutexException
 from ..fields.Field import Field
 from ..fields.PrimaryKeyField import PrimaryKeyField
 from .Tools import NoDupOrderedDict
 
+LOGGER = logging.getLogger(__name__)
+DEFAULT_PRIMARY_KEY_NAME = 'pk_auto'
+
 class MetaModel(type):
     @classmethod
-    def __prepare__(metacls, name : str, bases : Tuple[type, ...], **attrs : Any) -> Mapping[str, Any]:
+    def __prepare__(cls, name : str, bases : Tuple[type, ...], **attrs : Any) -> Mapping[str, Any]:
         return NoDupOrderedDict()
 
-    def __new__(metacls, name : str, bases : Tuple[type, ...], attrs : NoDupOrderedDict[str, Any]):
+    def __new__(cls, name : str, bases : Tuple[type, ...], attrs : NoDupOrderedDict[str, Any]):
         field_names = list()
-        primary_key_field = None
+        pk_field_name = None
         for key, value in attrs.items():
             if not isinstance(value, Field): continue
-            attrs[key].name = key
+            value.name = key
             field_names.append(key)
             if not isinstance(value, PrimaryKeyField): continue
-            if primary_key_field is None:
-                primary_key_field = value
+            if pk_field_name is None:
+                pk_field_name = key
                 continue
-            raise AttributeError('PrimaryKey for Model({:s}) already set to attribute({:s})'.format(
-                str(name), str(primary_key_field.name)))
-        cls_obj = super().__new__(metacls, name, bases, dict(attrs))
-        setattr(cls_obj, '_primary_key_field', primary_key_field)
+            raise AttributeError('PrimaryKeyField for Model({:s}) already set to attribute({:s})'.format(
+                str(name), str(pk_field_name)))
+        if pk_field_name is None:
+            if DEFAULT_PRIMARY_KEY_NAME in attrs.keys():
+                msg = 'PrimaryKeyField for Model({:s}) not defined and attribute "{:s}" already used. '\
+                      'Leave attribute name "{:s}" for automatic PrimaryKeyField, or set a PrimaryKeyField.'
+                raise AttributeError(msg.format(str(name), DEFAULT_PRIMARY_KEY_NAME, DEFAULT_PRIMARY_KEY_NAME))
+            pk_field_name = DEFAULT_PRIMARY_KEY_NAME
+            attrs[pk_field_name] = PrimaryKeyField(name=pk_field_name)
+            field_names.append(pk_field_name)
+        cls_obj = super().__new__(cls, name, bases, dict(attrs))
+        setattr(cls_obj, '_pk_field_name', pk_field_name)
         setattr(cls_obj, '_field_names_list', field_names)
         setattr(cls_obj, '_field_names_set', set(field_names))
         return cls_obj
 
 class Model(metaclass=MetaModel):
-    def __init__(self, parent : 'Model', primary_key : Any = None) -> None:
-        if not isinstance(parent, Model):
-            str_class_path = '{}.{}'.format(Model.__module__, Model.__name__)
-            raise AttributeError('parent must inherit from {}'.format(str_class_path))
-        self._parent = parent
-        self._backend = self._parent.backend
-        self._class_name = type(self).__name__
-        backend_key = self._class_name
-        if self._primary_key_field is not None: # pylint: disable=no-member
-            primary_key_field_name = self._primary_key_field.name # pylint: disable=no-member
-            setattr(self, primary_key_field_name, primary_key) 
-            backend_key += '[{:s}]'.format(getattr(self, primary_key_field_name))
-        else:
-            try:
-                chk_none('primary_key', primary_key)
-            except:
-                msg = 'Unable to set primary_key({:s}) since no PrimaryKeyField is defined in the model'
-                raise AttributeError(msg.format(str(primary_key)))
-        self._backend_key : str = key_to_str([self.parent.backend_key, backend_key])
-        self._backend_parent_key : str = self.parent.backend_key
-        self._backend_references_key : str = key_to_str([self.parent.backend_key, backend_key, 'references'])
+    def __init__(self, database : Database, primary_key : str, auto_load : bool = True) -> None:
+        if not isinstance(database, Database):
+            str_class_path = '{}.{}'.format(Database.__module__, Database.__name__)
+            raise AttributeError('database must inherit from {}'.format(str_class_path))
+        self._model_class = type(self)
+        self._class_name = self._model_class.__name__
+        pk_field_name = self._pk_field_name # pylint: disable=no-member
+        pk_field_instance : 'PrimaryKeyField' = getattr(self._model_class, pk_field_name)
+        primary_key = pk_field_instance.validate(primary_key)
+        if primary_key.startswith(self._class_name):
+            match = re.match(r'^{:s}\[([^\]]*)\]'.format(self._class_name), primary_key)
+            if match: primary_key = match.group(1)
+        setattr(self, pk_field_name, primary_key)
+        self._database = database
+        self._backend = database.backend
+        self._instance_key : str = '{:s}[{:s}]'.format(self._class_name, primary_key)
+        self._references_key : str = key_to_str([self._instance_key, 'references'])
         self._owner_key : Optional[str] = None
+        if auto_load: self.load()
 
     @property
-    def parent(self) -> 'Model': return self._parent
-
-    @property
-    def backend(self) -> _Backend: return self._parent.backend
-
-    @property
-    def backend_key(self) -> str: return self._backend_key
+    def instance_key(self) -> str: return self._instance_key
 
     def lock(self, extra_keys : List[List[str]] = []):
-        lock_keys = [self._backend_key, self.parent.backend_key, self._backend_references_key] + extra_keys
+        lock_keys = [self._instance_key, self._references_key] + extra_keys
         lock_keys = [key_to_str([lock_key, 'lock']) for lock_key in lock_keys]
         acquired,self._owner_key = self._backend.lock(lock_keys, owner_key=self._owner_key)
         if acquired: return
@@ -75,43 +77,49 @@ class Model(metaclass=MetaModel):
             str(lock_keys), str(self._owner_key)))
 
     def unlock(self, extra_keys : List[List[str]] = []):
-        lock_keys = [self._backend_key, self.parent.backend_key, self._backend_references_key] + extra_keys
+        lock_keys = [self._instance_key, self._references_key] + extra_keys
         lock_keys = [key_to_str([lock_key, 'lock']) for lock_key in lock_keys]
         released = self._backend.unlock(lock_keys, self._owner_key)
         if released: return
-        raise Exception('Unable to unlock keys {:s} using owner_key {:s}'.format(
+        raise MutexException('Unable to unlock keys {:s} using owner_key {:s}'.format(
             str(lock_keys), str(self._owner_key)))
 
     def load(self) -> None:
-        self.lock()
-
-        model_class = type(self)
-        attributes = self._backend.dict_get(self._backend_key)
-        pk_field = self._primary_key_field # pylint: disable=no-member
-        pk_field_name = None if pk_field is None else pk_field.name
-        for field_name in self._field_names_list: # pylint: disable=no-member
-            if field_name == pk_field_name: continue
-            if field_name not in attributes: continue
-            raw_field_value = attributes[field_name]
-            field_class : 'Field' = getattr(model_class, field_name)
-            field_value = field_class.deserialize(raw_field_value)
-            setattr(self, field_name, field_value)
+        pk_field_name = self._pk_field_name # pylint: disable=no-member
 
-        self.unlock()
+        try:
+            self.lock()
+
+            attributes = self._backend.dict_get(self._instance_key)
+            if attributes is None: return
+            for field_name in self._field_names_list: # pylint: disable=no-member
+                if field_name == pk_field_name: continue
+                if field_name not in attributes: continue
+                raw_field_value = attributes[field_name]
+                field_instance : 'Field' = getattr(self._model_class, field_name)
+                field_value = field_instance.deserialize(raw_field_value)
+                if isinstance(field_instance, ForeignKeyField):
+                    setattr(self, field_name + '_stored', field_value)
+                    field_value = field_instance.foreign_model(self._database, field_value, auto_load=True)
+                setattr(self, field_name, field_value)
+        finally:
+            self.unlock()
 
     def save(self) -> None:
-        model_class = type(self)
-
         attributes : Dict[str, Any] = dict()
         required_keys : Set[str] = set()
         foreign_additions : Dict[str, str] = dict()
         foreign_removals : Dict[str, str] = dict()
         for field_name in self._field_names_list: # pylint: disable=no-member
-            field_value = str(getattr(self, field_name))
-            field_instance : 'Field' = getattr(model_class, field_name)
+            field_value = getattr(self, field_name)
+            field_instance : 'Field' = getattr(self._model_class, field_name)
             serialized_field_value = field_instance.serialize(field_value)
+            if serialized_field_value is None:
+                if not field_instance.required: continue
+                msg = 'Attribute({}) is required.'
+                raise AttributeError(msg.format(str(field_instance.name)))
             if isinstance(field_instance, ForeignKeyField):
-                foreign_reference = '{:s}:{:s}'.format(self._backend_key, field_name)
+                foreign_reference = '{:s}:{:s}'.format(self._instance_key, field_name)
                 field_value_stored = getattr(self, field_name + '_stored', None)
                 if field_value_stored is not None:
                     foreign_removals[key_to_str([field_value_stored, 'references'])] = foreign_reference
@@ -119,32 +127,21 @@ class Model(metaclass=MetaModel):
                 required_keys.add(serialized_field_value)
             attributes[field_name] = serialized_field_value
 
-        if len(self._backend_parent_key) > 0:
-            required_keys.add(self._backend_parent_key)
-
         extra_keys = []
         extra_keys.extend(list(foreign_removals.keys()))
         extra_keys.extend(list(foreign_additions.keys()))
 
-        print('self._backend_key', self._backend_key)
-        print('extra_keys', extra_keys)
-        print('attributes', attributes)
-        print('foreign_removals', foreign_removals)
-        print('foreign_additions', foreign_additions)
-
         try:
-            print('dump_before', self._backend.dump())
             self.lock(extra_keys=extra_keys)
-            print('dump_after', self._backend.dump())
 
             not_exists = []
             for required_key in required_keys:
                 if self._backend.exists(required_key): continue
                 not_exists.append('{:s}'.format(str(required_key)))
             if len(not_exists) > 0:
-                raise ValueError('Required Keys ({:s}) does not exist'.format(', '.join(sorted(not_exists))))
+                raise ConstraintException('Required Keys ({:s}) does not exist'.format(', '.join(sorted(not_exists))))
 
-            self._backend.dict_update(self._backend_key, attributes)
+            self._backend.dict_update(self._instance_key, attributes)
             for serialized_field_value,foreign_reference in foreign_removals.items():
                 self._backend.set_remove(serialized_field_value, foreign_reference)
 
@@ -157,9 +154,30 @@ class Model(metaclass=MetaModel):
             setattr(self, (foreign_reference.split(':')[-1]) + '_stored', field_value_stored)
 
     def delete(self) -> None:
-        self.lock()
-        self._backend.delete(self._backend_key)
-        self.unlock()
+        foreign_removals : Dict[str, str] = {}
+        for field_name in self._field_names_list: # pylint: disable=no-member
+            field_instance : 'Field' = getattr(self._model_class, field_name)
+            if not isinstance(field_instance, ForeignKeyField): continue
+            foreign_reference = '{:s}:{:s}'.format(self._instance_key, field_name)
+            field_value_stored = getattr(self, field_name + '_stored', None)
+            if field_value_stored is None: continue
+            foreign_removals[key_to_str([field_value_stored, 'references'])] = foreign_reference
+
+        extra_keys = []
+        extra_keys.extend(list(foreign_removals.keys()))
+
+        try:
+            self.lock(extra_keys=extra_keys)
+
+            if self._backend.exists(self._references_key):
+                references = self._backend.set_get_all(self._references_key)
+                raise ConstraintException('Instance is used by Keys ({:s})'.format(', '.join(sorted(references))))
+
+            self._backend.delete(self._instance_key)
+            for serialized_field_value,foreign_reference in foreign_removals.items():
+                self._backend.set_remove(serialized_field_value, foreign_reference)
+        finally:
+            self.unlock(extra_keys=extra_keys)
 
     def dump_id(self) -> Dict:
         raise NotImplementedError()
@@ -168,8 +186,7 @@ class Model(metaclass=MetaModel):
         raise NotImplementedError()
 
     def __repr__(self) -> str:
-        pk_field = self._primary_key_field # pylint: disable=no-member
-        pk_field_name = None if pk_field is None else pk_field.name # pylint: disable=no-member
+        pk_field_name = self._pk_field_name # pylint: disable=no-member
         arguments = ', '.join(
             '{:s}={:s}{:s}'.format(
                 name, repr(getattr(self, name)), '(PK)' if name == pk_field_name else '')
diff --git a/src/common/orm/tests/test_unitary_orm.py b/src/common/orm/tests/test_unitary_orm.py
index 7ae5a1a79363aab2728a790cc35e32cbbcf23355..a03a1051206e1062e1c8f27d665e107bc968fdf8 100644
--- a/src/common/orm/tests/test_unitary_orm.py
+++ b/src/common/orm/tests/test_unitary_orm.py
@@ -1,43 +1,64 @@
 import logging, pytest
-from common.orm._Database import _Database
+from common.orm.Exceptions import ConstraintException
+from common.orm.Database import Database
 from common.orm.backend._Backend import _Backend
-from common.orm.backend.inmemory.InMemoryBackend import LOGGER, InMemoryBackend
+from common.orm.backend.inmemory.InMemoryBackend import InMemoryBackend
 from common.orm.fields.BooleanField import BooleanField
 from common.orm.fields.FloatField import FloatField
 from common.orm.fields.ForeignKeyField import ForeignKeyField
 from common.orm.fields.IntegerField import IntegerField
 from common.orm.fields.PrimaryKeyField import PrimaryKeyField
 from common.orm.fields.StringField import StringField
-from common.orm.model.Model import Model
+from common.orm.model.Model import DEFAULT_PRIMARY_KEY_NAME, Model
 
 logging.basicConfig(level=logging.INFO)
+LOGGER = logging.getLogger(__name__)
 
 def test_database_instantiation():
     with pytest.raises(AttributeError) as e:
-        _Database(None)
+        Database(None)
     str_class_path = '{}.{}'.format(_Backend.__module__, _Backend.__name__)
     assert str(e.value) == 'backend must inherit from {}'.format(str_class_path)
 
-    assert _Database(InMemoryBackend()) is not None
+    assert Database(InMemoryBackend()) is not None
 
 def test_model_without_attributes():
     with pytest.raises(AttributeError) as e:
         Model(None, 'valid-uuid')
-    str_class_path = '{}.{}'.format(Model.__module__, Model.__name__)
-    assert str(e.value) == 'parent must inherit from {}'.format(str_class_path)
+    str_class_path = '{}.{}'.format(Database.__module__, Database.__name__)
+    assert str(e.value) == 'database must inherit from {}'.format(str_class_path)
 
-    database = _Database(InMemoryBackend())
+    database = Database(InMemoryBackend())
 
-    with pytest.raises(AttributeError) as e:
+    with pytest.raises(ValueError) as e:
         Model(database, '')
-    assert str(e.value) == 'Unable to set primary_key() since no PrimaryKeyField is defined in the model'
+    msg = '{:s}() is out of range: allow_empty(False).'
+    assert str(e.value) == msg.format(DEFAULT_PRIMARY_KEY_NAME)
 
-    with pytest.raises(AttributeError) as e:
-        Model(database, 'primary-key')
-    assert str(e.value) == 'Unable to set primary_key(primary-key) since no PrimaryKeyField is defined in the model'
+    with pytest.raises(TypeError) as e:
+        Model(database, 23)
+    msg = '{:s}(23) is of a wrong type(int). Accepted type_or_types(<class \'str\'>).'
+    assert str(e.value) == msg.format(DEFAULT_PRIMARY_KEY_NAME)
+
+    with pytest.raises(TypeError) as e:
+        Model(database, 23.5)
+    msg = '{:s}(23.5) is of a wrong type(float). Accepted type_or_types(<class \'str\'>).'
+    assert str(e.value) == msg.format(DEFAULT_PRIMARY_KEY_NAME)
+    
+    with pytest.raises(TypeError) as e:
+        Model(database, True)
+    msg = '{:s}(True) is of a wrong type(bool). Accepted type_or_types(<class \'str\'>).'
+    assert str(e.value) == msg.format(DEFAULT_PRIMARY_KEY_NAME)
+
+    with pytest.raises(TypeError) as e:
+        Model(database, ['a'])
+    msg = '{:s}([\'a\']) is of a wrong type(list). Accepted type_or_types(<class \'str\'>).'
+    assert str(e.value) == msg.format(DEFAULT_PRIMARY_KEY_NAME)
+
+    Model(database, 'valid-primary-key')
 
 def test_model_with_primarykey():
-    database = _Database(InMemoryBackend())
+    database = Database(InMemoryBackend())
 
     with pytest.raises(AttributeError) as e:
         class WrongTestModel(Model): # pylint: disable=unused-variable
@@ -47,7 +68,7 @@ def test_model_with_primarykey():
             salary = FloatField(min_value=0.0)
             active = BooleanField()
             pk2 = PrimaryKeyField()
-    assert str(e.value) == 'PrimaryKey for Model(WrongTestModel) already set to attribute(pk)'
+    assert str(e.value) == 'PrimaryKeyField for Model(WrongTestModel) already set to attribute(pk)'
 
     class TestModel(Model):
         pk = PrimaryKeyField()
@@ -57,8 +78,8 @@ def test_model_with_primarykey():
         active = BooleanField()
 
     with pytest.raises(ValueError) as e:
-        TestModel(database)
-    assert str(e.value) == 'pk(None) is None.'
+        TestModel(database, None)
+    assert str(e.value) == 'pk(None) is required. It cannot be None.'
 
     with pytest.raises(ValueError) as e:
         TestModel(database, '')
@@ -72,7 +93,7 @@ def test_model_with_primarykey():
     assert str(e.value) == 'PrimaryKeyField cannot be modified'
 
 def test_model_with_primarykey_and_attributes():
-    database = _Database(InMemoryBackend())
+    database = Database(InMemoryBackend())
 
     class TestModel(Model):
         pk = PrimaryKeyField()
@@ -144,7 +165,7 @@ def test_model_with_primarykey_and_attributes():
     assert repr(obj) == "TestModel(pk='valid-pk'(PK), name='John Smith', age=37, salary=5023.52, active=True)"
 
 def test_model_database_operations():
-    database = _Database(InMemoryBackend())
+    database = Database(InMemoryBackend())
 
     class TestModel(Model):
         pk = PrimaryKeyField()
@@ -166,8 +187,8 @@ def test_model_database_operations():
 
     database_dump = database.dump()
     assert len(database_dump) == 1
-    db_entry_repr = '[dict] /TestModel[valid-pk]'\
-                    '                                                                                 '\
+    db_entry_repr = '[dict] TestModel[valid-pk]'\
+                    '                                                                                  '\
                     ':: {\'pk\': \'valid-pk\', \'name\': \'John Smith\', \'age\': \'37\', \'salary\': \'5023.52\', '\
                     '\'active\': \'True\'}'
     assert database_dump[0] == db_entry_repr
@@ -187,21 +208,22 @@ def test_model_database_operations():
     database.clear_all()
     assert len(database.dump()) == 0
 
-def test_model_with_foreignkeys():
-    database = _Database(InMemoryBackend())
+def test_model_foreignkeys():
+    database = Database(InMemoryBackend())
 
     class Team(Model):
         pk = PrimaryKeyField()
-        name = StringField(max_length=10)
+        name = StringField(max_length=10, required=True)
 
     class Workplace(Model):
         pk = PrimaryKeyField()
-        name = StringField(max_length=10)
+        name = StringField(max_length=10, required=True)
 
     class Member(Model):
         pk = PrimaryKeyField()
-        place = ForeignKeyField(Workplace)
-        name = StringField(max_length=10)
+        team = ForeignKeyField(Team)
+        place = ForeignKeyField(Workplace, required=False)
+        name = StringField(max_length=10, required=True)
 
     team_dev_ops = Team(database, 'dev-ops')
     team_dev_ops.name = 'Dev Ops'
@@ -213,35 +235,200 @@ def test_model_with_foreignkeys():
     assert workplace_bcn is not None
     assert repr(workplace_bcn) == "Workplace(pk='bcn'(PK), name='Barcelona')"
 
-    member_john = Member(team_dev_ops, 'john')
+    member_john = Member(database, 'john')
     member_john.name = 'John'
+    member_john.team = team_dev_ops
     member_john.place = workplace_bcn
     assert member_john is not None
-    assert repr(member_john) == "Member(pk='john'(PK), place='/Workplace[bcn]', name='John')"
+    assert repr(member_john) == "Member(pk='john'(PK), team='Team[dev-ops]', place='Workplace[bcn]', name='John')"
 
-    with pytest.raises(ValueError) as e:
+    database_dump = database.dump()
+    LOGGER.info('----- Database Dump: -----')
+    for database_entry in database_dump:
+        LOGGER.info('  ' + database_entry)
+    LOGGER.info('--------------------------')
+
+    with pytest.raises(ConstraintException) as e:
         member_john.save()
-    assert str(e.value) == 'Required Keys (/Team[dev-ops], /Workplace[bcn]) does not exist'
+    assert str(e.value) == 'Required Keys (Team[dev-ops], Workplace[bcn]) does not exist'
 
     workplace_bcn.save()
+    assert repr(Workplace(database, workplace_bcn.pk)) == "Workplace(pk='bcn'(PK), name='Barcelona')"
 
-    with pytest.raises(ValueError) as e:
+    with pytest.raises(ConstraintException) as e:
         member_john.save()
-    assert str(e.value) == 'Required Keys (/Team[dev-ops]) does not exist'
+    assert str(e.value) == 'Required Keys (Team[dev-ops]) does not exist'
 
     team_dev_ops.save()
+    assert repr(Team(database, team_dev_ops.pk)) == "Team(pk='dev-ops'(PK), name='Dev Ops')"
+
     member_john.save()
+    str_member = "Member(pk='john'(PK), team='Team[dev-ops]', place='Workplace[bcn]', name='John')"
+    assert repr(Member(database, member_john.pk)) == str_member
+
+    with pytest.raises(ConstraintException) as e:
+        workplace_bcn.delete()
+    assert str(e.value) == 'Instance is used by Keys (Member[john]:place)'
+
+    with pytest.raises(ConstraintException) as e:
+        team_dev_ops.delete()
+    assert str(e.value) == 'Instance is used by Keys (Member[john]:team)'
+
+    workplace_mad = Workplace(database, 'mad')
+    workplace_mad.name = 'Madrid'
+    assert workplace_mad is not None
+    assert repr(workplace_mad) == "Workplace(pk='mad'(PK), name='Madrid')"
+
+    member_john = Member(database, 'john')
+    member_john.name = 'John'
+    member_john.place = workplace_mad
+    assert member_john is not None
+    assert repr(member_john) == "Member(pk='john'(PK), team='Team[dev-ops]', place='Workplace[mad]', name='John')"
+
+    member_tom = Member(database, 'tom')
+    member_tom.name = 'Tom'
+    member_tom.place = workplace_mad
+    assert member_tom is not None
+    assert repr(member_tom) == "Member(pk='tom'(PK), team=None, place='Workplace[mad]', name='Tom')"
+
+    with pytest.raises(ConstraintException) as e:
+        member_tom.save()
+    assert str(e.value) == 'ForeignKey(team, None) is required. It cannot be serialized as empty.'
+
+    member_tom.team = team_dev_ops
+    
+    with pytest.raises(ConstraintException) as e:
+        member_john.save()
+    assert str(e.value) == 'Required Keys (Workplace[mad]) does not exist'
+
+    workplace_mad.save()
+    assert repr(Workplace(database, workplace_mad.pk)) == "Workplace(pk='mad'(PK), name='Madrid')"
+
+    member_tom.save()
+    str_member = "Member(pk='tom'(PK), team='Team[dev-ops]', place='Workplace[mad]', name='Tom')"
+    assert repr(Member(database, member_tom.pk)) == str_member
+
+    member_john = Member(database, 'john')
+
+    with pytest.raises(ConstraintException) as e:
+        del member_john.place
+        del member_john.team
+    assert str(e.value) == 'ForeignKey(team) is required. Unable to clear it.'
+
+    member_brad = Member(database, 'brad')
+    assert member_brad is not None
+    assert repr(member_brad) == "Member(pk='brad'(PK), team=None, place=None, name=None)"
+
+    with pytest.raises(ConstraintException) as e:
+        member_brad.save()
+    assert str(e.value) == 'ForeignKey(team, None) is required. It cannot be serialized as empty.'
+
+    member_brad.team = team_dev_ops
+
+    with pytest.raises(ValueError) as e:
+        member_brad.save()
+    assert str(e.value) == 'name(None) is required. It cannot be None.'
+
+    member_brad.name = 'Brad'
+    assert repr(member_brad) == "Member(pk='brad'(PK), team=\'Team[dev-ops]\', place=None, name='Brad')"
+
+    member_brad.save()
+    str_member = "Member(pk='brad'(PK), team='Team[dev-ops]', place=None, name='Brad')"
+    assert repr(Member(database, member_brad.pk)) == str_member
+
+    team_admin = Team(database, 'admin')
+    team_admin.name = 'Admin'
+    team_admin.save()
+    assert repr(Team(database, team_admin.pk)) == "Team(pk='admin'(PK), name='Admin')"
+
+    member_brad = Member(database, member_brad.pk)
+    str_member = "Member(pk='brad'(PK), team='Team[dev-ops]', place=None, name='Brad')"
+    assert repr(member_brad) == str_member
+    member_brad.team = team_admin
+    str_member = "Member(pk='brad'(PK), team='Team[admin]', place=None, name='Brad')"
+    assert repr(member_brad) == str_member
+    member_brad.save()
+    str_member = "Member(pk='brad'(PK), team='Team[admin]', place=None, name='Brad')"
+    assert repr(Member(database, member_brad.pk)) == str_member
 
     database_dump = database.dump()
     LOGGER.info('----- Database Dump: -----')
     for database_entry in database_dump:
         LOGGER.info('  ' + database_entry)
     LOGGER.info('--------------------------')
-    #assert len(database_dump) == 1
-    raise Exception()
 
+    assert len(database_dump) == 11
+    spaces = '                                                                            '
+    db_entry_repr_00 = "[dict] Member[brad]             " + spaces + \
+                       ":: {'pk': 'brad', 'team': 'Team[admin]', 'name': 'Brad'}"
+    db_entry_repr_01 = "[dict] Member[john]             " + spaces + \
+                       ":: {'pk': 'john', 'team': 'Team[dev-ops]', 'place': 'Workplace[bcn]', 'name': 'John'}"
+    db_entry_repr_02 = "[dict] Member[tom]              " + spaces + \
+                       ":: {'pk': 'tom', 'team': 'Team[dev-ops]', 'place': 'Workplace[mad]', 'name': 'Tom'}"
+    db_entry_repr_03 = "[dict] Team[admin]              " + spaces + \
+                       ":: {'pk': 'admin', 'name': 'Admin'}"
+    db_entry_repr_04 = "[ set] Team[admin]/references   " + spaces + \
+                       ":: {'Member[brad]:team'}"
+    db_entry_repr_05 = "[dict] Team[dev-ops]            " + spaces + \
+                       ":: {'pk': 'dev-ops', 'name': 'Dev Ops'}"
+    db_entry_repr_06a = "[ set] Team[dev-ops]/references " + spaces + \
+                       ":: {'Member[john]:team', 'Member[tom]:team'}"
+    db_entry_repr_06b = "[ set] Team[dev-ops]/references " + spaces + \
+                       ":: {'Member[tom]:team', 'Member[john]:team'}"
+    db_entry_repr_07 = "[dict] Workplace[bcn]           " + spaces + \
+                       ":: {'pk': 'bcn', 'name': 'Barcelona'}"
+    db_entry_repr_08 = "[ set] Workplace[bcn]/references" + spaces + \
+                       ":: {'Member[john]:place'}"
+    db_entry_repr_09 = "[dict] Workplace[mad]           " + spaces + \
+                       ":: {'pk': 'mad', 'name': 'Madrid'}"
+    db_entry_repr_10 = "[ set] Workplace[mad]/references" + spaces + \
+                       ":: {'Member[tom]:place'}"
+    assert database_dump[ 0] == db_entry_repr_00
+    assert database_dump[ 1] == db_entry_repr_01
+    assert database_dump[ 2] == db_entry_repr_02
+    assert database_dump[ 3] == db_entry_repr_03
+    assert database_dump[ 4] == db_entry_repr_04
+    assert database_dump[ 5] == db_entry_repr_05
+    assert (database_dump[ 6] == db_entry_repr_06a) or (database_dump[ 6] == db_entry_repr_06b)
+    assert database_dump[ 7] == db_entry_repr_07
+    assert database_dump[ 8] == db_entry_repr_08
+    assert database_dump[ 9] == db_entry_repr_09
+    assert database_dump[10] == db_entry_repr_10
+
+    Member(database, member_tom.pk).delete()
+
+    database_dump = database.dump()
+    LOGGER.info('----- Database Dump: -----')
+    for database_entry in database_dump:
+        LOGGER.info('  ' + database_entry)
+    LOGGER.info('--------------------------')
 
-# TODO: Test remove foreign key
-# TODO: Test change foreign key
-# TODO: Test remove entity with foreign keys pointing to another entity
-# TODO: Test remove entity with primary key being pointed by another entity
+    assert len(database_dump) == 9
+    spaces = '                                                                            '
+    db_entry_repr_00 = "[dict] Member[brad]             " + spaces + \
+                       ":: {'pk': 'brad', 'team': 'Team[admin]', 'name': 'Brad'}"
+    db_entry_repr_01 = "[dict] Member[john]             " + spaces + \
+                       ":: {'pk': 'john', 'team': 'Team[dev-ops]', 'place': 'Workplace[bcn]', 'name': 'John'}"
+    db_entry_repr_02 = "[dict] Team[admin]              " + spaces + \
+                       ":: {'pk': 'admin', 'name': 'Admin'}"
+    db_entry_repr_03 = "[ set] Team[admin]/references   " + spaces + \
+                       ":: {'Member[brad]:team'}"
+    db_entry_repr_04 = "[dict] Team[dev-ops]            " + spaces + \
+                       ":: {'pk': 'dev-ops', 'name': 'Dev Ops'}"
+    db_entry_repr_05 = "[ set] Team[dev-ops]/references " + spaces + \
+                       ":: {'Member[john]:team'}"
+    db_entry_repr_06 = "[dict] Workplace[bcn]           " + spaces + \
+                       ":: {'pk': 'bcn', 'name': 'Barcelona'}"
+    db_entry_repr_07 = "[ set] Workplace[bcn]/references" + spaces + \
+                       ":: {'Member[john]:place'}"
+    db_entry_repr_08 = "[dict] Workplace[mad]           " + spaces + \
+                       ":: {'pk': 'mad', 'name': 'Madrid'}"
+    assert database_dump[ 0] == db_entry_repr_00
+    assert database_dump[ 1] == db_entry_repr_01
+    assert database_dump[ 2] == db_entry_repr_02
+    assert database_dump[ 3] == db_entry_repr_03
+    assert database_dump[ 4] == db_entry_repr_04
+    assert database_dump[ 5] == db_entry_repr_05
+    assert database_dump[ 6] == db_entry_repr_06
+    assert database_dump[ 7] == db_entry_repr_07
+    assert database_dump[ 8] == db_entry_repr_08
diff --git a/src/common/type_checkers/Checkers.py b/src/common/type_checkers/Checkers.py
index b3693d87d29dc2a9c34343bfb8eb1cc69d1c2381..8c6231aaaca758b8cacea039878cac5fb2b93205 100644
--- a/src/common/type_checkers/Checkers.py
+++ b/src/common/type_checkers/Checkers.py
@@ -1,15 +1,15 @@
 import re
 from typing import Any, Container, List, Optional, Pattern, Set, Sized, Tuple, Union
 
-def chk_none(name : str, value : Any) -> Any:
+def chk_none(name : str, value : Any, reason=None) -> Any:
     if value is None: return value
-    msg = '{}({}) is not None.'
-    raise ValueError(msg.format(str(name), str(value)))
+    if reason is None: reason = 'must be None.'
+    raise ValueError('{}({}) {}'.format(str(name), str(value), str(reason)))
 
-def chk_not_none(name : str, value : Any) -> Any:
+def chk_not_none(name : str, value : Any, reason=None) -> Any:
     if value is not None: return value
-    msg = '{}({}) is None.'
-    raise ValueError(msg.format(str(name), str(value)))
+    if reason is None: reason = 'must not be None.'
+    raise ValueError('{}({}) {}'.format(str(name), str(value), str(reason)))
 
 def chk_type(name : str, value : Any, type_or_types : Union[type, Set[type]] = set()) -> Any:
     if isinstance(value, type_or_types): return value