diff --git a/src/Scaffolding/TableImplementation.php b/src/Scaffolding/TableImplementation.php
index 4533bee67ae0a9f9ec0d3f47abd27c82e51e34d6..5243912241ec8f751c96ca14fcfaff27ed968658 100644
--- a/src/Scaffolding/TableImplementation.php
+++ b/src/Scaffolding/TableImplementation.php
@@ -89,9 +89,6 @@ final class TableImplementation implements Capability
 			->setBody("return [\n".$columnsArrayTemplate."\n];", $columnsDefinitions);
 
 
-		// Column references
-		// todo add - use constants? Or references to Column class?
-
 		$classType->addMethod('find')
 			->setParameters([
 				(new Code\Parameter('primaryKey'))
@@ -99,12 +96,9 @@ final class TableImplementation implements Capability
 			])
 			->setReturnType($this->rowClass)
 			->setReturnNullable()
-			->setBody(
-				'$row = $this->tableManager->find($this, $primaryKey);' . "\n" .
-				'\assert($row instanceof ? || $row === NULL);' . "\n" .
-				'return $row;',
-				[new Code\Literal($namespace->simplifyName($this->rowClass))]
-			);
+			->addBody('$row = $this->tableManager->find($this, $primaryKey, required: false);')
+			->addBody('\assert($row instanceof ? || $row === null);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
+			->addBody('return $row;');
 
 		$namespace->addUse(RowNotFound::class);
 		$classType->addMethod('get')
@@ -114,13 +108,9 @@ final class TableImplementation implements Capability
 			])
 			->setReturnType($this->rowClass)
 			->addComment('@throws RowNotFound')
