diff --git a/src/Adapter/AdapterInterface.php b/src/Adapter/AdapterInterface.php
index ec8e6aa..d0ca171 100644
--- a/src/Adapter/AdapterInterface.php
+++ b/src/Adapter/AdapterInterface.php
@@ -9,8 +9,9 @@ interface AdapterInterface {
     public const IDENTIFIER_TABLE = 2;
     public const IDENTIFIER_DATABASE = 3;
     public const IDENTIFIER_SCHEMA = 4;
+    public const IDENTIFIER_VALUE = 5;
     
-    public function connect() : PdoObject;
+    public function connect() : object /* | PdoObject|mixed */;
     public function buildDataSourceName() : string;
     public function setup(array $configuration) : void;
     public function escapeIdentifier(string $segment, int $type) : string;
diff --git a/src/Adapter/MsSQL.php b/src/Adapter/MsSQL.php
index ade60fc..5d84ee7 100644
--- a/src/Adapter/MsSQL.php
+++ b/src/Adapter/MsSQL.php
@@ -194,6 +194,9 @@ class MsSQL implements AdapterInterface {
             case static::IDENTIFIER_TABLE:
             case static::IDENTIFIER_FIELD:
                 return "[" . str_replace(["[", "]"], [ "[[", "]]" ], $segment) . "]";
+
+            case static::IDENTIFIER_VALUE:
+                return "'$segment'";
         }
     }
 
diff --git a/src/Adapter/MySQL.php b/src/Adapter/MySQL.php
index e033103..910c162 100644
--- a/src/Adapter/MySQL.php
+++ b/src/Adapter/MySQL.php
@@ -131,6 +131,9 @@ class MySQL implements AdapterInterface {
             case static::IDENTIFIER_TABLE:
             case static::IDENTIFIER_FIELD:
                 return "`" . str_replace("`", "``", $segment) . "`";
+
+            case static::IDENTIFIER_VALUE:
+                return "\"$segment\"";
         }
     }
 
diff --git a/src/Annotation/Property/Field/Bigint.php b/src/Annotation/Property/Field/Bigint.php
new file mode 100644
index 0000000..01b49ac
--- /dev/null
+++ b/src/Annotation/Property/Field/Bigint.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Ulmus\Annotation\Property\Field;
+
+class Bigint extends \Ulmus\Annotation\Property\Field
+{
+    public function __construct(? string $type = "bigint", ? int $length = null)
+    {
+        parent::__construct($type, $length);
+    }
+}
\ No newline at end of file
diff --git a/src/Annotation/Property/Field/Longtext.php b/src/Annotation/Property/Field/Longtext.php
new file mode 100644
index 0000000..b15a14a
--- /dev/null
+++ b/src/Annotation/Property/Field/Longtext.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Ulmus\Annotation\Property\Field;
+
+class Longtext extends \Ulmus\Annotation\Property\Field
+{
+    public function __construct(? string $type = "longtext", ? int $length = null)
+    {
+        parent::__construct($type, $length);
+    }
+}
\ No newline at end of file
diff --git a/src/Annotation/Property/Field/Mediumtext.php b/src/Annotation/Property/Field/Mediumtext.php
new file mode 100644
index 0000000..ac7654f
--- /dev/null
+++ b/src/Annotation/Property/Field/Mediumtext.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Ulmus\Annotation\Property\Field;
+
+class Mediumtext extends \Ulmus\Annotation\Property\Field
+{
+    public function __construct(? string $type = "mediumtext", ? int $length = null)
+    {
+        parent::__construct($type, $length);
+    }
+}
\ No newline at end of file
diff --git a/src/Annotation/Property/Field/Text.php b/src/Annotation/Property/Field/Text.php
new file mode 100644
index 0000000..fb7843f
--- /dev/null
+++ b/src/Annotation/Property/Field/Text.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Ulmus\Annotation\Property\Field;
+
+class Text extends \Ulmus\Annotation\Property\Field
+{
+    public function __construct(? string $type = "text", ? int $length = null)
+    {
+        parent::__construct($type, $length);
+    }
+}
\ No newline at end of file
diff --git a/src/Annotation/Property/Field/Tinyint.php b/src/Annotation/Property/Field/Tinyint.php
new file mode 100644
index 0000000..59ef127
--- /dev/null
+++ b/src/Annotation/Property/Field/Tinyint.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Ulmus\Annotation\Property\Field;
+
+class Tinyint extends \Ulmus\Annotation\Property\Field
+{
+    public function __construct(? string $type = "tinyint", ? int $length = null)
+    {
+        parent::__construct($type, $length);
+    }
+}
\ No newline at end of file
diff --git a/src/Annotation/Property/Relation.php b/src/Annotation/Property/Relation.php
index d472147..258f257 100644
--- a/src/Annotation/Property/Relation.php
+++ b/src/Annotation/Property/Relation.php
@@ -17,7 +17,7 @@ class Relation implements \Ulmus\Annotation\Annotation {
     public /*stringable*/ $bridgeKey;
 
     public /*stringable*/ $bridgeForeignKey;
-    
+
     public string $entity;
 
     public string $join;
@@ -30,20 +30,20 @@ class Relation implements \Ulmus\Annotation\Annotation {
             $this->type = $type;
         }
     }
-    
+
     public function entity() {
         try {
-            $e = $this->entity;        
+            $e = $this->entity;
         } catch (\Throwable $ex) {
             throw new \Exception("Your @Relation annotation seems to be missing an `entity` entry.");
         }
-        
+
         return new $e();
     }
-    
+
     public function bridge() {
         $e = $this->bridge;
-        
+
         return new $e();
     }
 
@@ -51,4 +51,24 @@ class Relation implements \Ulmus\Annotation\Annotation {
     {
         return strtolower(str_replace(['-', '_', ' '], '', $this->type));
     }
+
+    public function isOneToOne() : bool
+    {
+        return $this->normalizeType() === 'onetoone';
+    }
+
+    public function isOneToMany() : bool
+    {
+        return $this->normalizeType() === 'onetomany';
+    }
+
+    public function isManyToMany() : bool
+    {
+        return $this->normalizeType() === 'manytomany';
+    }
+
+    public function hasBridge() : bool
+    {
+        return isset($this->bridge);
+    }
 }
