- src/Database.fs - подключение к БД и выполнение запросов
- src/SqlParser.fs - парсинг схемы БД
- src/TypeGenerator.fs - генерация типов F# из схемы
- src/QueryBuilder.fs - построение SQL запросов
- src/core/ORMCore.fs - высокоуровневый API для CRUD операций
- src/DataMapper.fs - маппинг f# типов -> sql типы и наоборот
Билдим проект
dotnet clean; dotnet build;Создаем типы из схемы (сохраняются в generated/GeneratedTypes.fs)
dotnet run -- --generate-typesБилдим полученные типы из бд как часть приложения
dotnet build Пользуемся предоставленными методами библиотеки (пример)
open ORM.Database
open ORM.ORMCore
open ORM.GeneratedTypes
use db = new DatabaseConnection()
let productsTable = db.Table<Products>("products")
let productId = 5
CRUD.update productsTable productId ["price", box 7999]
let usersTable = db.Table<Users>("users")
CRUD.insert usersTable [
"username", box testUsername
"email", box testEmail
"age", box 25
] services:
postgres:
image: postgres:16.6
shm_size: 128mb
ports:
- 5432:5432
volumes:
- postgres-data:/var/lib/postgresql/data
- ./initdb:/docker-entrypoint-initdb.d
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
env_file:
- .env
volumes:
postgres-data:POSTGRES_USER=username
POSTGRES_PASSWORD=password
POSTGRES_DB=dbname
POSTGRES_HOST=localhost
POSTGRES_PORT=6767
- Подключаемся к базе данных
- Получаем схемы таблиц из вашей бд (они должны быть доступны из information_schema и table_schema должен быть 'public')
- Генерируем f# типы в generated/GeneratedTypes.fs (на этапе build) (+ маппинг)
- Компилируется ORMCore - публичная API (библиотека) с доступными CRUD (cudi) методами (create, delete, insert, update)
- Вызываем метод, используя поля сгенерированного типа
- (под капотом) Вызывается QueryBuilder, формируя type-safe запрос (runtime проверка)
- Запрос отправляется в DataBase.fs, откуда идет непосредствеено в базу данных
- Мапинг результата (если select)
- Логирование ошибок (по наличию)
// AUTO-GENERATED FILE - DO NOT EDIT
// Generated at: 2025-12-21 17:46:00
// Generated from database schema
namespace ORM.GeneratedTypes
open System
[<AttributeUsage(AttributeTargets.Property)>]
type PrimaryKeyAttribute() =
inherit Attribute()
type Orders = {
[<PrimaryKey>] id: int
userId: int option
productId: int option
quantity: int option
status: string
orderDate: System.DateTime option
}
type Products = {
[<PrimaryKey>] id: int
name: string
price: int
category: string
inStock: bool option
}
type Users = {
[<PrimaryKey>] id: int
username: string
email: string
age: int option
createdAt: System.DateTime option
}
src/Schema.fs
type ColumnType =
| Int
| BigInt
| Varchar of maxLength: int option
| Text
| Boolean
| Json
| Datetype QueryType =
| Select of SelectQuery
| Insert of InsertQuery
| Update of UpdateQuery
| Delete of DeleteQueryЭтап 1: Безопасная конфигурация ✅
- Подключение к PostgreSQL через Npgsql ✅
- Чтение данных из .env ✅
- Базовая проверка соединения ✅
Этап 2: Парсинг схемы базы данных (SqlParser)✅ Цель: Получить структуру таблиц из БД
- Получить список всех таблиц в схеме public ✅
- Для каждой таблицы получить: ✅
- Название таблицы
- Список колонок с:
- Именем колонки
- Типом данных PostgreSQL
- Признаком NULL/NOT NULL
- Признаком первичного ключа
- Ограничениями (varchar(100), decimal(10,2), etc.)
- Сохранить эту структуру в F# типах ✅
Этап 3: генератор типов на этапе build ✅ Цель: представить таблицы f# как типы
- Генерация типов на основе схемы из Этапа 2: ✅
- type User = { id: int; username: string; email: string }
- type Product = { id: int; name: string; price: decimal }
- Маппинг типов PostgreSQL → F#: ✅
- INTEGER → int
- VARCHAR → string
- DECIMAL → decimal
- BOOLEAN → bool
- TIMESTAMP → DateTime
- и т.д.
- Генерация типов во build ✅
- Валидация типов после билда ✅
Этап 4: query builder
- Базовый DSL для построения запросов: ✅
- SELECT * FROM table WHERE condition
- INSERT INTO table (columns) VALUES (values)
- UPDATE table SET column = value WHERE condition
- DELETE FROM table WHERE condition
- Параметризованные запросы (защита от SQL-инъекций) ✅
- Поддержка простых условий (WHERE, ORDER BY, LIMIT) ✅
Этап 5: ORM Core - CRUD операции Цель: Реализовать базовые методы ORM
- Create/Insert: db.Users.Insert({ ... }) ✅
- Read/Select: ✅
- db.Users.FindAll()
- db.Users.FindBy(fun u -> u.Id = 1)
- db.Users.Where(fun u -> u.Age > 18).ToList()
- Update: db.Users.Update(1, {| Name = "New Name" |}) ✅
- Delete: db.Users.Delete(1) ✅
- Конфликт зависимостей uGet с FSharp.TypeProviders.SDK (deprecated: при неудачной попытке реализовать type Provider)
- Не ясно как гарантировать подключение к бд на этапе компиляции (deprecated: при неудачной попытке реализовать type Provider)