-			->setBody(
-				'$row = $this->find($primaryKey);' . "\n" .
-				'if ($row === NULL) {' . "\n" .
-				'	throw new RowNotFound();' . "\n" .
-				'}' . "\n" .
-				'return $row;'
-			);
+			->addBody('$row = $this->tableManager->find($this, $primaryKey, required: true);')
+			->addBody('\assert($row instanceof ?);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
+			->addBody('return $row;');
 
 		$namespace->addUse(OrderBy::class);
 		$namespace->addUse(Paginator::class);
@@ -166,10 +156,8 @@ final class TableImplementation implements Capability
 			->addComment('@return ' . $namespace->simplifyName($this->rowClass))
 			->addComment('@throws RowNotFound')
 			->setReturnType($this->rowClass)
-			->addBody('[$row, $count] = $this->tableManager->findOneBy($this, $conditions);')
-			->addBody('\assert($row instanceof ? || $row === null);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
-			->addBody('if ($row === null) { throw new RowNotFound(); }')
-			->addBody('if ($count > 1) { throw new TooManyRowsFound(); }')
+			->addBody('$row = $this->tableManager->findOneBy($this, $conditions, required: true, unique: true);')
+			->addBody('\assert($row instanceof ?);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
 			->addBody('return $row;');
 
 		$classType->addMethod('findOneBy')
@@ -177,13 +165,12 @@ final class TableImplementation implements Capability
 				(new Code\Parameter('conditions'))->setType(Condition::class . '|array'),
 			])
 			->addComment('@param Condition|Condition[] $conditions')
-			->addComment('@return ' . $namespace->simplifyName($this->rowClass))
+			->addComment('@return ' . $namespace->simplifyName($this->rowClass) . '|null')
 			->addComment('@throws RowNotFound')
 			->setReturnType($this->rowClass)
 			->setReturnNullable()
-			->addBody('[$row, $count] = $this->tableManager->findOneBy($this, $conditions);')
+			->addBody('$row = $this->tableManager->findOneBy($this, $conditions, required: false, unique: true);')
 			->addBody('\assert($row instanceof ? || $row === null);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
-			->addBody('if ($count > 1) { throw new TooManyRowsFound(); }')
 			->addBody('return $row;');
 
 		$classType->addMethod('getFirstBy')
@@ -196,9 +183,8 @@ final class TableImplementation implements Capability
 			->addComment('@return ' . $namespace->simplifyName($this->rowClass))
 			->addComment('@throws RowNotFound')
 			->setReturnType($this->rowClass)
-			->addBody('[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);')
-			->addBody('\assert($row instanceof ? || $row === null);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
-			->addBody('if ($row === null) { throw new RowNotFound(); }')
+			->addBody('$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: true, unique: false);')
+			->addBody('\assert($row instanceof ?);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
 			->addBody('return $row;');
 
 		$classType->addMethod('findFirstBy')
@@ -208,11 +194,10 @@ final class TableImplementation implements Capability
 			])
 			->addComment('@param Condition|Condition[] $conditions')
 			->addComment('@param array<OrderBy|Expression<mixed>> $orderBy')
-			->addComment('@return ' . $namespace->simplifyName($this->rowClass))
-			->addComment('@throws RowNotFound')
+			->addComment('@return ' . $namespace->simplifyName($this->rowClass) . '|null')
 			->setReturnType($this->rowClass)
 			->setReturnNullable()
-			->addBody('[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);')
+			->addBody('$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: false, unique: false);')
 			->addBody('\assert($row instanceof ? || $row === null);', [new Code\Literal($namespace->simplifyName($this->rowClass))])
 			->addBody('return $row;');
 
diff --git a/src/TableManager.php b/src/TableManager.php
index 4b6880e1657b52496d065af8ff7b302841df5c86..3938260d30546c4f5e61664f995c9ea8a6775ab7 100644
--- a/src/TableManager.php
+++ b/src/TableManager.php
@@ -54,17 +54,12 @@ final class TableManager
 	 * @template TableType of Table
 	 * @param TableType $table
 	 * @param PrimaryKey<TableType> $primaryKey
-	 * @return null|Row
+	 * @return ($required is true ? Row : Row|null)
+	 * @throws RowNotFound
 	 */
-	public function find(Table $table, PrimaryKey $primaryKey): ?Row
+	public function find(Table $table, PrimaryKey $primaryKey, bool $required = true): ?Row
 	{
-		$rows = $this->findBy($table, $primaryKey->getCondition($table));
-		if (\count($rows) === 1) {
-			$row = \reset($rows);
-			return $row;
-		}
-		\assert(\count($rows) === 0);
-		return NULL;
+		return $this->findOneBy($table, $primaryKey->getCondition($table), required: $required);
 	}
 
 	/**
@@ -142,9 +137,10 @@ final class TableManager
 	 * @param TableType $table
 	 * @param Condition|Condition[] $conditions
 	 * @param array<OrderBy|Expression<mixed>> $orderBy
-	 * @return array{Row|null, int}
+	 * @return ($required is true ? Row : Row|null)
+	 * @throws RowNotFound
 	 */
-	public function findOneBy(Table $table, Condition|array $conditions, array $orderBy = [], bool $checkCount = true): array
+	public function findOneBy(Table $table, Condition|array $conditions, array $orderBy = [], bool $required = true, bool $unique = true): ?Row
 	{
 		$result = $this->connection->query(
 			'SELECT *',
@@ -159,32 +155,30 @@ final class TableManager
 					return $orderBy->toSql()->getValues();
 				})
 				: [['%sql', 'true::boolean']],
-			'%lmt', $checkCount ? 2 : 1,
 		);
 
 		foreach ($table::getDatabaseColumns() as $column) {
 			$result->setType($column->getName(), NULL);
 		}
 
-		$dibiRows = $result->fetchAll();
+		$dibiRow = $result->fetch();
+		if ($dibiRow === null) {
+			return ! $required ? null : throw new RowNotFound();
+		}
 
-		/** @var class-string<Row> $rowClass */
-		$rowClass = $table::getRowClass();
-		$modelRows = [];
-		foreach ($dibiRows as $dibiRow) {
-			\assert($dibiRow instanceof \Dibi\Row);
-			$modelRows[] = $rowClass::reconstitute(
-				mapWithKeys(
-					$dibiRow->toArray(),
-					static fn(string $columnName, mixed $value) => $value !== null ? $table->getTypeOf($columnName)->fromDatabase($value) : null,
-				),
-			);
+		if ($unique && $result->fetch() !== null) {
+			throw new TooManyRowsFound();
 		}
 
-		return [
-			$modelRows[0] ?? null,
-			\count($modelRows),
-		];
+		/** @var class-string<Row> $rowClass */
+		$rowClass = $table::getRowClass();
+		\assert($dibiRow instanceof \Dibi\Row);
+		return $rowClass::reconstitute(
+			mapWithKeys(
+				$dibiRow->toArray(),
+				static fn(string $columnName, mixed $value) => $value !== null ? $table->getTypeOf($columnName)->fromDatabase($value) : null,
+			),
+		);
 	}
 
 	/**
diff --git a/tests/Fixtures/ConfigTable.php b/tests/Fixtures/ConfigTable.php
index 605dd7294e124c6fef22862846951d30b5f490dc..660d80fb18e6f422a1cb3586833f54e6f3196483 100644
--- a/tests/Fixtures/ConfigTable.php
+++ b/tests/Fixtures/ConfigTable.php
@@ -80,8 +80,8 @@ final class ConfigTable implements Table
 
 	public function find(ConfigPrimaryKey $primaryKey): ?ConfigRow
 	{
-		$row = $this->tableManager->find($this, $primaryKey);
-		\assert($row instanceof ConfigRow || $row === NULL);
+		$row = $this->tableManager->find($this, $primaryKey, required: false);
+		\assert($row instanceof ConfigRow || $row === null);
 		return $row;
 	}
 
@@ -91,10 +91,8 @@ final class ConfigTable implements Table
 	 */
 	public function get(ConfigPrimaryKey $primaryKey): ConfigRow
 	{
-		$row = $this->find($primaryKey);
-		if ($row === NULL) {
-			throw new RowNotFound();
-		}
+		$row = $this->tableManager->find($this, $primaryKey, required: true);
+		\assert($row instanceof ConfigRow);
 		return $row;
 	}
 
@@ -131,24 +129,21 @@ final class ConfigTable implements Table
 	 */
 	public function getOneBy(Condition|array $conditions): ConfigRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
-		\assert($row instanceof ConfigRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
-		if ($count > 1) { throw new TooManyRowsFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, required: true, unique: true);
+		\assert($row instanceof ConfigRow);
 		return $row;
 	}
 
 
 	/**
 	 * @param Condition|Condition[] $conditions
-	 * @return ConfigRow
+	 * @return ConfigRow|null
 	 * @throws RowNotFound
 	 */
 	public function findOneBy(Condition|array $conditions): ?ConfigRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
+		$row = $this->tableManager->findOneBy($this, $conditions, required: false, unique: true);
 		\assert($row instanceof ConfigRow || $row === null);
-		if ($count > 1) { throw new TooManyRowsFound(); }
 		return $row;
 	}
 
