| Project | Purpose |
|---|---|
MiniOrm/ |
Core ORM library + demo Program.cs |
MiniOrm.Migrations/ |
CLI migration tool |
CREATE DATABASE miniorm;Note: Database Username=postgres and Password=root
export MINIORM_CONN="Host=localhost;Database=miniorm;Username=postgres;Password=root"cd MiniOrmMigration
# Generate migration SQL file
dotnet run -- migrations add InitialCreate
# Review the generated file in Migrations/
# Apply all pending migrations
dotnet run -- migrations apply
# List applied / pending
dotnet run -- migrations list
# Rollback the last applied migration
dotnet run -- migrations rollbackcd MiniOrm
dotnet runThe demo:
- Connects to PostgreSQL
- Inserts two
Productrows (one withDiscount = NULL) - Finds a row by id
- Updates price and discount
- Lists all rows
- Deletes all rows
We have created the Product entity and we want the products table to be created in the database. When we run migrations add, MiniOrm scans the Product class and looks at every property one by one. But not every property should become a database column — for example a navigation property like public List<Order> Orders should never become a column. So MiniOrm checks each property for a [Column] or [PrimaryKey] attribute. If a property has neither of these attributes, it is silently skipped and ignored completely. If it has [PrimaryKey], it is marked as the primary key column. If it has [Column("name")], the name inside the attribute becomes the column name in the database. This filtering process is called attribute filtering — it is the thing that decides which properties are allowed into the database and which are not.
Once attribute filtering is done, MiniOrm has a list of properties that should become columns. But now it needs to know what SQL type to give each column. So for each filtered property, MiniOrm checks its C# type and translates it into the correct PostgreSQL equivalent. If the property is the primary key, it becomes SERIAL PRIMARY KEY. If the property is decimal?, the ? tells MiniOrm it is nullable, so it becomes NUMERIC NULL. If it is decimal without the ?, it becomes NUMERIC NOT NULL. If it is string? it becomes TEXT NULL, if it is string it becomes TEXT NOT NULL. Every C# type has a corresponding PostgreSQL type. This translation process is called type mapping — it is the translator that converts C# language into PostgreSQL language so the database can understand what kind of data each column will hold.