Migrations, Concurrency & Real-World Tradeoffs
Migrations Workflow
dotnet ef migrations add AddUserEmailColumn # generates the migration file for review
dotnet ef database update # applies it to the actual databaseCode First: entity classes drive the schema, migrations generated from model diffs. Database First: an existing DB drives generated entity classes. The two-step generate-then-apply process gives a review checkpoint before touching a real database — and migrations can be rolled back if one turns out problematic.
AsNoTracking & Read-Only Queries
var report = context.Orders.AsNoTracking().Where(o => o.Year == 2026).ToList();
// skips change-tracking overhead for data that will never be saved backOptimistic Concurrency
public class Account {
public int Id { get; set; }
public decimal Balance { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; } // concurrency token
}
// SaveChanges() throws DbUpdateConcurrencyException if RowVersion
// changed since this entity was loaded — someone else updated it firstDetects conflicting concurrent updates instead of silently letting one overwrite the other — important wherever multiple users might edit the same record around the same time.
ORM vs. Raw SQL
EF Core gives compile-time-checked, portable queries with change tracking for most access patterns. For highly complex or performance-critical queries, EF Core also supports dropping to raw SQL — a common, pragmatic mix rather than an all-or-nothing choice. Watch for client-side evaluation: some LINQ expressions can't translate to SQL and silently fall back to slow in-memory processing.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free