@@ -161,9 +156,8 @@ final class ConfigTable implements Table
 	 */
 	public function getFirstBy(Condition|array $conditions, array $orderBy = []): ConfigRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
-		\assert($row instanceof ConfigRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: true, unique: false);
+		\assert($row instanceof ConfigRow);
 		return $row;
 	}
 
@@ -171,12 +165,11 @@ final class ConfigTable implements Table
 	/**
 	 * @param Condition|Condition[] $conditions
 	 * @param array<OrderBy|Expression<mixed>> $orderBy
-	 * @return ConfigRow
-	 * @throws RowNotFound
+	 * @return ConfigRow|null
 	 */
 	public function findFirstBy(Condition|array $conditions, array $orderBy = []): ?ConfigRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: false, unique: false);
 		\assert($row instanceof ConfigRow || $row === null);
 		return $row;
 	}
diff --git a/tests/Fixtures/GeneratedTable.php b/tests/Fixtures/GeneratedTable.php
index 5dbe6bfb297ac19707312dd063b7e8af7d1a13ab..ee0834412cbe41e9dc14300214620d23babe826a 100644
--- a/tests/Fixtures/GeneratedTable.php
+++ b/tests/Fixtures/GeneratedTable.php
@@ -80,8 +80,8 @@ final class GeneratedTable implements Table
 
 	public function find(GeneratedPrimaryKey $primaryKey): ?GeneratedRow
 	{
-		$row = $this->tableManager->find($this, $primaryKey);
-		\assert($row instanceof GeneratedRow || $row === NULL);
+		$row = $this->tableManager->find($this, $primaryKey, required: false);
+		\assert($row instanceof GeneratedRow || $row === null);
 		return $row;
 	}
 