diff --git a/src/Annotation/Property/Relation/Ignore.php b/src/Annotation/Property/Relation/Ignore.php
new file mode 100644
index 0000000..0b6ef93
--- /dev/null
+++ b/src/Annotation/Property/Relation/Ignore.php
@@ -0,0 +1,5 @@
+<?php
+
+namespace Ulmus\Annotation\Property\Relation;
+
+class Ignore implements \Ulmus\Annotation\Annotation {}
diff --git a/src/Annotation/Property/Where.php b/src/Annotation/Property/Where.php
index 622179c..7affbd7 100644
--- a/src/Annotation/Property/Where.php
+++ b/src/Annotation/Property/Where.php
@@ -14,7 +14,7 @@ class Where implements \Ulmus\Annotation\Annotation {
 
     public string $condition;
     
-    public function __construct(? string $field = null, $value = null, ? string $operator = null, ? string $condition = null)
+    public function __construct(/* ? Stringable */ $field = null, $value = null, ? string $operator = null, ? string $condition = null)
     {
         if ( $field !== null ) {
             $this->field = $field;
diff --git a/src/Annotation/Property/WithJoin.php b/src/Annotation/Property/WithJoin.php
new file mode 100644
index 0000000..ff582b0
--- /dev/null
+++ b/src/Annotation/Property/WithJoin.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Ulmus\Annotation\Property;
+
+class WithJoin implements \Ulmus\Annotation\Annotation {
+
+    protected array $joins;
+
+    public function __construct(/*Stringable|array|null*/ $joins = null)
+    {
+        if ( $joins ) {
+            $this->joins = (array)$joins;
+        }
+    }
+}
diff --git a/src/Common/EntityField.php b/src/Common/EntityField.php
index fd07f76..c0f72c9 100644
--- a/src/Common/EntityField.php
+++ b/src/Common/EntityField.php
@@ -32,7 +32,7 @@ class EntityField
         
         $name = $this->entityResolver->databaseAdapter()->adapter()->escapeIdentifier($name, AdapterInterface::IDENTIFIER_FIELD);
 
-        return $useAlias ? "{$this->alias}.$name" : $name;
+        return $useAlias && $this->alias ? "{$this->alias}.$name" : $name;
     }
 
     public static function isScalarType($type) : bool
diff --git a/src/Common/EntityResolver.php b/src/Common/EntityResolver.php
index 5e6a952..3dc23fc 100644
--- a/src/Common/EntityResolver.php
+++ b/src/Common/EntityResolver.php
@@ -15,6 +15,8 @@ class EntityResolver {
     
     const KEY_COLUMN_NAME = 02;
 
+    const KEY_LC_ENTITY_NAME = 03;
+
     public string $entityClass;
 
     public array $uses;
@@ -64,6 +66,11 @@ class EntityResolver {
                     }
                     
                     switch($fieldKey) {
+                        case static::KEY_LC_ENTITY_NAME:
+                            $key = strtolower($item['name']);
+                            break;
+
+
                         case static::KEY_ENTITY_NAME:
                             $key = $item['name'];
                         break;
@@ -158,12 +165,12 @@ class EntityResolver {
         return $this->tableAnnotation(false)->database ?? $this->databaseAdapter()->adapter()->database;
     }
 
-    public function databaseAdapter() : \Ulmus\ConnectionAdapter
+    public function sqlAdapter() : \Ulmus\ConnectionAdapter
     {
         if ( null !== $table = $this->getAnnotationFromClassname( Table::class ) ) {
             if ( $table->adapter ?? null ) {
                 if ( null === ( $adapter = \Ulmus\Ulmus::$registeredAdapters[$table->adapter] ?? null ) ) {
-                    throw new \Exception("Requested database adapter ( {$table->adapter} ) is not registered.");
+                    throw new \Exception("Requested database adapter `{$table->adapter}` is not registered.");
                 }
                 else {
                     return $adapter;
@@ -174,6 +181,14 @@ class EntityResolver {
         return Ulmus::$defaultAdapter;
     }
 
+    /**
+     * Alias of sqlAdapter
+     */
+    public function databaseAdapter() : \Ulmus\ConnectionAdapter
+    {
+        return $this->sqlAdapter();
+    }
+
     public function schemaName(bool $required = false) : ? string
     {
         if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
diff --git a/src/ConnectionAdapter.php b/src/ConnectionAdapter.php
index 617b2c2..2964efe 100644
--- a/src/ConnectionAdapter.php
+++ b/src/ConnectionAdapter.php
@@ -65,6 +65,11 @@ class ConnectionAdapter
         return $this->pdo ?? $this->pdo = $this->connect()->pdo;
     }
 
+    public function connector() : object
+    {
+        return $this->pdo();
+    }
+
     /**
      * Instanciate an adapter which interact with the data source
      * @param  string $name An Ulmus adapter or full class name implementing AdapterInterface
diff --git a/src/EntityCollection.php b/src/EntityCollection.php
index e490113..478058b 100644
--- a/src/EntityCollection.php
+++ b/src/EntityCollection.php
@@ -233,7 +233,6 @@ class EntityCollection extends \ArrayObject {
 
     public function fromArray(array $datasets, ? string /*stringable*/ $entityClass = null) : self
     {
-
         foreach($datasets as $dataset) {
             $this->append( $this->arrayToEntity($dataset, $entityClass) );
         }
@@ -247,7 +246,7 @@ class EntityCollection extends \ArrayObject {
             throw new \Exception("An entity class name must be provided to be instanciated and populated before insertion into this collection.");
         }
 
-        $className = $this->entityClass;
+        $className = $entityClass ?: $this->entityClass;
 
         return ( new $className() )->fromArray($dataset);
     }
@@ -318,4 +317,9 @@ class EntityCollection extends \ArrayObject {
     {
         return $this->replaceWith(array_reverse($this->getArrayCopy()));;
     }
+
+    public function slice(int $offset, ? int $length = null) : self
+    {
+        return new self(array_slice($this->getArrayCopy(), $offset, $length));
+    }
 }
diff --git a/src/EntityTrait.php b/src/EntityTrait.php
index e7e2e74..842c21e 100644
--- a/src/EntityTrait.php
+++ b/src/EntityTrait.php
@@ -8,8 +8,9 @@ use Ulmus\Repository,
     Ulmus\Common\EntityField;
 
 use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
-use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual, On, };
-use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, };
+use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual, On, WithJoin, };
+use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Text, Mediumtext, Longtext, };
+use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore };
 
 trait EntityTrait {
     use EventTrait;
@@ -28,174 +29,18 @@ trait EntityTrait {
      * @Ignore
      */
     public array $entityLoadedDataset = [];
-    
+
     /**
      * @Ignore
      */
     public function __get(string $name)
     {
-        $entityResolver =  $this->resolveEntity();
-
-        # Resolve relations here if one is called
-
-        # @TODO REFACTOR THIS CODE ASAP !
-        if ( $this->isLoaded() ) {
-            $annotation = $entityResolver->searchFieldAnnotation($name, new Annotation\Property\Join) ?:
-                $entityResolver->searchFieldAnnotation($name, new Annotation\Property\Relation);
-
-            if ( $annotation ) {
-                $vars = [];
-
-                $len = strlen( $name ) + 1;
-
-                foreach($this->entityDatasetUnmatchedFields as $key => $value) {
-                    if ( substr($key, 0, $len ) === "{$name}$" ) {
-                        $vars[substr($key, $len)] = $value;
-                    }
-                }
-
-                if ( [] !== $data = (array_values(array_unique($vars)) !== [ null ] ? $vars : []) ) {
-                    $entity = $annotation->entity ?? $entityResolver->properties[$name]['type'];
-
-                    return $this->$name = ( new $entity() )->fromArray($data)->resetVirtualProperties();
-                }
-            }
-            
-            if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
-                $order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
-                $where = $entityResolver->searchFieldAnnotationList($name, new Where() );
-                $filters = $entityResolver->searchFieldAnnotationList($name, new Filter() );
-
-                $baseEntity = $relation->entity ?? $relation->bridge ?? $entityResolver->properties[$name]['type'];
-                $repository = $baseEntity::repository()->open();
-
-                foreach($where as $condition) {
-                    $repository->where($condition->field, is_callable($condition->value) ? call_user_func_array($condition->value, [ $this ]) : $condition->value, $condition->operator, $condition->condition);
-                }
-
-                $repository->close();
-
-                foreach ($order as $item) {
-                    $repository->orderBy($item->field, $item->order);
-                }
-                                
-                $applyFilter = function($repository) use ($filters, $name) {
-                    foreach($filters as $filter) {
-                        $repository = call_user_func_array([ $this, $filter->method ], [ $repository, $name ]);
-                    }
-                    
-                    return $repository;
-                };
-
-                $field = $relation->key;
-
-                $applyFilter = function($repository) use ($filters, $name) {
-                    foreach($filters as $filter) {
-                        $repository = call_user_func_array([ $this, $filter->method ], [ $repository, $name ]);
-                    }
-
-                    return $repository;
-                };
-
-                switch( $relation->normalizeType() ) {
-                    case 'onetoone':
-                        $repository->limit(1);
-
-                        if ($relation->foreignKey) {
-                            $repository->where( is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey), is_callable($field) ? $field($this) : $this->$field );
-                        }
-
-                        $this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
-                        
-                        $result = call_user_func([$repository, $relation->function]);
-
-                        if ( count($result) === 0 ) {
-                            return new $baseEntity();
-                        }
-
-                        return $this->$name = $result[0];
-
-                    case 'onetomany':
-                        if ($relation->foreignKey) {
-                            $repository->where( is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey), is_callable($field) ? $field($this) : $this->$field );
-                        }
-                        
-                        $this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
-
-                        return $this->$name = call_user_func([$applyFilter($repository), $relation->function]);
-
-                    case 'manytomany':
-                        if ( false === $relation->bridge ?? false ) {
-                            throw new \Exception("Your many-to-many @Relation() from variable `$name` is missing a 'bridge' value.");
-                        }
-
-                        $bridgeEntity = Ulmus::resolveEntity($relation->bridge);
-                        $bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
-                        $relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
-
-                        if ($relationRelation === null) {
-                            throw new \Exception("@Relation annotation not found for field `{$relation->foreignField}` in entity {$relation->bridge}");
-                        }
-
-                        $repository = $relationRelation->entity()->repository();
-
-                        $bridgeAlias = uniqid("bridge_");
-                        $relationAlias = uniqid("relation_");
-
-                        # @TODO Rewrite to be done here, this code must move somewhere else...
-                        $repository->select("{$repository->alias}.*")
-                            ->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName(), $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey), $bridgeAlias)
-                            ->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName(), $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias), $relationAlias)
-                            ->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} );
-
-                        $repository->open();
-
-                        foreach($where as $condition) {
-                            $repository->where($condition->field, $condition->value, $condition->operator);
-                        }
-
-                        $repository->close();
-
-                        foreach($order as $item) {
-                            $repository->orderBy($item->field, $item->order);
-                        }
-
-                        $this->eventExecute(Event\EntityRelationLoadInterface::class, $name, $repository);
-                        
-                        $this->$name = call_user_func([ $applyFilter($repository), $relationRelation->function ]);
-
-                        if ($relation->bridgeField ?? false) {
-                            $repository = $relationRelation->entity::repository();
-
-                            $repository->select("$bridgeAlias.*")
-                                ->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName(), $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey), $bridgeAlias)
-                                ->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName(), $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias), $relationAlias)
-                                ->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} );
-
-                            $repository->open();
-
-                            foreach($where as $condition) {
-                                $repository->where($condition->field, $condition->value, $condition->operator);
-                            }
-
-                            $repository->close();
-
-                            foreach($order as $item) {
-                                $repository->orderBy($item->field, $item->order);
-                            }
-
-                            $bridgeName = $relation->bridgeField;
-
-                            $this->$bridgeName = $repository->collectionFromQuery($relation->bridge);
-                        }
-
-                        return $this->$name;
-                }
-            
-                return;
-            }
+        $relation = new Repository\RelationBuilder($this);
+        
+        if ( false !== $data = $relation->searchRelation($name) ) {
+            return $this->$name = $data;
         }
