Previous issues of Milan's .NET Weekly
MNW #040: Scheduling Background Jobs With Quartz.NET
Jun 03 2023
5 min read
If you're building a scalable application, it's a common requirement to offload some work in your application to a background job. A few examples of that are: - Publishing email notifications - Generating reports - Updating a cache - Image processing How can you create a recurring background job in...
MNW #039: Build a CI/CD Pipeline With GitHub Actions And .NET
May 27 2023
5 min read
Do you want to streamline your software development process and accelerate your release cycles? Imagine being able to automatically build, test, and deploy your .NET applications with every code change. With CI/CD, you can significantly reduce manual effort and focus more on creating software, ensu...
MNW #038: Multi-Tenant Applications With EF Core
May 20 2023
5 min read
Most software applications today are built around the concept of multi-tenancy. One application serves multiple customers, while keeping their data isolated. You can approach multi-tenancy in two ways: - Single database & logical isolation of tenants - Multiple databases & physical isolation of ten...
MNW #037: Visualize Your Software Architecture With The C4 Model
May 13 2023
5 min read
Software architecture diagrams are a great way to communicate how you are planning to build a software system or how an existing software system works. However, the majority of software architecture diagrams I've seen are a total mess. If only there was a standard way to visualize your software arc...
MNW #036: Enforcing Software Architecture With Architecture Tests
May 06 2023
5 min read
Software architecture is a blueprint for how you should structure your system. You can follow this blueprint strictly, or you can give yourself varying levels of freedom. But when deadlines are tight, and you start cutting corners, that beautiful software architecture you built crumbles like a hous...
MNW #035: Health Checks In ASP.NET Core For Monitoring Your Applications
Apr 29 2023
5 min read
We all want to build robust and reliable applications that can scale indefinitely and handle any number of requests. But with distributed systems and microservices architectures growing in complexity, it's becoming increasingly harder to monitor the health of our applications. It's vital that you h...
MNW #034: Idempotent Consumer - Handling Duplicate Messages
Apr 22 2023
5 min read
What happens when a message is retried in an event-driven system? It happens more often than you think. The worst case scenario is that the message is processed twice, and the side effects can also be applied more than once. Do you want your bank account to be double charged? I'll assume the answer...
MNW #033: EF Core Raw SQL Queries
Apr 15 2023
5 min read
EF Core is getting many new and exciting features in the upcoming version. EF7 introduced support for returning scalar types using SQL queries. And now we're getting support for querying unmapped types with raw SQL queries in EF8. This is exactly what Dapper offers out of the box, and it's good to ...
MNW #032: How To Use Rate Limiting In ASP.NET Core
Apr 08 2023
5 min read
Rate limiting is a technique to limit the number of requests to a server or an API. A limit is introduced within a given time period to prevent server overload and protect against abuse. In ASP.NET Core 7 we have a built-in rate limiter middleware, that's easy to integrate into your API. We're goin...
MNW #031: Implementing The Saga Pattern With Rebus And RabbitMQ
Apr 01 2023
5 min read
Designing long-lived processes in a distributed environment is an interesting engineering challenge. And a well known pattern for solving this problem is a Saga. A Saga is a sequence of local transactions, where each local transaction updates the Saga state and publishes a message triggering the ne...
MNW #030: How To Publish MediatR Notifications In Parallel
Mar 25 2023
4 min read
MediatR is a popular library with a simple mediator pattern implementation in .NET. Here's a definiton taken from MediatR's GitHub: "In-process messaging with no dependencies." With the rise in popularity of the CQRS pattern, MediatR became the go-to library to implement commands and queries. Howev...
MNW #029: Creating Data-Driven Tests With xUnit
Mar 18 2023
5 min read
Data-driven testing is a testing method where test data is provided through some external source. Hence it's also known as parameterized testing. A popular testing library in .NET that supports parameterized testing is xUnit. It uses attributes to define test methods. The Fact attribute defines a s...
MNW #028: Using Multiple EF Core DbContexts In a Single Application
Mar 11 2023
5 min read
Entity Framework Core (EF Core) is a popular ORM in .NET that allows you to work with SQL databases. EF Core uses a DbContext, which represents a session with the database and is responsible for tracking changes, performing database operations, and managing database connections. It's common to have...
MNW #027: How To Apply Functional Programming In C#
Mar 04 2023
4 min read
Although C# is an object-oriented programming language, it received many new functional features in recent versions. To mention just a few of these features: - Pattern matching - Switch expressions - Records You're probably already doing functional programming without even knowing it. Do you use LI...
MNW #026: Outbox Pattern For Reliable Microservices Messaging
Feb 25 2023
5 min read
Working with Microservices, or any distributed system for that matter, is difficult. In a distributed system many things can go wrong, and there are even research papers about this. If you want to explore this topic futher, I suggest that you read about the fallacies of distributed computing. Reduc...
MNW #025: Structured Logging In ASP.NET Core With Serilog
Feb 18 2023
5 min read
Structured logging is a practice where you apply the same message format to all of your application logs. The end result is that all your logs will have a similar structure, allowing them to be easily searched and analyzed. Serilog is a popular logging library in .NET, packed with many features. It...
MNW #024: Messaging Made Easy With Azure Service Bus
Feb 11 2023
5 min read
If you're working in a distributed system, you need to be able to communicate between multiple services. There are a few ways that you can implement this. Depending on your chosen approach, you can either introduce tight coupling between your services or stay loosely coupled. Loose coupling is an i...
MNW #023: Working With Transactions In EF Core
Feb 04 2023
4 min read
Every software engineer working with SQL databases needs to know about transactions. And since most of the time the SQL database will be abstracted by an ORM like EF Core, it's important to understand how you can work with transactions using the available abstractions. So today, I'll show you how t...
MNW #022: How To Implement API Key Authentication In ASP.NET Core
Jan 28 2023
5 min read
In this week's newsletter I want to show you how to implement API Key authentication in ASP.NET Core. This authentication approach uses an API Key to authenticate the client of an API. You can pass the API Key to the API in a few ways, such as through the query string or a request header. I will sh...
MNW #021: C# Yield Return Statement
Jan 21 2023
5 min read
In this week's newsletter I want to talk about the yield keyword in C#. I think it's a powerful C# feature and I wanted to highlight the benefits. The yield keyword tells the compiler that the method in which it appears is an iterator block. An iterator block, or method, returns an IEnumerable as th...
MNW #020: Unleash EF Core Performance With Compiled Queries
Jan 14 2023
5 min read
In this week's newsletter I want to introduce you to an interesting feature in EF Core called Compiled Queries. If you have queries that you execute frequently in your application with a different set of parameters, it can be helpful to explicitly compile the query and reuse it throughout the lifeti...
MNW #019: Adding Validation To The Options Pattern In ASP.NET Core
Jan 07 2023
5 min read
In this week's newsletter I will show you how to easily add validation the strongly-typed configuration objects injected with IOptions. The Options pattern allows us to use classes to provide strongly-typed configuration values in our application at runtime. But you have no guarantee that the config...
MNW #018: How To Be a Better Software Engineer In 2023
Dec 31 2022
4 min read
In this week's newsletter I will share 5 simple tips on how you can be a better software engineer in 2023. I find it a little amusing that the last newsletter of the year and is also coming out on the last day of the year. Here are 5 tips for being a better software engineer in 2023....
MNW #017: Clean Architecture And The Benefits Of Structured Software Design
Dec 24 2022
5 min read
In the world of software development, there are countless approaches and methodologies to choose from. It's easy to get swayed with the latest trends, and loose sight of architectural principles that really matter. One of the more popular ones is Clean Architecture, a design approach that prioritize...
MNW #016: Fast Document Database In .NET With Marten
Dec 17 2022
5 min read
Did you know you can turn PostgreSQL into a fully-fledged Document database? Marten is a .NET library that allows developers to use the PostgreSQL database as both a document database and a fully-featured event store. You don't need to install anything else to be able to use PostgreSQL as a document...
MNW #015: How To Structure Minimal APIs
Dec 10 2022
4 min read
Minimal APIs were introduced to remove some of the ceremony of creating traditional APIs with controllers. To define an endpoint, you can use the new extension methods the were introduced such as MapGet to define a GET endpoint. I see one big issue with Minimal APIs, and that is the lack of clear gu...
MNW #014: Running Background Tasks In ASP.NET Core
Dec 03 2022
4 min read
In this week's newsletter we will talk about running background tasks in ASP .NET Core. After reading this newsletter, you will be able to set up a background task and have it up and running within minutes. Background tasks are used to offload some work in your application to the background, outside...
MNW #013: How To Use The New Bulk Update Feature In EF Core 7
Nov 26 2022
5 min read
In this week's newsletter, we're going to explore the new ExecuteUpdate and ExecuteDelete methods that were released with EF7. ExecuteUpdate allows us to write a query and run a bulk update operation on the entities matching that query. Similarly, ExecuteDelete allows us to write a query and delete ...
MNW #012: How To Use The Options Pattern In ASP.NET Core 7
Nov 19 2022
4 min read
In this week's newsletter I want to show you how you can use the powerful Options pattern in ASP.NET Core 7. The options pattern uses classes to provide strongly typed settings in your application at runtime. The values for the options instance can come from multiple sources. The typical use case is...
MNW #011: What's New In .NET 7?
Nov 12 2022
4 min read
In this week's newsletter I want to highlight a few interesting things that are now available with the release of C# 11 and .NET 7. In case you missed it, .NET 7 was released November 8th....
MNW #010: 5 Ways To Check For Duplicates In Collections, With Benchmarks
Nov 05 2022
4 min read
In this week's newsletter, we will take a look at five different ways to check if a collection contains duplicates. I'm going to explain the idea behind each algorithm, discuss the algorithm complexity (Big O Notation), and at the end, we'll look at some benchmark results....
MNW #009: How to Use Global Query Filters in EF Core
Oct 29 2022
4 min read
In this week's newsletter, I'll show you how you can remove repetitive conditions in EF Core database queries. An example would be when you implement soft-delete, and have to check if a record was soft-deleted or not in every query. Also, it is practical if you're working in a multi-tenant system an...
MNW #008: Introduction To Locking And Concurrency Control in .NET 6
Oct 22 2022
4 min read
In this week's newsletter, we'll see how we can work with locking in .NET 6. We won't talk about how the lock is actually implemented at the operating system level. We will focus on application-level locking mechanisms instead. Locking allows us to control how many threads can access some piece of c...
MNW #007: How I Optimized an API Endpoint to Make It 15x Faster
Oct 15 2022
4 min read
Performance optimizations are my favorite thing about software engineering. Over the last 5 years, I've encountered various performance problems that taught me different ways to overcome them....
MNW #006: Decorator Pattern In ASP.NET Core
Oct 08 2022
3 min read
Let's imagine we have an existing Repository implementation, and we want to introduce caching to reduce the load on the database. How can we achieve this without changing anything about the Repository implementation? Decorator pattern is a structural design pattern that allows you to introduce new b...
MNW #005: 3 Ways To Create Middleware In ASP .NET Core
Oct 01 2022
4 min read
In this newsletter, we'll be covering three ways to create middleware in ASP.NET Core applications. Middleware allows us to introduce additional logic before or after executing an HTTP request. You are already using many of the built-in middleware available in the framework. I'm going to show you th...
MNW #004: How I Approach Clean Architecture Folder Structure
Sep 24 2022
3 min read
Clean Architecture is a popular approach to structuring your .NET application. It's a layered architecture and splits into four layers: Domain, Application, Infrastructure, and Presentation. Each of the layers is typically one project in your solution. How do we create this in our .NET solutions?...
MNW #003: How I Improved Performance With EF Core Query Splitting
Sep 17 2022
3 min read
I recently ran into an issue with Entity Framework Core. The query I was running was constantly timing out. So I used a new EF Core feature called Query Splitting to significantly improve my performance....
MNW #002: Records, Anonymous Types, and Non-Destructive Mutation
Sep 10 2022
2 min read
Today, I'm going to share some fascinating things you can do with records and anonymous types. I will introduce you to the concept of non-destructive mutation. And I will talk about when and why we might want to use this C# language feature....
MNW #001: Why I Write My LINQ Queries Tall, Not Wide
Sep 03 2022
2 min read
In this newsletter, I'll show you how you can write tall LINQ queries to improve readability and make your code easier to maintain. We are going to start from a wide LINQ query, and see how we can refactor it into a tall LINQ query....