January 13 2025

public class BookingDbContext(DbContextOptions<BookingDbContext> options) : DbContext(options) { public DbSet<Traveler> Travelers { get; set; } public DbSet<BookingSagaData> BookingSagaData { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<BookingSagaData>().HasKey(s => s.CorrelationId); } }
public class Traveler { public Guid Id { get; set; } public string Email { get; set; } = string.Empty; public DateTime BookedOn { get; set; } }
public class BookingSaga : MassTransitStateMachine<BookingSagaData> { public State HotelBooking { get; set; } public State FlightBooking { get; set; } public State CarRenting { get; set; } public State BookingCompleting { get; set; } public Event<HotelBooked> HotelBooked { get; set; } public Event<FlightBooked> FlightBooked { get; set; } public Event<CarRented> CarRented { get; set; } public Event<BookingCompleted> BookingCompleted { get; set; } public BookingSaga() { InstanceState(x => x.CurrentState); Event(() => HotelBooked, e => e.CorrelateById(m => m.Message.TravelerId)); Event(() => FlightBooked, e => e.CorrelateById(m => m.Message.TravelerId)); Event(() => CarRented, e => e.CorrelateById(m => m.Message.TravelerId)); Initially ( When(HotelBooked) .Then(context => { context.Saga.TravelerId = context.Message.TravelerId; context.Saga.HotelName = context.Message.HotelName; context.Saga.FlightCode = context.Message.FlightCode; context.Saga.CarPlateNumber = context.Message.CarPlateNumber; }) .TransitionTo(FlightBooking) .Publish(context => new BookFlight(context.Message.TravelerId, context.Message.Email, context.Message.FlightCode, context.Message.CarPlateNumber)) ); During(FlightBooking, When(FlightBooked) .Then(context => context.Saga.FlightBooked = true) .TransitionTo(CarRenting) .Publish(context => new RentCar(context.Message.TravelerId, context.Message.Email, context.Message.CarPlateNumber)) ); During(CarRenting, When(CarRented) .Then(context => { context.Saga.CarRented = true; context.Saga.BookingFinished = true; }) .TransitionTo(BookingCompleting) .Publish(context => new BookingCompleted { TravelerId = context.Message.TravelerId, Email = context.Message.Email }) .Finalize()); } }
public record BookHotel(string Email, string HotelName, string FlightCode, string CarPlateNumber); public record BookFlight(Guid TravelerId, string Email, string FlightCode, string CarPlateNumber); public record RentCar(Guid TravelerId, string Email, string CarPlateNumber);
public class HotelBooked { public Guid TravelerId { get; set; } public string Email { get; set; } = string.Empty; public string HotelName { get; set; } = string.Empty; public string FlightCode { get; set; } = string.Empty; public string CarPlateNumber { get; set; } = string.Empty; } public class FlightBooked { public Guid TravelerId { get; set; } public string Email { get; set; } = string.Empty; public string FlightCode { get; set; } = string.Empty; public string CarPlateNumber { get; set; } = string.Empty; } public class CarRented { public Guid TravelerId { get; set; } public string Email { get; set; } = string.Empty; public string CarPlateNumber { get; set; } = string.Empty; } public class BookingCompleted { public Guid TravelerId { get; set; } public string Email { get; set; } = string.Empty; }
public class BookHotelHandler(BookingDbContext _dbContext) : IConsumer<BookHotel> { public async Task Consume(ConsumeContext<BookHotel> context) { Console.WriteLine($"Booking hotel {context.Message.HotelName} for traveler {context.Message.Email}"); var traveler = new Traveler { Id = Guid.NewGuid(), Email = context.Message.Email, BookedOn = DateTime.Now }; _dbContext.Travelers.Add(traveler); await _dbContext.SaveChangesAsync(); await context.Publish(new HotelBooked { TravelerId = traveler.Id, HotelName = context.Message.HotelName, FlightCode = context.Message.FlightCode, CarPlateNumber = context.Message.CarPlateNumber }); } }
public class BookHotelHandler(BookingDbContext _dbContext) : IConsumer<BookHotel> { public async Task Consume(ConsumeContext<BookHotel> context) { Console.WriteLine($"Booking hotel {context.Message.HotelName} for traveler {context.Message.Email}"); var traveler = new Traveler { Id = Guid.NewGuid(), Email = context.Message.Email, BookedOn = DateTime.Now }; _dbContext.Travelers.Add(traveler); await _dbContext.SaveChangesAsync(); await context.Publish(new HotelBooked { TravelerId = traveler.Id, HotelName = context.Message.HotelName, FlightCode = context.Message.FlightCode, CarPlateNumber = context.Message.CarPlateNumber }); } }
[HttpPost("bookTrip")] public IActionResult BookTrip(BookingDetails bookingDetails) { _bus.Publish(new BookHotel(bookingDetails.Email, bookingDetails.HotelName, bookingDetails.FlightCode, bookingDetails.CarPlateNumber)); return Accepted(); }
1. Design Patterns that Deliver
This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.
Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.
Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.
Join 18,000+ subscribers to improve your .NET Knowledge.
Subscribe to the TheCodeMan.net and be among the 18,000+ subscribers gaining practical tips and resources to enhance your .NET expertise.