-
+        
         throw new \Exception(sprintf("[%s] - Undefined variable: %s", static::class, $name));
     }
     
@@ -227,7 +72,7 @@ trait EntityTrait {
             $field = $entityResolver->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? null;
             
             if ( $field === null ) {
-                $field = $entityResolver->field($key, EntityResolver::KEY_ENTITY_NAME, false);
+                $field = $entityResolver->field(strtolower($key), EntityResolver::KEY_LC_ENTITY_NAME, false);
             }
             
             if ( $field === null ) {
@@ -261,7 +106,7 @@ trait EntityTrait {
                 elseif ( $field['type'] === 'bool' ) {
                     $this->{$field['name']} = (bool) $value;
                 }
-        
+
                 $this->{$field['name']} = $value;
             }
             elseif ( ! $field['builtin'] ) {
@@ -385,7 +230,7 @@ trait EntityTrait {
      */
     public function toCollection() : EntityCollection
     {
-        return static::entityCollection([ $this->toArray() ]);
+        return static::entityCollection([ $this ]);
     }
     
     /**
@@ -445,14 +290,6 @@ trait EntityTrait {
         return $collection;
     }
 
-    /**
-     * @Ignore
-     */
-    public static function queryBuilder() : QueryBuilder
-    {
-        return Ulmus::queryBuilder(static::class);
-    }
-
     /**
      * @Ignore
      */
diff --git a/src/Query/Create.php b/src/Query/Create.php
index bc345c5..ed7ca4b 100644
--- a/src/Query/Create.php
+++ b/src/Query/Create.php
@@ -5,7 +5,6 @@ namespace Ulmus\Query;
 use Ulmus\Annotation,
     Ulmus\Common\EntityField;
 
-
 class Create extends Fragment {
 
     const SQL_TOKEN = "CREATE TABLE";
diff --git a/src/Query/Fragment.php b/src/Query/Fragment.php
index 5dd7d23..5b83a6b 100644
--- a/src/Query/Fragment.php
+++ b/src/Query/Fragment.php
@@ -6,7 +6,7 @@ abstract class Fragment {
 
     public int $order = 0;
 
-    public abstract function render() : string;
+    public abstract function render() /*: mixed*/;
 
     protected function renderSegments(array $segments, string $glue = " ") : string
     {
diff --git a/src/Query/GroupBy.php b/src/Query/GroupBy.php
index fd969cf..feb81b0 100644
--- a/src/Query/GroupBy.php
+++ b/src/Query/GroupBy.php
@@ -11,7 +11,7 @@ class GroupBy extends Fragment {
 
     public function set(array $order) : self
     {
-        $this->groupBy = [ $order ];
+        $this->groupBy = [ $order ];
         
         return $this;
     }
diff --git a/src/Query/Having.php b/src/Query/Having.php
index 166a56a..a106e99 100644
--- a/src/Query/Having.php
+++ b/src/Query/Having.php
@@ -14,13 +14,13 @@ class Having extends Fragment {
 
     public array $conditionList;
 
-    public QueryBuilder $queryBuilder;
+    public QueryBuilderInterface $queryBuilder;
 
     public ? Having $parent = null;
 
     public string $condition = Where::CONDITION_AND;
 
-    public function __construct(? QueryBuilder $queryBuilder, $condition = Where::CONDITION_AND)
+    public function __construct(? QueryBuilderInterface $queryBuilder, $condition = Where::CONDITION_AND)
     {
         $this->queryBuilder = $queryBuilder;
         $this->condition = $condition;
@@ -70,11 +70,11 @@ class Having extends Fragment {
             public string $field;
             public string $operator;
             public string $condition;
-            public QueryBuilder $queryBuilder;
+            public QueryBuilderInterface $queryBuilder;
 
             protected string $content = "";
 
-            public function __construct(QueryBuilder $queryBuilder, string $field, $value, string $operator, string $condition, bool $not) {
+            public function __construct(QueryBuilderInterface $queryBuilder, string $field, $value, string $operator, string $condition, bool $not) {
                 $this->queryBuilder = $queryBuilder;
                 $this->field = $field;
                 $this->value = $value;
diff --git a/src/Query/Join.php b/src/Query/Join.php
index d0f9c2c..77a5e95 100644
--- a/src/Query/Join.php
+++ b/src/Query/Join.php
@@ -39,7 +39,7 @@ class Join extends Fragment
 
     public int $order = 40;
 
-    public function __construct(QueryBuilder $queryBuilder) 
+    public function __construct(QueryBuilderInterface $queryBuilder) 
     {
         $this->queryBuilder = new QueryBuilder();
         $this->queryBuilder->parent = $queryBuilder;
diff --git a/src/Query/QueryBuilderInterface.php b/src/Query/QueryBuilderInterface.php
new file mode 100644
index 0000000..9f40562
--- /dev/null
+++ b/src/Query/QueryBuilderInterface.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Ulmus\Query;
+
+interface QueryBuilderInterface
+{
+    public function push(Fragment $queryFragment) : self;
+    public function pull(Fragment $queryFragment) : self;
+    public function render(bool $skipToken = false) /* mixed */;
+    public function reset() : void;
+    public function getFragment(string $class, int $index = 0) : ? Fragment;
+    public function removeFragment(Fragment $fragment) : void;
+}
\ No newline at end of file
diff --git a/src/Query/Set.php b/src/Query/Set.php
index 07e9939..2004919 100644
--- a/src/Query/Set.php
+++ b/src/Query/Set.php
@@ -10,9 +10,9 @@ class Set extends Fragment {
     
     public array $dataset;
     
-    public QueryBuilder $queryBuilder;
+    public QueryBuilderInterface $queryBuilder;
 
-    public function __construct(QueryBuilder $queryBuilder)
+    public function __construct(QueryBuilderInterface $queryBuilder)
     {
         $this->queryBuilder = $queryBuilder;
     }
diff --git a/src/Query/Where.php b/src/Query/Where.php
index 7b24b73..d1db936 100644
--- a/src/Query/Where.php
+++ b/src/Query/Where.php
@@ -2,8 +2,6 @@
 
 namespace Ulmus\Query;
 
-use Ulmus\QueryBuilder;
-
 use Ulmus\Common\EntityField,
     Ulmus\Common\Sql;
 
@@ -24,13 +22,13 @@ class Where extends Fragment {
 
     public array $conditionList;
 
-    public QueryBuilder $queryBuilder;
+    public QueryBuilderInterface $queryBuilder;
 
     public ? Where $parent = null;
 
     public string $condition = self::CONDITION_AND;
 
-    public function __construct(? QueryBuilder $queryBuilder, $condition = self::CONDITION_AND)
+    public function __construct(? QueryBuilderInterface $queryBuilder, $condition = self::CONDITION_AND)
     {
         $this->queryBuilder = $queryBuilder;
         $this->condition = $condition;
@@ -80,11 +78,11 @@ class Where extends Fragment {
             public string $field;
             public string $operator;
             public string $condition;
-            public QueryBuilder $queryBuilder;
+            public QueryBuilderInterface $queryBuilder;
 
             protected string $content = "";
 
-            public function __construct(QueryBuilder $queryBuilder, string $field, $value, string $operator, string $condition, bool $not) {
+            public function __construct(QueryBuilderInterface $queryBuilder, string $field, $value, string $operator, string $condition, bool $not) {
                 $this->queryBuilder = $queryBuilder;
                 $this->field = $field;
                 $this->value = $value;
diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php
index 23d50c6..ec78463 100644
--- a/src/QueryBuilder.php
+++ b/src/QueryBuilder.php
@@ -2,13 +2,15 @@
 
 namespace Ulmus;
 
-class QueryBuilder
+use Ulmus\Query\QueryBuilderInterface;
+
+class QueryBuilder implements Query\QueryBuilderInterface
 {
     public Query\Where $where;
 
     public Query\Having $having;
     
-    public QueryBuilder $parent;
+    public QueryBuilderInterface $parent;
     
     /**
      * Those are the parameters we are going to bind to PDO.
@@ -371,7 +373,7 @@ class QueryBuilder
         return array_shift($this->queryStack);
     }
 
-    public function render(bool $skipToken = false) : string
+    public function render(bool $skipToken = false) /* : mixed */
     {
         $sql = [];
 
@@ -396,11 +398,13 @@ class QueryBuilder
         unset($this->where, $this->having);
     }
 
-    public function getFragment(string $class) : ? Query\Fragment
+    public function getFragment(string $class, int $index = 0) : ? Query\Fragment
     {
         foreach($this->queryStack as $item) {
             if ( get_class($item) === $class ) {
-                return $item;
+                if ( $index-- === 0 ) {
+                    return $item;
+                }
             }
         }
 
diff --git a/src/Repository.php b/src/Repository.php
index db8e757..0e54639 100644
--- a/src/Repository.php
+++ b/src/Repository.php
@@ -2,7 +2,7 @@
 
 namespace Ulmus;
 
-use Ulmus\Annotation\Property\{ Where, Having, Relation, Join };
+use Ulmus\Annotation\Property\{ Where, Having, Relation, Join, WithJoin, Relation\Ignore as RelationIgnore };
 use Ulmus\Common\EntityResolver;
 
 class Repository
@@ -13,7 +13,7 @@ class Repository
 
     public ? ConnectionAdapter $adapter;
 
-    protected QueryBuilder $queryBuilder;
+    protected Query\QueryBuilderInterface $queryBuilder;
 
     protected EntityResolver $entityResolver;
 
@@ -271,6 +271,39 @@ class Repository
         }
     }
 
+    public function selectEntity(string $entity, string $alias, string $prependField = "") : self
+    {
+        $prependField and ( $prependField .= "$" );
+
+        foreach($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
+            if ( null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore) ) {
+                $this->select("$alias.$key as {$prependField}{$field['name']}");
+            }
+        }
+
+        return $this;
+    }
+
+    public function selectJsonEntity(string $entity, string $alias, bool $skipFrom = false) : self
+    {
+        $fieldlist = [];
+
+        foreach ($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
+            if (null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore)) {
+                $fieldlist[] = $key;
+                $fieldlist[] = $entity::field($field['name'], $alias);
+            }
+        }
+
+        $this->select(
+            Common\Sql::function('JSON_ARRAYAGG', Common\Sql::function('JSON_OBJECT', ... $fieldlist))
+        );
+
+        return $skipFrom ? $this : $this->from(
+            $entity::resolveEntity()->tableName(), $alias, $entity::resolveEntity()->schemaName()
+        );
+    }
+
     public function select(/*array|Stringable*/ $fields) : self
     {
         $this->queryBuilder->select($fields);
@@ -444,8 +477,8 @@ class Repository
             $this->select("{$this->alias}.*");
         }
 
-        # Apply FILTER annotation to this too !
-        foreach((array) $fields as $item) {
+        # @TODO Apply FILTER annotation to this too !
+        foreach(array_filter((array) $fields) as $item) {
             $annotation = $this->entityResolver->searchFieldAnnotation($item, new Join) ?:
                 $this->entityResolver->searchFieldAnnotation($item, new Relation);
 
@@ -459,7 +492,9 @@ class Repository
                 $entity = $annotation->entity ?? $this->entityResolver->properties[$item]['type'];
 
                 foreach($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME, true) as $key => $field) {
-                    $this->select("$alias.$key as {$alias}\${$field['name']}");
+                    if ( null === $entity::resolveEntity()->searchFieldAnnotation($field['name'], new RelationIgnore) ) {
+                        $this->select("$alias.$key as {$alias}\${$field['name']}");
+                    }
                 }
 
                 $this->open();
@@ -482,9 +517,14 @@ class Repository
 
                 $this->join("LEFT", $entity::resolveEntity()->tableName(), $key, $foreignKey, $alias, function($join) use ($item, $entity, $alias) {
                     foreach($this->entityResolver->searchFieldAnnotationList($item, new Where() ) as $condition) {
-                        $field = clone $condition->field;
+                        if ( ! is_object($condition->field) ) {
+                            $field = $this->entityClass::field($condition->field);
+                        }
+                        else {
+                            $field = clone $condition->field;
+                        }
 
-                        if ( is_object($condition->field) && ( $condition->field->entityClass === $entity ) ) {
+                        if ( $condition->field->entityClass === $entity ) {
                             $field->alias = $alias;
 
                             $join->where(is_object($field) ? $field : $entity::field($field, $alias), $condition->value, $condition->operator);
@@ -500,13 +540,77 @@ class Repository
         return $this;
     }
 
-    public function filterServerRequest(SearchRequest\SearchRequestInterface $searchRequest) : self
+    public function withSubquery(/*string|array*/ $fields) : self
     {
-        $searchRequest->count = $searchRequest->filter( clone $this )
-            ->wheres($searchRequest->wheres(), Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
-            ->likes($searchRequest->likes(), Query\Where::CONDITION_OR)
-            ->groups($searchRequest->groups())
-            ->count();
+        # We skip subqueries when counting results since it should not affect the row count.
+        if ( $this instanceof Repository\ServerRequestCountRepository ) {
+            return $this;
+        }
+
+        if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) {
+            $this->select("{$this->alias}.*");
+        }
+
+        # Apply FILTER annotation to this too !
+        foreach(array_filter((array) $fields) as $item) {
+            if ( $relation = $this->entityResolver->searchFieldAnnotation($item, new Relation) ) {
+                $alias = $relation->alias ?? $item;
+
+                if ( $relation->isManyToMany() ) {
+                    $entity = $relation->bridge;
+                    $repository = $relation->bridge::repository();
+                    $repository->queryBuilder->parent = $this->queryBuilder;
+
+                    extract(Repository\RelationBuilder::relationAnnotations($item, $relation));
+
+                    $repository->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName(), $relation->bridge::field($relationRelation->key, $relation->bridgeField), $relationRelation->entity::field($relationRelation->foreignKey, $alias), $relation->bridgeField)
+                        ->where( $entity::field($bridgeRelation->key, $relation->bridgeField), $entity::field($bridgeRelation->foreignKey, $this->alias))
+                        ->selectJsonEntity($relationRelation->entity, $alias)->open();
+                }
+                else {
+                    $entity = $relation->entity ?? $this->entityResolver->properties[$item]['type'];
+                    $repository = $entity::repository()->selectJsonEntity($entity, $alias)->open();
+                }
+
+                #  $relation->isManyToMany() and $repository->selectJsonEntity($relation->bridge, $relation->bridgeField, true);
+
+                foreach($this->entityResolver->searchFieldAnnotationList($item, new Where() ) as $condition) {
+                    $repository->where(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->value, $condition->operator);
+                }
+
+                foreach($this->entityResolver->searchFieldAnnotationList($item, new Having() ) as $condition) {
+                    $repository->having(is_object($condition->field) ? $condition->field : $entity::field($condition->field), $condition->value, $condition->operator);
+                }
+
+                $repository->close();
+
+                $key = is_string($relation->key) ? $this->entityClass::field($relation->key) : $relation->key;
+
+                if (! $relation->isManyToMany() ) {
+                    $foreignKey = is_string($relation->foreignKey) ? $entity::field($relation->foreignKey, $alias) : $relation->foreignKey;
+
+                    $repository->where( $foreignKey, $key);
+                }
+
+                $this->select("(" . $r = Common\Sql::raw($repository->queryBuilder->render() . ") as $item\$collection"));
+            }
+            else {
+                throw new \Exception("You referenced field `$item` which do not exist or do not contain a valid @Join annotation.");
+            }
+        }
+
+        return $this;
+    }
+
+    public function filterServerRequest(SearchRequest\SearchRequestInterface $searchRequest, bool $count = true) : self
+    {
+        if ($count) {
+            $searchRequest->count = $searchRequest->filter(new Repository\ServerRequestCountRepository($this->entityClass, $this->alias, $this->adapter))
+                ->wheres($searchRequest->wheres(), Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
+                ->likes($searchRequest->likes(), Query\Where::CONDITION_OR)
+                ->groups($searchRequest->groups())
+                ->count();
+        }
 
         return $searchRequest->filter($this)
             ->wheres($searchRequest->wheres(), Query\Where::OPERATOR_EQUAL, Query\Where::CONDITION_AND)
@@ -551,18 +655,18 @@ class Repository
 
         return Ulmus::runQuery($this->queryBuilder, $this->adapter);
     }
-    
+
     public function resetQuery() : self
     {
         $this->queryBuilder->reset();
-        
+
         return $this;
     }
-    
+
     protected function insertSqlQuery(array $dataset) : self
     {
         if ( null === $this->queryBuilder->getFragment(Query\Insert::class) ) {
-            $this->insert(array_keys($dataset), $this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
+            $this->insert(array_map([ $this, 'escapeField' ] , array_keys($dataset)), $this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
         }
 
         $this->values($dataset);
@@ -651,6 +755,11 @@ class Repository
         return new $this->entityClass();
     }
 
+    public function escapeField(string $identifier) : string
+    {
+        return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_FIELD);
+    }
+
     public function escapeTable(string $identifier) : string
     {
         return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_TABLE);
diff --git a/src/Repository/MssqlRepository.php b/src/Repository/MssqlRepository.php
new file mode 100644
index 0000000..e1d1741
--- /dev/null
+++ b/src/Repository/MssqlRepository.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace Ulmus\Repository;
+
+use Ulmus\{ Repository, Query };
+
+class MssqlRepository extends Repository {
+
+    protected function finalizeQuery() : void
+    { 
+        if ( null !== $offset = $this->queryBuilder->getFragment(Query\Offset::class) ) {
+            if ( null === $limit = $this->queryBuilder->getFragment(Query\Limit::class) ) {
+                throw new \Exception("Your offset query fragment is missing a LIMIT value.");
+            }
+
+            # an order by is mandatory for mssql offset/limit
+            if ( null === $order = $this->queryBuilder->getFragment(Query\OrderBy::class) ) {
+                $this->orderBy("(SELECT 0)");
+            }
+
+            $mssqlOffset = new \Ulmus\Query\MsSQL\Offset();
+
+            $mssqlOffset->set($offset->offset, $limit->limit);
+
+            $this->queryBuilder->removeFragment($offset);
+            $this->queryBuilder->removeFragment($limit);
+
+            $this->queryBuilder->push($mssqlOffset);
+        }
+        elseif ( null !== $limit = $this->queryBuilder->getFragment(Query\Limit::class) ) {
+            if ( null !== $select = $this->queryBuilder->getFragment(Query\Select::class) ) {
+                $select->top = $limit->limit;
+            }
+            elseif ( null !== $delete = $this->queryBuilder->getFragment(Query\Delete::class) ) {
+                $delete->top = $limit->limit;
+            }
+
+            $this->queryBuilder->removeFragment($limit);
+        }
+    }
+
+}
diff --git a/src/Repository/RelationBuilder.php b/src/Repository/RelationBuilder.php
new file mode 100644
index 0000000..4ff6d34
--- /dev/null
+++ b/src/Repository/RelationBuilder.php
@@ -0,0 +1,259 @@
+<?php
+
+namespace Ulmus\Repository;
+
+use Ulmus\{ Ulmus, Annotation, Query, Common, Common\EntityResolver, Repository, Event, EntityCollection, };
+use Ulmus\Annotation\Property\{Filter, OrderBy, Relation, Relation\Ignore as RelationIgnore, Where, WithJoin, };
+
+use Closure;
+
+class RelationBuilder
+{
+    protected Repository $repository;
+
+    protected /*object|string*/ $entity;
+
+    protected EntityResolver $resolver;
+
+    protected array $orders;
+
+    protected array $wheres;
+
+    protected array $filters;
+
+    protected array $joins;
+
+    public function __construct(/*string|object*/ $entity, ? Repository $repository = null)
+    {
+        $this->entity = $entity;
+        $this->resolver = $entity::resolveEntity();
+
+        if ($repository) {
+            $this->repository = $repository;
+        }
+    }
+
+    public function searchRelation(string $name) /* : object|EntityCollection|bool */
+    {
+        # Resolve relations here if one is called
+        if ( $this->entity->isLoaded() ) {
+            if ( false !== ( $dataset = $this->fetchFromDataset($name) ) ) {
+                return $dataset;
+            }
+
+            return $this->resolveRelation($name);
+        }
+    }
+
+    protected function resolveRelation(string $name) /* : object|EntityCollection */
+    {
+        if ( null !== ( $relation = $this->resolver->searchFieldAnnotation($name, new Relation() ) ) ) {
+            $this->orders = $this->resolver->searchFieldAnnotationList($name, new OrderBy() );
+            $this->wheres = $this->resolver->searchFieldAnnotationList($name, new Where() );
+            $this->filters = $this->resolver->searchFieldAnnotationList($name, new Filter() );
+            $this->joins = $this->resolver->searchFieldAnnotationList($name, new WithJoin() );
+
+            switch( true ) {
+                case $relation->isOneToOne():
+                    if ( $relation->hasBridge() ) {
+                        # @TODO ! dump($this->relationAnnotations($name, $relation));
+                    }
+                    else {
+                        $this->oneToOne($name, $relation);
+                    }
+
+                    $this->entity->eventExecute(Event\EntityRelationLoadInterface::class, $name, $this->repository);
+
+                    $result = call_user_func([ $this->repository, $relation->function ]);
+
+                    return count($result) === 0 ? $this->instanciateEmptyEntity($name, $relation): $result[0];
+
+                case $relation->isOneToMany():
+                    $this->oneToMany($name, $relation);
+
+                    $this->entity->eventExecute(Event\EntityRelationLoadInterface::class, $name, $this->repository);
+
+                    return call_user_func([ $this->repository, $relation->function ]);
+
+                case $relation->isManyToMany():
+                    $this->manyToMany($name, $relation, $relationRelation);
+
+                    $this->entity->eventExecute(Event\EntityRelationLoadInterface::class, $name, $this->repository);
+
+                    $results = call_user_func([ $this->repository, $relationRelation->function ]);
+
+                    if ($relation->bridgeField ?? false) {
+                        $collection = $relation->bridge::entityCollection();
+
+                        foreach($results as $entity) {
+                            $collection->append($this->fetchFromDataset($relation->bridgeField, $entity->entityLoadedDataset));
+                        }
+
+                        $this->entity->{$relation->bridgeField} = $collection;
+                    }
+
+                    return $results;
+            }
+        }
+
+        return false;
+    }
+
+    protected function applyFilter(Repository $repository, string $name) : Repository
+    {
+        foreach($this->filters ?? [] as $filter) {
+            $repository = call_user_func_array([ $this->entity, $filter->method ], [ $repository, $name ]);
+        }
+
+        return $repository;
+    }
+
+    protected function applyWhere() : void
+    {
+        if ($this->wheres) {
+            $this->repository->open();
+
+            foreach($this->wheres as $condition) {
+                $this->repository->where($condition->field, $condition->value, $condition->operator);
+            }
+
+            $this->repository->close();
+        }
+    }
+
+    protected function applyOrderBy() : void
+    {
+        foreach($this->orders as $item) {
+            $this->repository->orderBy($item->field, $item->order);
+        }
+    }
+
+    protected function instanciateEmptyEntity(string $name, Relation $relation) : object
+    {
+        $class = $relation->entity ?? $this->resolver->properties[$name]['type'];
+
+        return new $class();
+    }
+
+    protected function fetchFromDataset($name, ? array $data = null) /* object|bool */
+    {
+        $annotation = $this->resolver->searchFieldAnnotation($name, new Annotation\Property\Join) ?:
+            $this->resolver->searchFieldAnnotation($name, new Annotation\Property\Relation);
+
+        if ( $annotation ) {
+            $vars = [];
+            $len = strlen( $name ) + 1;
+
+            if ( ( $annotation instanceof Relation ) && $annotation->isManyToMany() ) {
+                $entity = $this->relationAnnotations($name, $annotation)['relationRelation']->entity;
+            }
+            else {
+                $entity = $annotation->entity ?? $this->resolver->properties[$name]['type'];
+            }
+
+            foreach($data ?: $this->entity->entityLoadedDataset as $key => $value) {
+                if ( $key === "{$name}\$collection" ) {
+                    if ($value) {
+                        if ( null === ( $dataset = \json_decode($value, true) ) ) {
+                            throw new \Exception(sprintf("JSON error '%s' from '%s'", \json_last_error_msg(), $value));
+                        }
+
+                        return $entity::entityCollection()->fromArray($dataset)->iterate(fn($e) => $e->resetVirtualProperties());
+                    }
+                    else {
+                        return $entity::entityCollection();
+                    }
+                }
+                elseif ( substr($key, 0, $len ) === "{$name}\$" ) {
+                    $vars[substr($key, $len)] = $value;
+                }
+            }
+
+            if ($vars) {
+                if ( [] !== $data = (array_values(array_unique($vars)) !== [ null ] ? $vars : []) ) {
+                    return ( new $entity() )->fromArray($data)->resetVirtualProperties();
+                }
+                else {
+                    return new $entity();
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public function oneToOne(string $name, Relation $relation) : Repository
+    {
+        return $this->oneToMany($name, $relation)->limit(1);
+    }
+
+    public function oneToMany(string $name, Relation $relation) : Repository
+    {
+        $baseEntity = $relation->entity ?? $this->resolver->properties[$name]['type'];
+
+        $this->repository = $baseEntity::repository();
+
+        $this->applyWhere();
+
+        $this->applyOrderBy();
+
+        $field = $relation->key;
+
+        if ($relation->foreignKey) {
+            $this->repository->where( is_object($relation->foreignKey) ? $relation->foreignKey : $baseEntity::field($relation->foreignKey), ! is_string($field) && is_callable($field) ? $field($this->entity) : $this->entity->$field );
+        }
+
+        return $this->applyFilter($this->repository, $name);
+    }
+
+    public function manyToMany(string $name, Relation $relation, ? Relation & $relationRelation = null, bool $selectBridgeField = true) : Repository
+    {
+        extract($this->relationAnnotations($name, $relation));
+
+        $this->repository = $relationRelation->entity::repository();
+
+        $bridgeAlias = $relation->bridgeField ?? uniqid("bridge_");
+
+        $relationAlias = $relation->field;
+
+        $this->repository->select("{$this->repository->alias}.*")
+            ->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName(), $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey), $bridgeAlias, function($join) {
+
+            })->join(Query\Join::TYPE_INNER, $this->entity::resolveEntity()->tableName(), $relation->bridge::field($bridgeRelation->key, $bridgeAlias), $this->entity::field($bridgeRelation->foreignKey, $relationAlias), $relationAlias, function($join) {
+
+            })->where( $this->entity::field($bridgeRelation->foreignKey, $relationAlias), is_string($this->entity) ? $this->entity::field($bridgeRelation->foreignKey) : $this->entity->{$bridgeRelation->foreignKey} );
+
+        if ($selectBridgeField && $relation->bridgeField) {
+            $this->repository->selectEntity($relation->bridge, $bridgeAlias, $bridgeAlias);
+        }
+
+        return $this->applyFilter($this->repository, $name);
+    }
+
+    public static function relationAnnotations(string $name, Relation $relation) : array
+    {
+        if ( $relation->isOneToOne() || $relation->isManyToMany() ) {
+            if ( ! $relation->hasBridge() ) {
+                throw new \Exception("Your many-to-many @Relation() from variable `$name` is missing a 'bridge' field.");
+            }
+
+            $bridgeEntity = Ulmus::resolveEntity($relation->bridge);
+            $bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
+            $relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
+
+            if ($relationRelation === null) {
+                throw new \Exception("@Relation annotation not found for field `{$relation->foreignField}` in entity {$relation->bridge}");
+            }
+
+            $relationRelation->entity ??= $relation->bridge::resolveEntity()->properties[$relation->foreignField]['type'];
+
+            return [
+                'bridgeEntity' => $bridgeEntity,
+                'bridgeRelation' => $bridgeRelation,
+                'relationRelation' => $relationRelation,
+            ];
+        }
+
+        return [];
+    }
+}
\ No newline at end of file
diff --git a/src/Repository/ServerRequestCountRepository.php b/src/Repository/ServerRequestCountRepository.php
new file mode 100644
index 0000000..964b4f7
--- /dev/null
+++ b/src/Repository/ServerRequestCountRepository.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Ulmus\Repository;
+
+use Ulmus\Repository;
+
+class ServerRequestCountRepository extends Repository {}
\ No newline at end of file
diff --git a/src/SearchRequest/SearchRequestPaginationTrait.php b/src/SearchRequest/SearchRequestPaginationTrait.php
index 0494c34..912b862 100644
--- a/src/SearchRequest/SearchRequestPaginationTrait.php
+++ b/src/SearchRequest/SearchRequestPaginationTrait.php
@@ -13,6 +13,8 @@ trait SearchRequestPaginationTrait {
     public int $limit = 25;
     
     public bool $skipCount = false;
+
+    public ? array $columns = null;
     
     public function limit(): int 
     {
diff --git a/src/Ulmus.php b/src/Ulmus.php
index d2f8bd8..9636c2b 100644
--- a/src/Ulmus.php
+++ b/src/Ulmus.php
@@ -18,13 +18,15 @@ abstract class Ulmus
     
     public static array $resolved = [];
 
-    public static function iterateQueryBuilder(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null) : Generator
+    public static function iterateQueryBuilder(Query\QueryBuilderInterface $queryBuilder, ? ConnectionAdapter $adapter = null) : Generator
     {
-        $sql = $queryBuilder->render();
+        $rendered = $queryBuilder->render();
         
-        $statement = ( $adapter ?: static::$defaultAdapter )->pdo()->select($sql, $queryBuilder->parameters ?? []);
+        $statement = ( $adapter ?: static::$defaultAdapter )->connector()->select($rendered, $queryBuilder->parameters ?? []);
 
-        while ( $row = $statement->fetch() ) {
+        $i = 0;
+
+        while ( $row = $statement->fetch()  ) {
             yield $row;
         }
 
@@ -37,13 +39,13 @@ abstract class Ulmus
         ];
     }
     
-    public static function datasetQueryBuilder(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null) : array
+    public static function datasetQueryBuilder(Query\QueryBuilderInterface $queryBuilder, ? ConnectionAdapter $adapter = null) : array
     {
         $rows = [];
+
+        $rendered = $queryBuilder->render();
         
-        $sql = $queryBuilder->render();
-        
-        $statement = ( $adapter ?: static::$defaultAdapter )->pdo()->select($sql, $queryBuilder->parameters ?? []);
+        $statement = ( $adapter ?: static::$defaultAdapter )->connector()->select($rendered, $queryBuilder->parameters ?? []);
 
         while ( $row = $statement->fetch() ) {
             $rows[] = $row;
@@ -56,22 +58,22 @@ abstract class Ulmus
         return $rows;
     }
     
-    public static function pdo(? ConnectionAdapter $adapter = null) : Common\PdoObject
+    public static function connector(? ConnectionAdapter $adapter = null) : object
     {
-        return ( $adapter ?: static::$defaultAdapter )->pdo();
+        return ( $adapter ?: static::$defaultAdapter )->connector();
     }
     
-    public static function runSelectQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null)
+    public static function runSelectQuery(Query\QueryBuilderInterface $queryBuilder, ? ConnectionAdapter $adapter = null)
     {   
-        $dataset = static::pdo($adapter)->select($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
+        $dataset = static::connector($adapter)->select($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
         $queryBuilder->reset();
         
         return $dataset;
     }
     
-    public static function runQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null)
+    public static function runQuery(Query\QueryBuilderInterface $queryBuilder, ? ConnectionAdapter $adapter = null)
     {   
-        $return = static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
+        $return = static::connector($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
         $queryBuilder->reset();
         
         return $return;
@@ -87,7 +89,7 @@ abstract class Ulmus
         return new static::$repositoryClass(...$arguments);
     }
 
-    public static function queryBuilder(...$arguments) : QueryBuilder
+    public static function queryBuilder(...$arguments) : Query\QueryBuilderInterface
     {
         return new static::$queryBuilderClass(...$arguments);
     }
@@ -116,9 +118,9 @@ abstract class Ulmus
         static::$registeredAdapters[$adapter->name] = $adapter;
     }
     
-    protected static function fetchQueryBuilder(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null) : array
+    protected static function fetchQueryBuilder(Query\QueryBuilderInterface $queryBuilder, ? ConnectionAdapter $adapter = null) : array
     {
-        $result = ( $adapter ?: static::$defaultAdapter )->pdo->select($queryBuilder->render(), $queryBuilder->parameters ?? [])->fetchAll();
+        $result = ( $adapter ?: static::$defaultAdapter )->connector->select($queryBuilder->render(), $queryBuilder->parameters ?? [])->fetchAll();
         $queryBuilder->reset();
         
         return $result;