DEV Community

Sabin Sim
Sabin Sim

Posted on

C#.NET - day 05

Day 5: LINQ — Searching and Filtering Data

Finding what you want from accumulated in-memory data

Introduction

At this stage, we already have data accumulating in memory. The next natural question is simple:

“How do we extract only what we want from what we have stored?”

This step introduces LINQ, a core C# feature that allows us to express what we want to retrieve, not how to loop through data.


🌊 System Flow (Search Flow)

  1. Input: The user requests /api/hello/search?name=Sabin.
  2. Controller: Receives the keyword Sabin and forwards it.
  3. Service: Decides how the search should behave.
  4. Repository: Uses LINQ to filter matching data and returns the result.

1️⃣ Repository: Adding LINQ Search

LINQ belongs in the Repository. This is the layer that knows how data is stored and how it can be queried.

Add the following method to HelloRepository.cs.

public List<HelloResponse> Search(string keyword)
{
    return _storage.Values
        .Where(x => x.Message.Contains(keyword))
        .ToList();
}
Enter fullscreen mode Exit fullscreen mode

Key CS Concepts

  • Lambda Expression (x => ...): a small anonymous function that answers a yes/no question.
  • Where: filters data (conceptually similar to SQL WHERE).

This code reads almost like a sentence:

“From all stored values, keep only those whose message contains the keyword.”


2️⃣ Service: Connecting the Logic

The Service does not search data itself. Instead, it decides what should happen based on the input.

Update HelloService.cs:

public List<HelloResponse> FindHello(string keyword)
{
    if (string.IsNullOrWhiteSpace(keyword))
    {
        return _repository.GetAll();
    }

    return _repository.Search(keyword);
}
Enter fullscreen mode Exit fullscreen mode

This logic answers a business question:

  • If no keyword is provided → return everything
  • If a keyword exists → perform a filtered search

This decision belongs in the Service layer.


3️⃣ Controller: Opening a Search Counter

The Controller simply exposes a new endpoint. It does not know how LINQ works, nor how data is stored.

[HttpGet("search")]
public IActionResult SearchHello(string name)
{
    var results = _service.FindHello(name);
    return Ok(results);
}
Enter fullscreen mode Exit fullscreen mode

This reinforces the idea that the Controller is only a delivery mechanism.


🚀 Running and Testing LINQ

  1. Add multiple entries (e.g. Sabin, Sam, Tom, Jerry).
  2. Call /api/hello/search.
  3. Search with S and confirm only matching entries are returned.

🧠 One-Minute CS Insight: Deferred Execution

The following line does not execute immediately:

_storage.Values.Where(...)
Enter fullscreen mode Exit fullscreen mode

LINQ builds an execution plan first. Actual iteration happens only when ToList() (or foreach) is called.

This is known as Deferred Execution and helps avoid unnecessary computation, especially with large datasets.


🧠 What Step 2.0 Is Really About

In one sentence:

LINQ allows us to describe what we want to extract from data, not how to loop through it.

Just as important:

LINQ is used in the Repository, not scattered across the system.

This keeps responsibilities clear and prepares the system for future changes, such as replacing in-memory storage with a real database.


✍️ My Notes & Reflections

  • Since the repository is directly responsible for finding what I want, searching is clearly a repository responsibility.
  • This made me curious about how these backend responsibilities eventually connect to the frontend and user interactions.

Top comments (0)