@@ -91,10 +91,8 @@ final class GeneratedTable implements Table
 	 */
 	public function get(GeneratedPrimaryKey $primaryKey): GeneratedRow
 	{
-		$row = $this->find($primaryKey);
-		if ($row === NULL) {
-			throw new RowNotFound();
-		}
+		$row = $this->tableManager->find($this, $primaryKey, required: true);
+		\assert($row instanceof GeneratedRow);
 		return $row;
 	}
 
@@ -131,24 +129,21 @@ final class GeneratedTable implements Table
 	 */
 	public function getOneBy(Condition|array $conditions): GeneratedRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
-		\assert($row instanceof GeneratedRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
-		if ($count > 1) { throw new TooManyRowsFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, required: true, unique: true);
+		\assert($row instanceof GeneratedRow);
 		return $row;
 	}
 
 
 	/**
 	 * @param Condition|Condition[] $conditions
-	 * @return GeneratedRow
+	 * @return GeneratedRow|null
 	 * @throws RowNotFound
 	 */
 	public function findOneBy(Condition|array $conditions): ?GeneratedRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
+		$row = $this->tableManager->findOneBy($this, $conditions, required: false, unique: true);
 		\assert($row instanceof GeneratedRow || $row === null);
-		if ($count > 1) { throw new TooManyRowsFound(); }
 		return $row;
 	}
 
@@ -161,9 +156,8 @@ final class GeneratedTable implements Table
 	 */
 	public function getFirstBy(Condition|array $conditions, array $orderBy = []): GeneratedRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
-		\assert($row instanceof GeneratedRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: true, unique: false);
+		\assert($row instanceof GeneratedRow);
 		return $row;
 	}
 
@@ -171,12 +165,11 @@ final class GeneratedTable implements Table
 	/**
 	 * @param Condition|Condition[] $conditions
 	 * @param array<OrderBy|Expression<mixed>> $orderBy
-	 * @return GeneratedRow
-	 * @throws RowNotFound
+	 * @return GeneratedRow|null
 	 */
 	public function findFirstBy(Condition|array $conditions, array $orderBy = []): ?GeneratedRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: false, unique: false);
 		\assert($row instanceof GeneratedRow || $row === null);
 		return $row;
 	}
diff --git a/tests/Fixtures/PackagesTable.php b/tests/Fixtures/PackagesTable.php
index 4f6ca4d3d040a6fac92e197fea54421128537cf5..cd53a918b8dfb1e11d046a186f8ede02cd926eb2 100644
--- a/tests/Fixtures/PackagesTable.php
+++ b/tests/Fixtures/PackagesTable.php
@@ -80,8 +80,8 @@ final class PackagesTable implements Table
 
 	public function find(PackagePrimaryKey $primaryKey): ?PackageRow
 	{
-		$row = $this->tableManager->find($this, $primaryKey);
-		\assert($row instanceof PackageRow || $row === NULL);
+		$row = $this->tableManager->find($this, $primaryKey, required: false);
+		\assert($row instanceof PackageRow || $row === null);
 		return $row;
 	}
 
@@ -91,10 +91,8 @@ final class PackagesTable implements Table
 	 */
 	public function get(PackagePrimaryKey $primaryKey): PackageRow
 	{
-		$row = $this->find($primaryKey);
-		if ($row === NULL) {
-			throw new RowNotFound();
-		}
+		$row = $this->tableManager->find($this, $primaryKey, required: true);
+		\assert($row instanceof PackageRow);
 		return $row;
 	}
 
@@ -131,24 +129,21 @@ final class PackagesTable implements Table
 	 */
 	public function getOneBy(Condition|array $conditions): PackageRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
-		\assert($row instanceof PackageRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
-		if ($count > 1) { throw new TooManyRowsFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, required: true, unique: true);
+		\assert($row instanceof PackageRow);
 		return $row;
 	}
 
 
 	/**
 	 * @param Condition|Condition[] $conditions
-	 * @return PackageRow
+	 * @return PackageRow|null
 	 * @throws RowNotFound
 	 */
 	public function findOneBy(Condition|array $conditions): ?PackageRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
+		$row = $this->tableManager->findOneBy($this, $conditions, required: false, unique: true);
 		\assert($row instanceof PackageRow || $row === null);
