Data Operations

Back

Loading concept...

Entity Framework Core - Data Operations 🗄️

Imagine you have a magical notebook that can talk to a giant library. You write what you want, and the notebook fetches, adds, updates, or removes books for you. That’s Entity Framework Core (EF Core)! It’s your magical translator between your C# code and your database.


🎯 What We’ll Learn

Think of a restaurant kitchen:

  • CRUD = Taking orders, cooking food, updating orders, throwing away bad food
  • LINQ = A special language to describe exactly what food you want
  • Tracking = The chef remembering what’s cooking vs. just peeking at the menu
  • Loading Strategies = Getting ingredients when you need them
  • N+1 Problem = Asking for ingredients one by one instead of all at once
  • Relationships = How ingredients connect (eggs belong to breakfast, not dessert!)

1. CRUD Operations 🍳

CRUD stands for Create, Read, Update, Delete. These are the 4 things you can do with data—like a librarian managing books!

Create (Add New Things)

// Create a new student
var student = new Student
{
    Name = "Emma",
    Age = 10
};
context.Students.Add(student);
await context.SaveChangesAsync();

What happens? You tell EF Core: “Hey, I have a new student named Emma. Please save her to the database!”

Read (Find Things)

// Find all students
var allStudents = await context
    .Students
    .ToListAsync();

// Find one student by ID
var emma = await context
    .Students
    .FindAsync(1);

What happens? You ask: “Show me all the students!” or “Find student #1!”

Update (Change Things)

// Find Emma and change her age
var emma = await context
    .Students
    .FindAsync(1);
emma.Age = 11;  // Birthday!
await context.SaveChangesAsync();

What happens? You found Emma, changed her age, then told EF Core: “Save these changes!”

Delete (Remove Things)

// Remove a student
var student = await context
    .Students
    .FindAsync(1);
context.Students.Remove(student);
await context.SaveChangesAsync();

What happens? “Please remove this student from the database.”

graph TD A["Your Code"] --> B{CRUD Operation} B --> C["Create: Add"] B --> D["Read: Find/ToList"] B --> E["Update: Modify + Save"] B --> F["Delete: Remove"] C --> G["Database"] D --> G E --> G F --> G

2. LINQ with EF Core 🔍

LINQ (Language Integrated Query) is like ordering food at a restaurant. Instead of going to the kitchen yourself, you describe what you want!

Basic Queries

// Find students older than 8
var olderKids = await context.Students
    .Where(s => s.Age > 8)
    .ToListAsync();

// Get just the names
var names = await context.Students
    .Select(s => s.Name)
    .ToListAsync();

// Order by age
var sorted = await context.Students
    .OrderBy(s => s.Age)
    .ToListAsync();

Combining Filters

// Find students named "Emma" who are 10+
var result = await context.Students
    .Where(s => s.Name == "Emma")
    .Where(s => s.Age >= 10)
    .FirstOrDefaultAsync();

Counting and Checking

// How many students?
var count = await context.Students
    .CountAsync();

// Is there anyone named "Liam"?
var exists = await context.Students
    .AnyAsync(s => s.Name == "Liam");

Think of it like this:

  • Where = “I only want students who…”
  • Select = “I only want to see the…”
  • OrderBy = “Sort them by…”
  • FirstOrDefault = “Give me the first one, or nothing”

3. Tracking vs No-Tracking 👀

Imagine you’re a chef. Tracking means you remember every dish you’re cooking so you can update it. No-Tracking means you just peek at the menu—you’re not planning to cook anything.

Tracking (Default)

// EF Core remembers this student
var student = await context.Students
    .FirstAsync();

student.Name = "Updated Name";
await context.SaveChangesAsync();
// ✅ Changes are saved!

EF Core keeps an eye on student. When you change it and save, the database updates!

No-Tracking (Just Looking)

// EF Core forgets immediately
var student = await context.Students
    .AsNoTracking()
    .FirstAsync();

student.Name = "New Name";
await context.SaveChangesAsync();
// ❌ Nothing saved! EF Core forgot.

When to use No-Tracking?

  • When you’re just displaying data (read-only)
  • It’s faster because EF Core doesn’t need to remember
graph TD A["Query Data"] --> B{Will you change it?} B -->|Yes| C["Use Tracking"] B -->|No, just reading| D["Use AsNoTracking"] C --> E["Changes saved automatically"] D --> F["Faster, but no saves"]

