Entity Framework Core Mastery

Primary Keys, Composite Keys, & Guids

1 Views Updated 5/4/2026

Primary Keys, Composite Keys, & Guids

Every entity in a relational database must have a unique identifier. While an auto-incrementing integer (Identity Column) is the industry standard, modern distributed systems often require complex key structures, such as GUIDs or Multi-Column Composite Keys.

1. Standard Identifiers (Auto-Increment)

By convention, if a property is named Id or ClassNameId, EF Core automatically designates it as the Primary Key.

public class Order
{
    // EF Core recognizes this automatically.
    // In SQL Server, this becomes an IDENTITY(1,1) column.
    public int Id { get; set; } 
}

2. Using GUIDs (Globally Unique Identifiers)

Integers are sequential (1, 2, 3), making them highly predictable. A hacker who sees /api/orders/5 can immediately guess /api/orders/6. GUIDs (e.g., a3f8b...) are impossible to guess, making them ideal for secure API identifiers.

public class User
{
    public Guid Id { get; set; } 
}
❌ The GUID Performance Disaster

In SQL Server, Primary Keys are "Clustered" by default, meaning tables are physically sorted on the hard drive by the key. Integers sort sequentially, which is lightning fast. GUIDs are entirely random. Inserting random GUIDs causes violent "Page Splits" and heavy fragmentation on the hard drive, decimating insert performance.

✅ The Sequential GUID (SequentialUniqueIdentifier)

To fix this, we generate ordered GUIDs natively in SQL Server!

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .Property(u => u.Id)
        // Generates an ordered GUID inside SQL Server, eliminating Page Splits!
        .HasDefaultValueSql("NEWSEQUENTIALID()"); 
}

3. Shadow Properties as Foreign Keys

A "Shadow Property" is a column that exists in SQL Server, but does NOT exist in your C# class. This is incredibly useful for hiding internal database IDs from your domain logic.

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    // Note: There is NO 'BlogId' foreign key defined here in C#!
}

// In Fluent API:
modelBuilder.Entity<Post>()
            // We tell EF Core to create a 'BlogId' column in SQL Server anyway
            .Property<int>("BlogId"); 

4. Interview Mastery

Q: "We have an 'Enrollments' table linking 'Students' and 'Courses'. The DBA requires a Composite Primary Key using both the StudentId and CourseId. Why can't we just use two '[Key]' Data Annotations on the C# properties?"

Architect Answer: "Entity Framework Core explicitly prohibits using multiple `[Key]` annotations on a single entity class to define a composite key; the framework will throw a runtime exception during model building because it doesn't know the intended hierarchical order of the composite keys (e.g., should the SQL Index be StudentId, CourseId or CourseId, StudentId?). Composite keys MUST be configured using the Fluent API via `builder.HasKey(e => new { e.StudentId, e.CourseId });`. Note: As of EF Core 7+, Microsoft finally introduced the `[PrimaryKey(nameof(StudentId), nameof(CourseId))]` class-level attribute to circumvent this, but the Fluent API remains the safest and most expressive standard for complex schema generation."

Entity Framework Core Mastery
1. Foundations & Architecture
Introduction to Object Relational Mapping (ORM) Entity Framework Core Architecture & Providers Setup and DbContext Integration Code-First vs Database-First Approaches Reverse Engineering Existing Databases (Scaffolding)
2. Code-First Modeling
Entity Conventions & Data Annotations The Fluent API Deep Dive (OnModelCreating) Primary Keys, Composite Keys, & Guids Required Properties & Database Defaults Value Conversions (Enums & Strongly Typed IDs)
3. Relational Architecture
One-to-Many Relationships & Foreign Keys One-to-One Relationships (Dependent Entities) Many-to-Many Relationships & Navigation Properties Owned Entity Types (Value Objects) Table-per-Hierarchy (TPH) Inheritance
4. Data Querying & LINQ
Basic LINQ Queries & IQueryable Execution Tracking vs No-Tracking Queries (Performance) Eager Loading vs Explicit Loading (Include) Lazy Loading Pitfalls & Proxies Client vs Server Evaluation Parsing
5. Manipulating Data (CUD)
Adding, Updating, and Removing Entities The ChangeTracker and Entity States Disconnected Entities in Web APIs Batch Updates and Deletes (.NET 7+)
6. Advanced Performance & Scale
Concurrency Tokens and Optimistic Locking Raw SQL Queries and Views (FromSqlRaw) Compiled Queries for High Throughput Interceptors (Logging & Auditing Data Changes) DbContext Pooling Mechanisms Managing Complex EF Core Migrations (CI/CD)