-		if ($count > 1) { throw new TooManyRowsFound(); }
 		return $row;
 	}
 
@@ -161,9 +156,8 @@ final class PackagesTable implements Table
 	 */
 	public function getFirstBy(Condition|array $conditions, array $orderBy = []): PackageRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
-		\assert($row instanceof PackageRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: true, unique: false);
+		\assert($row instanceof PackageRow);
 		return $row;
 	}
 
@@ -171,12 +165,11 @@ final class PackagesTable implements Table
 	/**
 	 * @param Condition|Condition[] $conditions
 	 * @param array<OrderBy|Expression<mixed>> $orderBy
-	 * @return PackageRow
-	 * @throws RowNotFound
+	 * @return PackageRow|null
 	 */
 	public function findFirstBy(Condition|array $conditions, array $orderBy = []): ?PackageRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: false, unique: false);
 		\assert($row instanceof PackageRow || $row === null);
 		return $row;
 	}
diff --git a/tests/Fixtures/TestsTable.php b/tests/Fixtures/TestsTable.php
index 65f7f5f41b8cc99f1675dd0eadb43b3ab2de5adc..66a5e647a643ec51b2b5c8c7758b93557728e9cb 100644
--- a/tests/Fixtures/TestsTable.php
+++ b/tests/Fixtures/TestsTable.php
@@ -80,8 +80,8 @@ final class TestsTable implements Table
 
 	public function find(TestPrimaryKey $primaryKey): ?TestRow
 	{
-		$row = $this->tableManager->find($this, $primaryKey);
-		\assert($row instanceof TestRow || $row === NULL);
+		$row = $this->tableManager->find($this, $primaryKey, required: false);
+		\assert($row instanceof TestRow || $row === null);
 		return $row;
 	}
 
@@ -91,10 +91,8 @@ final class TestsTable implements Table
 	 */
 	public function get(TestPrimaryKey $primaryKey): TestRow
 	{
-		$row = $this->find($primaryKey);
-		if ($row === NULL) {
-			throw new RowNotFound();
-		}
+		$row = $this->tableManager->find($this, $primaryKey, required: true);
+		\assert($row instanceof TestRow);
 		return $row;
 	}
 
@@ -131,24 +129,21 @@ final class TestsTable implements Table
 	 */
 	public function getOneBy(Condition|array $conditions): TestRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
-		\assert($row instanceof TestRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
-		if ($count > 1) { throw new TooManyRowsFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, required: true, unique: true);
+		\assert($row instanceof TestRow);
 		return $row;
 	}
 
 
 	/**
 	 * @param Condition|Condition[] $conditions
-	 * @return TestRow
+	 * @return TestRow|null
 	 * @throws RowNotFound
 	 */
 	public function findOneBy(Condition|array $conditions): ?TestRow
 	{
-		[$row, $count] = $this->tableManager->findOneBy($this, $conditions);
+		$row = $this->tableManager->findOneBy($this, $conditions, required: false, unique: true);
 		\assert($row instanceof TestRow || $row === null);
-		if ($count > 1) { throw new TooManyRowsFound(); }
 		return $row;
 	}
 
@@ -161,9 +156,8 @@ final class TestsTable implements Table
 	 */
 	public function getFirstBy(Condition|array $conditions, array $orderBy = []): TestRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
-		\assert($row instanceof TestRow || $row === null);
-		if ($row === null) { throw new RowNotFound(); }
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: true, unique: false);
+		\assert($row instanceof TestRow);
 		return $row;
 	}
 
@@ -171,12 +165,11 @@ final class TestsTable implements Table
 	/**
 	 * @param Condition|Condition[] $conditions
 	 * @param array<OrderBy|Expression<mixed>> $orderBy
-	 * @return TestRow
-	 * @throws RowNotFound
+	 * @return TestRow|null
 	 */
 	public function findFirstBy(Condition|array $conditions, array $orderBy = []): ?TestRow
 	{
-		[$row] = $this->tableManager->findOneBy($this, $conditions, $orderBy, checkCount: false);
+		$row = $this->tableManager->findOneBy($this, $conditions, $orderBy, required: false, unique: false);
 		\assert($row instanceof TestRow || $row === null);
 		return $row;
 	}