4. EF Core Loading Strategies 📦

When you have related data (like a student and their classes), how should EF Core fetch them?

Eager Loading (Get Everything Now!)

// Get students WITH their classes
var students = await context.Students
    .Include(s => s.Classes)
    .ToListAsync();

Like ordering a combo meal—you get the burger AND fries together!

Lazy Loading (Get It When Needed)

// Classes load automatically when accessed
var student = await context.Students
    .FirstAsync();
var classes = student.Classes;
// Database call happens HERE

Like asking for ketchup only when you need it. But be careful—too many small trips!

Explicit Loading (Ask Specifically)

var student = await context.Students
    .FirstAsync();

// Load classes ONLY when I say so
await context.Entry(student)
    .Collection(s => s.Classes)
    .LoadAsync();

You decide exactly when to fetch related data.

Strategy When to Use Speed
Eager Need related data immediately 1 big query
Lazy Might need it, might not Many small queries
Explicit Control freak mode You decide

5. The N+1 Query Problem 🐌

This is a sneaky performance trap! Let’s see it with a story.

The Problem

Imagine you have 100 students, and each has classes. You want to show them all.

Bad Way (N+1):

var students = await context.Students
    .ToListAsync();

foreach (var s in students)
{
    // Each loop = NEW database query!
    Console.WriteLine(s.Classes.Count);
}
// Total: 1 + 100 = 101 queries! 😱

You made 1 query for students, then 100 MORE for each student’s classes!

The Solution

Good Way (Eager Loading):

var students = await context.Students
    .Include(s => s.Classes)
    .ToListAsync();

foreach (var s in students)
{
    Console.WriteLine(s.Classes.Count);
}
// Total: 1 query! 🚀
graph LR A["N+1 Problem"] --> B["1 Query: Get Students"] B --> C["Query 2: Student 1 Classes"] B --> D["Query 3: Student 2 Classes"] B --> E["Query 4: Student 3 Classes"] B --> F["... 100 more queries!"] G["Solution: Eager Loading"] --> H["1 Query: Students + Classes"] H --> I["Done! No extra queries"]

Remember: If you’re looping and accessing related data, use Include()!


6. EF Core Relationships 💑

Databases have relationships—just like friends, families, and teams!

One-to-Many (Parent has Many Children)

public class Teacher
{
    public int Id { get; set; }
    public string Name { get; set; }

    // One teacher has MANY students
    public List<Student> Students { get; set; }
}

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    // Each student has ONE teacher
    public int TeacherId { get; set; }
    public Teacher Teacher { get; set; }
}

One-to-One (One Person, One Passport)

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    // One student, one ID card
    public StudentIdCard IdCard { get; set; }
}

public class StudentIdCard
{
    public int Id { get; set; }
    public string CardNumber { get; set; }

    public int StudentId { get; set; }
    public Student Student { get; set; }
}

Many-to-Many (Students ↔ Classes)

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    // Many students in many classes
    public List<Class> Classes { get; set; }
}

public class Class
{
    public int Id { get; set; }
    public string Subject { get; set; }

    // Many classes have many students
    public List<Student> Students { get; set; }
}

EF Core 5+ handles the join table automatically!

graph LR subgraph One-to-Many A["Teacher"] -->|has many| B["Students"] end subgraph One-to-One C["Student"] -->|has one| D["ID Card"] end subgraph Many-to-Many E["Students"] <-->|enrolled in| F["Classes"] end

Loading Related Data

// Get teacher with all students
var teacher = await context.Teachers
    .Include(t => t.Students)
    .FirstAsync(t => t.Id == 1);

// Get student with classes
var student = await context.Students
    .Include(s => s.Classes)
    .FirstAsync(s => s.Id == 1);

🎉 Quick Summary

Concept Simple Explanation
CRUD Create, Read, Update, Delete—the 4 data actions
LINQ Ask for data using C# instead of SQL
Tracking EF Core remembers changes to save later
No-Tracking Just looking, no saving—faster!
Eager Loading Get everything in one trip
Lazy Loading Get extra stuff only when needed
N+1 Problem Making too many database trips—bad!
Relationships How tables connect (1-to-1, 1-to-many, many-to-many)

🌟 You did it! You now understand how EF Core talks to your database. It’s like having a super-smart assistant that translates your C# wishes into database actions. Keep practicing, and soon it’ll feel like magic! ✨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.