Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Working with an Event Store: Append, Optimistic Concurrency, and Streams with Marten and PostgreSQL
An event store's core contract is appending to a stream only while it is at the expected version; Marten provides this on PostgreSQL with a unique index on (stream_id, version) and FetchForWriting. Setting up Marten 9, StartStream/Append, wiring a decider to FetchForWriting, a race between two writers, stream id strategies, KurrentDB versus your own table, and event names that break under a Turkish culture.
A Separate Read Model: Materialized Views, Synchronization, and Living with Eventual Consistency
A separate read model stores the screen's row precomputed from domain events; updated in the same transaction it stays immediately consistent, updated asynchronously in a separate database you have to live with eventual consistency. Inline projections, PostgreSQL materialized views, an asynchronous projector with a checkpoint, waiting on a position for read-your-own-writes, idempotent updates and a full rebuild, with real output.
CQRS in a Single Database: Aggregates on the Write Side, Projections on the Read Side
CQRS in a single database means saving the aggregate through EF Core's change tracker on the write side and projecting from the same tables on the read side without ever touching the aggregate. What PlaceOrder and CancelOrder should return, a separate flat read DbContext, Dapper over a SQL view, and having PostgreSQL enforce that queries don't change state with read-only transactions, with real SQL and the 25006 error.
Stored Procedures with Dapper: Output, Return Value and the Auto-Detection Trap of 2.1.11
SQLite has no stored procedures, so we move to SQL Server in docker: CommandType.StoredProcedure, output and return values with DynamicParameters, how SET NOCOUNT affects Execute, single-word commands mistaken for procedures since 2.1.11, and the function vs procedure difference in PostgreSQL.