🚫 No face, just logic.
x.com/codewhisperdev
HATEOAS = Hypermedia as the Engine of Application State
📦 Instead of sending just data, include actions
🧠 Why?
• Makes APIs discoverable
• Reduces hard-coded logic on the client
• Enables better versioning and evolution
HATEOAS = Hypermedia as the Engine of Application State
📦 Instead of sending just data, include actions
🧠 Why?
• Makes APIs discoverable
• Reduces hard-coded logic on the client
• Enables better versioning and evolution
You’ll find more than just “class” in C#. Let’s dive into the types you can define and use.
You’ll find more than just “class” in C#. Let’s dive into the types you can define and use.
Idempotent methods can be safely retried without causing side effects.
🔹 GET, PUT, DELETE, HEAD, OPTIONS → Idempotent
🔹 POST → NOT idempotent
🧠 Why?
Using the correct method:
▪️ Makes APIs predictable
▪️ Enables retries in network failures
▪️ Helps with caching, monitoring, and debugging
Idempotent methods can be safely retried without causing side effects.
🔹 GET, PUT, DELETE, HEAD, OPTIONS → Idempotent
🔹 POST → NOT idempotent
🧠 Why?
Using the correct method:
▪️ Makes APIs predictable
▪️ Enables retries in network failures
▪️ Helps with caching, monitoring, and debugging
🚫 Bad (Scalar function kills performance on large data)
✅ Good (Inline logic or apply in WHERE/CTE for better performance)
Example:
🚫 Bad (Scalar function kills performance on large data)
✅ Good (Inline logic or apply in WHERE/CTE for better performance)
Example:
🔹 Singleton - one of instance for entire app
🔹 Scoped - one instance per request
🔹 Transient - new instance every time
🚨 Be careful:
- Dont inject Scoped/Transient into Singleton (causes bugs/memory leaks)
- Use Singleton only for stateless or thread-safe services.
🔹 Singleton - one of instance for entire app
🔹 Scoped - one instance per request
🔹 Transient - new instance every time
🚨 Be careful:
- Dont inject Scoped/Transient into Singleton (causes bugs/memory leaks)
- Use Singleton only for stateless or thread-safe services.
Use ToList() after filtering, not before
Why?
🔹 First version loads everything into memory before filtering
🔹 Second version filters at source, better for DB or large collections
🔹 Especially important when using EF Core or APIs with IQueryable
Use ToList() after filtering, not before
Why?
🔹 First version loads everything into memory before filtering
🔹 Second version filters at source, better for DB or large collections
🔹 Especially important when using EF Core or APIs with IQueryable
Scenario:
You need to process a large dataset (e.g., database records, file lines, etc.), but you don’t want to load everything into memory at once. Using IAsyncEnumerable<T> lets you stream data asynchronously with minimal memory usage.
Scenario:
You need to process a large dataset (e.g., database records, file lines, etc.), but you don’t want to load everything into memory at once. Using IAsyncEnumerable<T> lets you stream data asynchronously with minimal memory usage.
Queue<T> is a First-In-First-Out (FIFO) collection in C#.
It means the first item you add is the first one to be removed.
When to use?
- Task scheduling
- Print jobs
- Message handling
- Breadth-first search (BFS) in graphs
Example:
Queue<T> is a First-In-First-Out (FIFO) collection in C#.
It means the first item you add is the first one to be removed.
When to use?
- Task scheduling
- Print jobs
- Message handling
- Breadth-first search (BFS) in graphs
Example:
Always monitor and maintain your indexes.
Unused or duplicate indexes = slower writes and wasted space.
Why?
- Clean indexes = faster inserts/updates
- Less I/O, better performance
🔍 Use this to find unused indexes in SQL Server
Always monitor and maintain your indexes.
Unused or duplicate indexes = slower writes and wasted space.
Why?
- Clean indexes = faster inserts/updates
- Less I/O, better performance
🔍 Use this to find unused indexes in SQL Server
Use GroupJoin for efficient one-to-many relationships instead of nested loops.
Why?
🔹 Cleaner than SelectMany + Where
🔹 Ideal for creating master-detail structures in memory
Use GroupJoin for efficient one-to-many relationships instead of nested loops.
Why?
🔹 Cleaner than SelectMany + Where
🔹 Ideal for creating master-detail structures in memory
Use CROSS APPLY for row-wise calculations or to invoke table-valued functions per row.
Why?
🔹Powerful for row-by-row subqueries
🔹Cleaner & faster than correlated subqueries in many cases
Use CROSS APPLY for row-wise calculations or to invoke table-valued functions per row.
Why?
🔹Powerful for row-by-row subqueries
🔹Cleaner & faster than correlated subqueries in many cases
Use async Task for methods so exceptions can be awaited and handled properly.
Pro tip: Use async void only for UI event handlers.
Use async Task for methods so exceptions can be awaited and handled properly.
Pro tip: Use async void only for UI event handlers.
🔹 Pass by Value: A copy of the value is passed to the function. Changes inside the function don’t affect the original variable.
🔹 Pass by Reference: The memory address (reference) is passed. Changes inside the function do affect the original variable.
🔹 Pass by Value: A copy of the value is passed to the function. Changes inside the function don’t affect the original variable.
🔹 Pass by Reference: The memory address (reference) is passed. Changes inside the function do affect the original variable.
Use EXISTS instead of COUNT(*) > 0 for better performance when checking if rows exist.
✅ EXISTS stops at the first match.
❌ COUNT(*) scans the whole table.
Faster checks = faster queries ⚡
Use EXISTS instead of COUNT(*) > 0 for better performance when checking if rows exist.
✅ EXISTS stops at the first match.
❌ COUNT(*) scans the whole table.
Faster checks = faster queries ⚡
Need to update thousands of rows? Avoid looping with .SaveChanges() in EF Core — it's slow.
Use a bulk update library like EFCore.BulkExtensions for massive performance gains.
Bonus: Works for Insert, Delete, Merge too.
Need to update thousands of rows? Avoid looping with .SaveChanges() in EF Core — it's slow.
Use a bulk update library like EFCore.BulkExtensions for massive performance gains.
Bonus: Works for Insert, Delete, Merge too.
Extract magic values into constants to improve readability and maintainability.
Cleaner code = easier maintenance!
Extract magic values into constants to improve readability and maintainability.
Cleaner code = easier maintenance!
Use Dictionary for fast lookups instead of looping!
Instead of searching a list repeatedly, store key-value pairs in a dictionary for O(1) access.
Use Dictionary for fast lookups instead of looping!
Instead of searching a list repeatedly, store key-value pairs in a dictionary for O(1) access.
Use COALESCE() to return the first non-null value from a list of columns or expressions.
Why it’s awesome:
• Handles null values seamlessly
• You can chain multiple options: COALESCE(col1, col2, 'default')
Cleaner queries, fewer CASE statements!
Use COALESCE() to return the first non-null value from a list of columns or expressions.
Why it’s awesome:
• Handles null values seamlessly
• You can chain multiple options: COALESCE(col1, col2, 'default')
Cleaner queries, fewer CASE statements!
Use null-coalescing assignment ??= to simplify default value logic in C# 8.0+.
What it does:
If myList is null, assign it a new list.
Shorter, smarter and safer code!
Use null-coalescing assignment ??= to simplify default value logic in C# 8.0+.
What it does:
If myList is null, assign it a new list.
Shorter, smarter and safer code!
Support flexible filtering via query parameters, not custom endpoints.
Why?
🔹 Keeps your endpoints clean (/products stays consistent)
🔹 Easy to combine filters (e.g. by brand, price, rating)
🔹 Plays well with sorting & pagination
Support flexible filtering via query parameters, not custom endpoints.
Why?
🔹 Keeps your endpoints clean (/products stays consistent)
🔹 Easy to combine filters (e.g. by brand, price, rating)
🔹 Plays well with sorting & pagination
Use Any() instead of Count() > 0 for better performance when just checking for existance.
Any() stops at the first match, Count() goes through the whole collection. Speed matters!
Use Any() instead of Count() > 0 for better performance when just checking for existance.
Any() stops at the first match, Count() goes through the whole collection. Speed matters!
One major issue: translations aren’t native; they rely on Google Translate. This needs to be properly implemented.
One major issue: translations aren’t native; they rely on Google Translate. This needs to be properly implemented.