Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Money and Rounding: decimal, a Money Value Object, VAT and Distributing Cents
Modeling money correctly takes a Money value object that carries the amount with its currency, the same explicit rounding rule in C# and SQL, and Allocate instead of division so no cent is lost. The post shows Math.Round and SQL ROUND disagreeing on 0.125, the 1-cent difference between per-line and total VAT, an effective-dated VAT rate table (20%, 10%, 1% as of November 2026), EF Core complex type mapping and string amounts in JSON, with real output.
Settings Tables: A Global → Tenant → User Override Hierarchy
For settings that change at runtime and are overridden per tenant and per user, the most robust approach is a definition per setting (type, default, range and lowest override level) plus typed key-value rows tied to it, with the precedence rule in one service and validated, audited writes. The post compares this with EAV, typed columns, a JSON document and an external store, and shows the hidden IS NOT NULL filter EF Core adds to unique indexes on nullable columns.
Data Isolation in Multi-Tenancy: Database per Tenant, Shared Schema and Row-Level Security
For most SaaS products the best balance is shared tables with a TenantId column, a named tenant query filter in EF Core and, behind it, SQL Server row-level security fed by SESSION_CONTEXT. The post compares database per tenant, schema per tenant and shared tables, and shows tenant resolution, background jobs and automated isolation tests with real output.
Multilingual Data: Storing Names in Turkish and English — Translation Tables, JSON Columns and Fallback
For multilingual data managed by users, the most flexible option is a translation table keyed by (EntityId, Culture, Name) plus a fallback chain such as en-GB → en → tr built in one place. The post compares one column per language, translation tables, SQL Server 2025 json columns and a separate translation service, and shows the fallback with EF Core 10 LeftJoin and collation choice for the Turkish I with real output.
Expression Trees in C#: Holding a Lambda as Data, and the Bridge to EF Core
The difference between Func and Expression<Func>, looking at the tree's nodes and Compile, building a dynamic filter with Expression factory methods, a small SQL translator with ExpressionVisitor, IQueryable and EF Core 6's ToQueryString output, a captured variable turning into a parameter, the untranslatable method error, limits such as CS0834, CS8072 and CS8110, and the 70-microsecond cost of Compile measured with BenchmarkDotNet.
OWASP A05: Injection (1) — SQL Injection and Command Injection
We write the same book search endpoint with string concatenation, an ADO.NET parameter, Dapper and EF Core, and see how a parameter turns ' OR 1=1 -- into plain data. We examine FromSqlRaw vs FromSql through the EF1002 warning and ToQueryString, use ArgumentList and an allowlist instead of a shell in Process.Start, and clarify where input validation fits with .NET 10's built-in validation.