<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: FreeLearning365.com</title>
    <description>The latest articles on Forem by FreeLearning365.com (@freelearning365).</description>
    <link>https://forem.com/freelearning365</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3500697%2Fecd91a8e-e9e1-4c5f-851d-49b4582fbbdf.png</url>
      <title>Forem: FreeLearning365.com</title>
      <link>https://forem.com/freelearning365</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/freelearning365"/>
    <language>en</language>
    <item>
      <title>ASP.NET Core Mastery with Latest Features : 40-Part Series from Zero to Cloud Expert | FreeLearning365</title>
      <dc:creator>FreeLearning365.com</dc:creator>
      <pubDate>Wed, 22 Oct 2025 11:22:58 +0000</pubDate>
      <link>https://forem.com/freelearning365/aspnet-core-mastery-with-latest-features-40-part-series-from-zero-to-cloud-expert--4j48</link>
      <guid>https://forem.com/freelearning365/aspnet-core-mastery-with-latest-features-40-part-series-from-zero-to-cloud-expert--4j48</guid>
      <description>&lt;h2&gt;
  
  
  ASP.NET Core 2025 Mastery Series
&lt;/h2&gt;

&lt;p&gt;Your complete journey from beginner to cloud-native expert with 40 hands-on tutorials, real-world projects, and professional training&lt;/p&gt;

&lt;p&gt;40 Detailed Posts Beginner to Expert Cloud &amp;amp; AI Integration&lt;/p&gt;

&lt;p&gt;Beginner&lt;/p&gt;

&lt;p&gt;Intermediate&lt;/p&gt;

&lt;p&gt;Advanced&lt;/p&gt;

&lt;p&gt;Expert&lt;/p&gt;

&lt;h2&gt;
  
  
  Beginner Level - Foundation Building
&lt;/h2&gt;

&lt;p&gt;Start your ASP.NET Core journey with these fundamental concepts and hands-on tutorials.&lt;/p&gt;

&lt;p&gt;Post 1&lt;/p&gt;

&lt;h3&gt;
  
  
  ASP.NET Core 2025 Unleashed: Ultimate Beginner's Guide
&lt;/h3&gt;

&lt;p&gt;Dive into ASP.NET Core 2025 from zero! This ultimate guide covers setup, tools, and your first app to spark your dev passion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-2025-beginner-guide-part-1.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 2&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up ASP.NET Core Like a Pro
&lt;/h3&gt;

&lt;p&gt;Unlock insider secrets for ASP.NET Core setup with Visual Studio, CLI, and workflow boosts. Elevate your coding game today!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-pro-setup-guide-part-2.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 3&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Your First ASP.NET Core Web App
&lt;/h3&gt;

&lt;p&gt;Transform into a web dev hero with this thrilling tutorial on creating your debut ASP.NET Core app using MVC and Razor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/build-first-aspnet-core-mvc-web-app.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 4&lt;/p&gt;

&lt;h3&gt;
  
  
  C# 12 Mastery: Essential Features
&lt;/h3&gt;

&lt;p&gt;Master C# 12's game-changing features like records and pattern matching tailored for ASP.NET Core. Level up your code!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/c-12-features-mastery-part-4-primary.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 5&lt;/p&gt;

&lt;h3&gt;
  
  
  Deep Dive into ASP.NET Core MVC
&lt;/h3&gt;

&lt;p&gt;Conquer MVC in ASP.NET Core with in-depth coverage of controllers, views, routing, and DI for scalable apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-mvc-deep-dive-part-5.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 6&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity Framework Core 9 Fundamentals
&lt;/h3&gt;

&lt;p&gt;Unleash EF Core 9 for seamless database integration—models, migrations, and relationships made easy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/entity-framework-core-9-fundamentals.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 7&lt;/p&gt;

&lt;h3&gt;
  
  
  SqlClient Power Play
&lt;/h3&gt;

&lt;p&gt;Go raw with SqlClient for high-performance data access in ASP.NET Core—beyond ORMs for speed demons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/sqlclient-raw-performance-part-7.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 8&lt;/p&gt;

&lt;h3&gt;
  
  
  Dapper Deep Dive
&lt;/h3&gt;

&lt;p&gt;Speed up your apps with Dapper's ultra-fast querying and mapping in ASP.NET Core. The secret weapon for pros!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/dapper-deep-dive-part-8-ultra-fast.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intermediate Level - Core Development
&lt;/h2&gt;

&lt;p&gt;Deepen your skills with API development, authentication, and essential patterns.&lt;/p&gt;

&lt;p&gt;Post 9&lt;/p&gt;

&lt;h3&gt;
  
  
  Minimal APIs Revolution
&lt;/h3&gt;

&lt;p&gt;Revolutionize API development with Minimal APIs in ASP.NET Core for rapid, efficient builds. Game-changer alert!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/minimal-apis-revolution-aspnet-core.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 10&lt;/p&gt;

&lt;h3&gt;
  
  
  RESTful API Mastery
&lt;/h3&gt;

&lt;p&gt;Dominate REST APIs with best practices, versioning, and serialization in ASP.NET Core. Build irresistible services!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/restful-api-mastery-aspnet-core-best.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 11&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL Explosion
&lt;/h3&gt;

&lt;p&gt;Supercharge your APIs with GraphQL using HotChocolate—schemas, resolvers, and more for client-driven power.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/graphql-explosion-hotchocolate-aspnet.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 12&lt;/p&gt;

&lt;h3&gt;
  
  
  JWT Authentication Ninja
&lt;/h3&gt;

&lt;p&gt;Lock down your apps with JWT auth, claims, and refresh strategies in ASP.NET Core. Cybersecurity mastery!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/jwt-authentication-ninja-complete.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 13&lt;/p&gt;

&lt;h3&gt;
  
  
  ASP.NET Core Identity Unleashed
&lt;/h3&gt;

&lt;p&gt;Build secure identity systems with registration, roles, and 2FA in ASP.NET Core Identity. Magic for pros!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-identity-unleashed-complete.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 14&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced Authorization
&lt;/h3&gt;

&lt;p&gt;Master policy-based auth and resource protection in ASP.NET Core for ultimate security. Defend like a pro!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-advanced-authorization.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 15&lt;/p&gt;

&lt;h3&gt;
  
  
  Swagger Mastery
&lt;/h3&gt;

&lt;p&gt;Wow your team with interactive API docs using Swagger in ASP.NET Core. Effortless and viral-ready!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-swagger-mastery-interactive.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 16&lt;/p&gt;

&lt;h3&gt;
  
  
  Middleware Domination
&lt;/h3&gt;

&lt;p&gt;Take full control of ASP.NET Core pipelines with custom middleware for logging and auth. Ultimate power!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/module-16-of-40-aspnet-core-middleware.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 17&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration and Secrets Mastery
&lt;/h3&gt;

&lt;p&gt;Safeguard configs with appsettings, secrets, and cloud vaults in ASP.NET Core. Flexible and secure!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-configuration-secrets.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 18&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Patterns Revolution
&lt;/h3&gt;

&lt;p&gt;Apply essential patterns like Repository and Singleton in ASP.NET Core for clean code. Elegance unlocked!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-design-patterns-revolution.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Level - Architecture &amp;amp; Performance
&lt;/h2&gt;

&lt;p&gt;Master advanced patterns, performance optimization, and real-world application architecture.&lt;/p&gt;

&lt;p&gt;Post 19&lt;/p&gt;

&lt;h3&gt;
  
  
  Architectural Patterns Epic
&lt;/h3&gt;

&lt;p&gt;Architect resilient systems with CQRS, DDD, and patterns in ASP.NET Core. Enterprise-ready!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-architecture-patterns-cqrs.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 20&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Handling Triumph
&lt;/h3&gt;

&lt;p&gt;Turn bugs into wins with middleware and logging in ASP.NET Core error handling. Stay robust!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-error-handling-master.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 21&lt;/p&gt;

&lt;h3&gt;
  
  
  Razor Pages Breakthrough
&lt;/h3&gt;

&lt;p&gt;Simplify UIs with Razor Pages—syntax, models, and helpers for engaging interfaces. Game-changer!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-razor-pages-mastery.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 22&lt;/p&gt;

&lt;h3&gt;
  
  
  Blazor Superpowers
&lt;/h3&gt;

&lt;p&gt;Create SPA-like experiences with Blazor in ASP.NET Core—components and real-time features. Ignite your apps!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/blazor-superpowers-spa-components-real.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 23&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Fusion
&lt;/h3&gt;

&lt;p&gt;Blend JS frameworks with ASP.NET Core for powerful hybrids. Merge worlds seamlessly!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-frontend-fusion-integrating.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 26&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Hacks Unleashed
&lt;/h3&gt;

&lt;p&gt;Turbocharge with async, profiling, and tweaks in ASP.NET Core. Speed demons rejoice!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-performance-hacks-async.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 27&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching Strategies Epic
&lt;/h3&gt;

&lt;p&gt;Slash load times with caching in ASP.NET Core—Redis and more for massive traffic. Accelerate now!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-caching-mastery-redis.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 28&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Fortification
&lt;/h3&gt;

&lt;p&gt;Armor against threats with OWASP best practices in ASP.NET Core. Bulletproof your code!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-security-fortification.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 29&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Mastery
&lt;/h3&gt;

&lt;p&gt;Catch bugs early with comprehensive testing in ASP.NET Core. Triumph in quality!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/testing-mastery-catch-bugs-early-with.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 30&lt;/p&gt;

&lt;h3&gt;
  
  
  Background Jobs Revolution
&lt;/h3&gt;

&lt;p&gt;Automate with background jobs in ASP.NET Core—emails, reports, and more. Grind no more!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/background-jobs-revolution-mastering.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 31&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-Time Magic: SignalR and gRPC
&lt;/h3&gt;

&lt;p&gt;Bring apps alive with SignalR chats and gRPC efficiency in ASP.NET Core. Interactive wonders!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/real-time-magic-signalr-and-grpc-bring.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Expert Level - Cloud, AI &amp;amp; Production
&lt;/h2&gt;

&lt;p&gt;Become a cloud-native expert with AI integration, microservices, and production deployment.&lt;/p&gt;

&lt;p&gt;Post 24&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Integration Boom
&lt;/h3&gt;

&lt;p&gt;Infuse AI with ML.NET and OpenAI in ASP.NET Core for predictive smarts. Future-proof your apps!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/ai-integration-boom-infusing-aspnet.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 25&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Domination
&lt;/h3&gt;

&lt;p&gt;Scale globally with Azure and AWS in ASP.NET Core—storage, hosting, and more. Sky-high success!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-cloud-domination-master.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 32&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment Domination
&lt;/h3&gt;

&lt;p&gt;Launch seamlessly with Docker and K8s in ASP.NET Core. From local to live!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-docker-kubernetes.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 33&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD Pipelines Epic
&lt;/h3&gt;

&lt;p&gt;Streamline workflows with CI/CD in ASP.NET Core. Efficiency unlocked!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/enterprise-grade-cicd-for-aspnet-core.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 34&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring and Logging Mastery
&lt;/h3&gt;

&lt;p&gt;Stay proactive with monitoring and logs in ASP.NET Core. Keep apps thriving!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-monitoring-logging-mastery.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 35&lt;/p&gt;

&lt;h3&gt;
  
  
  Future Trends in ASP.NET Core 2025
&lt;/h3&gt;

&lt;p&gt;Stay ahead with MAUI, AI, and trends shaping ASP.NET Core. Future-proof your skills!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-future-trends-2025-maui-ai.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 36&lt;/p&gt;

&lt;h3&gt;
  
  
  CQRS and MediatR Masterclass
&lt;/h3&gt;

&lt;p&gt;Solve business complexity with CQRS and MediatR in ASP.NET Core. Scalable elegance!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/cqrs-and-mediatr-masterclass-solve.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 37&lt;/p&gt;

&lt;h3&gt;
  
  
  Repository and Unit of Work Patterns
&lt;/h3&gt;

&lt;p&gt;Build testable data access with Repository patterns in ASP.NET Core. Pro-level abstraction!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/master-repository-unit-of-work-patterns.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 38&lt;/p&gt;

&lt;h3&gt;
  
  
  FluentValidation and AutoMapper
&lt;/h3&gt;

&lt;p&gt;Ensure clean data with FluentValidation and AutoMapper in ASP.NET Core. Robust and efficient!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-microservices-grpc-message.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 39&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices Foundations
&lt;/h3&gt;

&lt;p&gt;Architect microservices with gRPC and brokers in ASP.NET Core. Foundational mastery!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/aspnet-core-fluentvalidation-automapper.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post 40&lt;/p&gt;

&lt;h3&gt;
  
  
  Full-Stack ASP.NET Core Project
&lt;/h3&gt;

&lt;p&gt;Build a complete full-stack project in ASP.NET Core—AI, cloud, and more. Real-world hero!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freelearning365.com/2025/10/full-stack-aspnet-core-project-build-ai.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FreeLearning365&lt;/p&gt;

&lt;p&gt;Master ASP.NET Core with our comprehensive 40-part series designed to take you from beginner to cloud-native expert. Join thousands of developers who have transformed their careers with our real-world projects and professional training.&lt;/p&gt;

&lt;p&gt;Subscribe All Posts&lt;/p&gt;




&lt;p&gt;&lt;em&gt;© 2025 FreeLearning365.com - Your journey to ASP.NET Core mastery starts here.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dapper Deep Dive Part 8: Ultra-Fast Querying &amp; Mapping Secrets for ASP.NET Core Pros - FreeLearning365.com</title>
      <dc:creator>FreeLearning365.com</dc:creator>
      <pubDate>Thu, 16 Oct 2025 10:33:13 +0000</pubDate>
      <link>https://forem.com/freelearning365/dapper-deep-dive-part-8-ultra-fast-querying-mapping-secrets-for-aspnet-core-pros--3mjo</link>
      <guid>https://forem.com/freelearning365/dapper-deep-dive-part-8-ultra-fast-querying-mapping-secrets-for-aspnet-core-pros--3mjo</guid>
      <description>&lt;h2&gt;
  
  
  Dapper Deep Dive Part 8: Ultra-Fast Querying &amp;amp; Mapping Secrets for ASP.NET Core Pros - FreeLearning365.com
&lt;/h2&gt;

&lt;p&gt;Dapper Deep Dive: Speed up your apps with Dapper's ultra-fast querying and mapping in ASP.NET Core&lt;/p&gt;

&lt;p&gt;Module Sequence: Part 8 - Mastering Dapper for High-Performance Data Access&lt;br&gt;
Table of Contents&lt;br&gt;
Dapper Fundamentals and Setup&lt;/p&gt;

&lt;p&gt;Basic Query Operations and Mapping&lt;/p&gt;

&lt;p&gt;Advanced Query Techniques&lt;/p&gt;

&lt;p&gt;Performance Optimization Strategies&lt;/p&gt;

&lt;p&gt;Multi-Mapping and Complex Relationships&lt;/p&gt;

&lt;p&gt;Stored Procedures and Dynamic Parameters&lt;/p&gt;

&lt;p&gt;Bulk Operations and Performance&lt;/p&gt;

&lt;p&gt;Real-World Enterprise Scenarios&lt;/p&gt;

&lt;p&gt;Integration with ASP.NET Core&lt;/p&gt;

&lt;p&gt;Best Practices and Advanced Patterns&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dapper Fundamentals and Setup
What is Dapper and Why Use It?
Dapper is a simple object mapper for .NET that extends IDbConnection with useful methods for executing queries and mapping results to objects. It's known for its exceptional performance and minimal overhead.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Key Advantages:&lt;/p&gt;

&lt;p&gt;Nearly as fast as raw ADO.NET&lt;/p&gt;

&lt;p&gt;Easy to use and learn&lt;/p&gt;

&lt;p&gt;Minimal configuration required&lt;/p&gt;

&lt;p&gt;Flexible mapping capabilities&lt;/p&gt;

&lt;p&gt;Supports complex object graphs&lt;/p&gt;

&lt;p&gt;Project Setup and Configuration&lt;br&gt;
Program.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using Microsoft.Data.SqlClient;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;var builder = WebApplication.CreateBuilder(args);&lt;/p&gt;

&lt;p&gt;// Add services to container&lt;br&gt;
builder.Services.AddControllers();&lt;br&gt;
builder.Services.AddScoped(provider =&amp;gt;&lt;br&gt;
{&lt;br&gt;
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");&lt;br&gt;
    return new SqlConnection(connectionString);&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;/p&gt;

&lt;p&gt;var app = builder.Build();&lt;/p&gt;

&lt;p&gt;// Configure pipeline&lt;br&gt;
if (app.Environment.IsDevelopment())&lt;br&gt;
{&lt;br&gt;
    app.UseDeveloperExceptionPage();&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;app.UseRouting();&lt;br&gt;
app.MapControllers();&lt;/p&gt;

&lt;p&gt;app.Run();&lt;br&gt;
appsettings.json&lt;/p&gt;

&lt;p&gt;json&lt;br&gt;
{&lt;br&gt;
  "ConnectionStrings": {&lt;br&gt;
    "DefaultConnection": "Server=.;Database=DapperDemo;Trusted_Connection=true;TrustServerCertificate=true;"&lt;br&gt;
  },&lt;br&gt;
  "Logging": {&lt;br&gt;
    "LogLevel": {&lt;br&gt;
      "Default": "Information",&lt;br&gt;
      "Microsoft.AspNetCore": "Warning"&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Database Setup and Initialization&lt;br&gt;
DatabaseInitializer.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using Microsoft.Data.SqlClient;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Data&lt;br&gt;
{&lt;br&gt;
    public class DatabaseInitializer&lt;br&gt;
    {&lt;br&gt;
        private readonly string _connectionString;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public DatabaseInitializer(string connectionString)
    {
        _connectionString = connectionString;
    }

    public async Task InitializeDatabaseAsync()
    {
        using var connection = new SqlConnection(_connectionString);

        // Create database if not exists
        var createDbSql = @"
            IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'DapperDemo')
            BEGIN
                CREATE DATABASE DapperDemo;
            END";

        await connection.ExecuteAsync(createDbSql);

        // Switch to DapperDemo database
        connection.ConnectionString += "Database=DapperDemo;";
        await connection.OpenAsync();

        // Create tables
        await CreateTablesAsync(connection);
        await SeedSampleDataAsync(connection);
    }

    private async Task CreateTablesAsync(IDbConnection connection)
    {
        // Users table
        var createUsersTable = @"
            IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Users' AND xtype='U')
            CREATE TABLE Users (
                Id INT IDENTITY PRIMARY KEY,
                Username NVARCHAR(50) NOT NULL UNIQUE,
                Email NVARCHAR(100) NOT NULL UNIQUE,
                FirstName NVARCHAR(50) NOT NULL,
                LastName NVARCHAR(50) NOT NULL,
                DateOfBirth DATE NULL,
                CreatedAt DATETIME2 DEFAULT GETUTCDATE(),
                IsActive BIT DEFAULT 1
            )";

        // Products table
        var createProductsTable = @"
            IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Products' AND xtype='U')
            CREATE TABLE Products (
                Id INT IDENTITY PRIMARY KEY,
                Name NVARCHAR(100) NOT NULL,
                Description NVARCHAR(500) NULL,
                Price DECIMAL(18,2) NOT NULL,
                StockQuantity INT NOT NULL DEFAULT 0,
                Category NVARCHAR(50) NULL,
                CreatedAt DATETIME2 DEFAULT GETUTCDATE(),
                IsActive BIT DEFAULT 1
            )";

        // Orders table
        var createOrdersTable = @"
            IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Orders' AND xtype='U')
            CREATE TABLE Orders (
                Id INT IDENTITY PRIMARY KEY,
                UserId INT NOT NULL FOREIGN KEY REFERENCES Users(Id),
                OrderDate DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
                TotalAmount DECIMAL(18,2) NOT NULL,
                Status NVARCHAR(20) NOT NULL DEFAULT 'Pending',
                ShippingAddress NVARCHAR(200) NULL,
                CreatedAt DATETIME2 DEFAULT GETUTCDATE()
            )";

        // OrderItems table
        var createOrderItemsTable = @"
            IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='OrderItems' AND xtype='U')
            CREATE TABLE OrderItems (
                Id INT IDENTITY PRIMARY KEY,
                OrderId INT NOT NULL FOREIGN KEY REFERENCES Orders(Id),
                ProductId INT NOT NULL FOREIGN KEY REFERENCES Products(Id),
                Quantity INT NOT NULL,
                UnitPrice DECIMAL(18,2) NOT NULL,
                TotalPrice DECIMAL(18,2) NOT NULL
            )";

        await connection.ExecuteAsync(createUsersTable);
        await connection.ExecuteAsync(createProductsTable);
        await connection.ExecuteAsync(createOrdersTable);
        await connection.ExecuteAsync(createOrderItemsTable);
    }

    private async Task SeedSampleDataAsync(IDbConnection connection)
    {
        // Check if data already exists
        var userCount = await connection.ExecuteScalarAsync&amp;lt;int&amp;gt;("SELECT COUNT(*) FROM Users");
        if (userCount &amp;gt; 0) return;

        // Insert sample users
        var insertUsers = @"
            INSERT INTO Users (Username, Email, FirstName, LastName, DateOfBirth) VALUES
            ('john_doe', 'john@example.com', 'John', 'Doe', '1985-05-15'),
            ('jane_smith', 'jane@example.com', 'Jane', 'Smith', '1990-08-22'),
            ('bob_wilson', 'bob@example.com', 'Bob', 'Wilson', '1988-12-10'),
            ('alice_brown', 'alice@example.com', 'Alice', 'Brown', '1992-03-30')";

        // Insert sample products
        var insertProducts = @"
            INSERT INTO Products (Name, Description, Price, StockQuantity, Category) VALUES
            ('Laptop', 'High-performance laptop', 999.99, 50, 'Electronics'),
            ('Smartphone', 'Latest smartphone model', 699.99, 100, 'Electronics'),
            ('Headphones', 'Noise-cancelling headphones', 199.99, 75, 'Electronics'),
            ('Book', 'Programming guide', 39.99, 200, 'Books'),
            ('Desk Chair', 'Ergonomic office chair', 299.99, 30, 'Furniture')";

        await connection.ExecuteAsync(insertUsers);
        await connection.ExecuteAsync(insertProducts);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic Query Operations and Mapping
Entity Models
Models/User.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
namespace DapperDeepDive.Models&lt;br&gt;
{&lt;br&gt;
    public class User&lt;br&gt;
    {&lt;br&gt;
        public int Id { get; set; }&lt;br&gt;
        public string Username { get; set; } = string.Empty;&lt;br&gt;
        public string Email { get; set; } = string.Empty;&lt;br&gt;
        public string FirstName { get; set; } = string.Empty;&lt;br&gt;
        public string LastName { get; set; } = string.Empty;&lt;br&gt;
        public DateTime? DateOfBirth { get; set; }&lt;br&gt;
        public DateTime CreatedAt { get; set; }&lt;br&gt;
        public bool IsActive { get; set; }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Navigation properties
    public List&amp;lt;Order&amp;gt; Orders { get; set; } = new List&amp;lt;Order&amp;gt;();
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
    public string Category { get; set; } = string.Empty;
    public DateTime CreatedAt { get; set; }
    public bool IsActive { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; } = string.Empty;
    public string ShippingAddress { get; set; } = string.Empty;
    public DateTime CreatedAt { get; set; }

    // Navigation properties
    public User User { get; set; } = new User();
    public List&amp;lt;OrderItem&amp;gt; OrderItems { get; set; } = new List&amp;lt;OrderItem&amp;gt;();
}

public class OrderItem
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal TotalPrice { get; set; }

    // Navigation properties
    public Product Product { get; set; } = new Product();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Basic Repository Implementation&lt;br&gt;
Repositories/IUserRepository.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using DapperDeepDive.Models;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public interface IUserRepository&lt;br&gt;
    {&lt;br&gt;
        Task GetByIdAsync(int id);&lt;br&gt;
        Task&amp;gt; GetAllAsync();&lt;br&gt;
        Task GetByUsernameAsync(string username);&lt;br&gt;
        Task GetByEmailAsync(string email);&lt;br&gt;
        Task CreateAsync(User user);&lt;br&gt;
        Task UpdateAsync(User user);&lt;br&gt;
        Task DeleteAsync(int id);&lt;br&gt;
        Task ExistsAsync(int id);&lt;br&gt;
        Task GetCountAsync();&lt;br&gt;
    }&lt;br&gt;
}&lt;br&gt;
Repositories/UserRepository.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public class UserRepository : IUserRepository&lt;br&gt;
    {&lt;br&gt;
        private readonly IDbConnection _connection;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public UserRepository(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;User?&amp;gt; GetByIdAsync(int id)
    {
        const string sql = @"
            SELECT Id, Username, Email, FirstName, LastName, 
                   DateOfBirth, CreatedAt, IsActive
            FROM Users 
            WHERE Id = @Id AND IsActive = 1";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;User&amp;gt;(sql, new { Id = id });
    }

    public async Task&amp;lt;IEnumerable&amp;lt;User&amp;gt;&amp;gt; GetAllAsync()
    {
        const string sql = @"
            SELECT Id, Username, Email, FirstName, LastName, 
                   DateOfBirth, CreatedAt, IsActive
            FROM Users 
            WHERE IsActive = 1
            ORDER BY CreatedAt DESC";

        return await _connection.QueryAsync&amp;lt;User&amp;gt;(sql);
    }

    public async Task&amp;lt;User?&amp;gt; GetByUsernameAsync(string username)
    {
        const string sql = @"
            SELECT Id, Username, Email, FirstName, LastName, 
                   DateOfBirth, CreatedAt, IsActive
            FROM Users 
            WHERE Username = @Username AND IsActive = 1";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;User&amp;gt;(sql, new { Username = username });
    }

    public async Task&amp;lt;User?&amp;gt; GetByEmailAsync(string email)
    {
        const string sql = @"
            SELECT Id, Username, Email, FirstName, LastName, 
                   DateOfBirth, CreatedAt, IsActive
            FROM Users 
            WHERE Email = @Email AND IsActive = 1";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;User&amp;gt;(sql, new { Email = email });
    }

    public async Task&amp;lt;int&amp;gt; CreateAsync(User user)
    {
        const string sql = @"
            INSERT INTO Users (Username, Email, FirstName, LastName, DateOfBirth)
            OUTPUT INSERTED.Id
            VALUES (@Username, @Email, @FirstName, @LastName, @DateOfBirth)";

        return await _connection.ExecuteScalarAsync&amp;lt;int&amp;gt;(sql, user);
    }

    public async Task&amp;lt;bool&amp;gt; UpdateAsync(User user)
    {
        const string sql = @"
            UPDATE Users 
            SET Username = @Username, Email = @Email, 
                FirstName = @FirstName, LastName = @LastName,
                DateOfBirth = @DateOfBirth
            WHERE Id = @Id AND IsActive = 1";

        var affectedRows = await _connection.ExecuteAsync(sql, user);
        return affectedRows &amp;gt; 0;
    }

    public async Task&amp;lt;bool&amp;gt; DeleteAsync(int id)
    {
        const string sql = @"
            UPDATE Users 
            SET IsActive = 0 
            WHERE Id = @Id";

        var affectedRows = await _connection.ExecuteAsync(sql, new { Id = id });
        return affectedRows &amp;gt; 0;
    }

    public async Task&amp;lt;bool&amp;gt; ExistsAsync(int id)
    {
        const string sql = "SELECT 1 FROM Users WHERE Id = @Id AND IsActive = 1";
        var result = await _connection.ExecuteScalarAsync&amp;lt;int?&amp;gt;(sql, new { Id = id });
        return result.HasValue;
    }

    public async Task&amp;lt;int&amp;gt; GetCountAsync()
    {
        const string sql = "SELECT COUNT(*) FROM Users WHERE IsActive = 1";
        return await _connection.ExecuteScalarAsync&amp;lt;int&amp;gt;(sql);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Product Repository with Advanced Features&lt;br&gt;
Repositories/ProductRepository.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public interface IProductRepository&lt;br&gt;
    {&lt;br&gt;
        Task GetByIdAsync(int id);&lt;br&gt;
        Task&amp;gt; GetAllAsync();&lt;br&gt;
        Task&amp;gt; GetByCategoryAsync(string category);&lt;br&gt;
        Task&amp;gt; GetActiveProductsAsync();&lt;br&gt;
        Task&amp;gt; SearchProductsAsync(string searchTerm);&lt;br&gt;
        Task GetTotalInventoryValueAsync();&lt;br&gt;
        Task&amp;gt; GetProductCountByCategoryAsync();&lt;br&gt;
        Task CreateAsync(Product product);&lt;br&gt;
        Task UpdateAsync(Product product);&lt;br&gt;
        Task UpdateStockAsync(int productId, int newStockQuantity);&lt;br&gt;
        Task DeleteAsync(int id);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ProductRepository : IProductRepository
{
    private readonly IDbConnection _connection;

    public ProductRepository(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;Product?&amp;gt; GetByIdAsync(int id)
    {
        const string sql = @"
            SELECT Id, Name, Description, Price, StockQuantity, 
                   Category, CreatedAt, IsActive
            FROM Products 
            WHERE Id = @Id";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;Product&amp;gt;(sql, new { Id = id });
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetAllAsync()
    {
        const string sql = @"
            SELECT Id, Name, Description, Price, StockQuantity, 
                   Category, CreatedAt, IsActive
            FROM Products 
            ORDER BY CreatedAt DESC";

        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql);
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetByCategoryAsync(string category)
    {
        const string sql = @"
            SELECT Id, Name, Description, Price, StockQuantity, 
                   Category, CreatedAt, IsActive
            FROM Products 
            WHERE Category = @Category AND IsActive = 1
            ORDER BY Name";

        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql, new { Category = category });
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetActiveProductsAsync()
    {
        const string sql = @"
            SELECT Id, Name, Description, Price, StockQuantity, 
                   Category, CreatedAt, IsActive
            FROM Products 
            WHERE IsActive = 1 AND StockQuantity &amp;gt; 0
            ORDER BY Price DESC";

        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql);
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; SearchProductsAsync(string searchTerm)
    {
        const string sql = @"
            SELECT Id, Name, Description, Price, StockQuantity, 
                   Category, CreatedAt, IsActive
            FROM Products 
            WHERE (Name LIKE '%' + @SearchTerm + '%' 
                   OR Description LIKE '%' + @SearchTerm + '%')
                  AND IsActive = 1
            ORDER BY 
                CASE 
                    WHEN Name LIKE @SearchTerm + '%' THEN 1
                    WHEN Name LIKE '%' + @SearchTerm + '%' THEN 2
                    ELSE 3
                END,
                Name";

        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql, new { SearchTerm = searchTerm });
    }

    public async Task&amp;lt;decimal&amp;gt; GetTotalInventoryValueAsync()
    {
        const string sql = @"
            SELECT SUM(Price * StockQuantity) 
            FROM Products 
            WHERE IsActive = 1";

        return await _connection.ExecuteScalarAsync&amp;lt;decimal&amp;gt;(sql);
    }

    public async Task&amp;lt;Dictionary&amp;lt;string, int&amp;gt;&amp;gt; GetProductCountByCategoryAsync()
    {
        const string sql = @"
            SELECT Category, COUNT(*) as Count
            FROM Products 
            WHERE IsActive = 1
            GROUP BY Category
            ORDER BY Count DESC";

        var results = await _connection.QueryAsync&amp;lt;(string Category, int Count)&amp;gt;(sql);
        return results.ToDictionary(x =&amp;gt; x.Category, x =&amp;gt; x.Count);
    }

    public async Task&amp;lt;int&amp;gt; CreateAsync(Product product)
    {
        const string sql = @"
            INSERT INTO Products (Name, Description, Price, StockQuantity, Category)
            OUTPUT INSERTED.Id
            VALUES (@Name, @Description, @Price, @StockQuantity, @Category)";

        return await _connection.ExecuteScalarAsync&amp;lt;int&amp;gt;(sql, product);
    }

    public async Task&amp;lt;bool&amp;gt; UpdateAsync(Product product)
    {
        const string sql = @"
            UPDATE Products 
            SET Name = @Name, Description = @Description, 
                Price = @Price, StockQuantity = @StockQuantity,
                Category = @Category, IsActive = @IsActive
            WHERE Id = @Id";

        var affectedRows = await _connection.ExecuteAsync(sql, product);
        return affectedRows &amp;gt; 0;
    }

    public async Task&amp;lt;bool&amp;gt; UpdateStockAsync(int productId, int newStockQuantity)
    {
        const string sql = @"
            UPDATE Products 
            SET StockQuantity = @StockQuantity
            WHERE Id = @ProductId";

        var affectedRows = await _connection.ExecuteAsync(sql, 
            new { ProductId = productId, StockQuantity = newStockQuantity });

        return affectedRows &amp;gt; 0;
    }

    public async Task&amp;lt;bool&amp;gt; DeleteAsync(int id)
    {
        const string sql = "DELETE FROM Products WHERE Id = @Id";
        var affectedRows = await _connection.ExecuteAsync(sql, new { Id = id });
        return affectedRows &amp;gt; 0;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Advanced Query Techniques
Multiple Result Sets
Repositories/AdvancedUserRepository.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public interface IAdvancedUserRepository&lt;br&gt;
    {&lt;br&gt;
        Task&amp;lt;(User User, IEnumerable Orders)&amp;gt; GetUserWithOrdersAsync(int userId);&lt;br&gt;
        Task GetUserStatisticsAsync(int userId);&lt;br&gt;
        Task&amp;gt; GetUsersPaginatedAsync(int pageNumber, int pageSize);&lt;br&gt;
        Task&amp;gt; GetUsersWithOrdersAsync();&lt;br&gt;
        Task GetUserDynamicAsync(int userId);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AdvancedUserRepository : IAdvancedUserRepository
{
    private readonly IDbConnection _connection;

    public AdvancedUserRepository(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;(User User, IEnumerable&amp;lt;Order&amp;gt; Orders)&amp;gt; GetUserWithOrdersAsync(int userId)
    {
        const string sql = @"
            SELECT * FROM Users WHERE Id = @UserId;
            SELECT * FROM Orders WHERE UserId = @UserId ORDER BY OrderDate DESC;";

        using var multi = await _connection.QueryMultipleAsync(sql, new { UserId = userId });

        var user = await multi.ReadFirstOrDefaultAsync&amp;lt;User&amp;gt;();
        var orders = await multi.ReadAsync&amp;lt;Order&amp;gt;();

        return (user, orders);
    }

    public async Task&amp;lt;UserStatistics&amp;gt; GetUserStatisticsAsync(int userId)
    {
        const string sql = @"
            SELECT 
                COUNT(o.Id) as TotalOrders,
                SUM(o.TotalAmount) as TotalSpent,
                AVG(o.TotalAmount) as AverageOrderValue,
                MAX(o.OrderDate) as LastOrderDate,
                MIN(o.OrderDate) as FirstOrderDate
            FROM Users u
            LEFT JOIN Orders o ON u.Id = o.UserId
            WHERE u.Id = @UserId
            GROUP BY u.Id, u.Username";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;UserStatistics&amp;gt;(sql, new { UserId = userId });
    }

    public async Task&amp;lt;PaginatedResult&amp;lt;User&amp;gt;&amp;gt; GetUsersPaginatedAsync(int pageNumber, int pageSize)
    {
        var offset = (pageNumber - 1) * pageSize;

        const string sql = @"
            SELECT 
                Id, Username, Email, FirstName, LastName, 
                DateOfBirth, CreatedAt, IsActive
            FROM Users 
            WHERE IsActive = 1
            ORDER BY CreatedAt DESC
            OFFSET @Offset ROWS 
            FETCH NEXT @PageSize ROWS ONLY;

            SELECT COUNT(*) 
            FROM Users 
            WHERE IsActive = 1;";

        using var multi = await _connection.QueryMultipleAsync(sql, 
            new { Offset = offset, PageSize = pageSize });

        var users = await multi.ReadAsync&amp;lt;User&amp;gt;();
        var totalCount = await multi.ReadFirstAsync&amp;lt;int&amp;gt;();

        return new PaginatedResult&amp;lt;User&amp;gt;(users, totalCount, pageNumber, pageSize);
    }

    public async Task&amp;lt;IEnumerable&amp;lt;User&amp;gt;&amp;gt; GetUsersWithOrdersAsync()
    {
        const string sql = @"
            SELECT 
                u.*,
                o.Id, o.UserId, o.OrderDate, o.TotalAmount, o.Status, o.ShippingAddress
            FROM Users u
            LEFT JOIN Orders o ON u.Id = o.UserId
            WHERE u.IsActive = 1
            ORDER BY u.CreatedAt DESC, o.OrderDate DESC";

        var userDict = new Dictionary&amp;lt;int, User&amp;gt;();

        var users = await _connection.QueryAsync&amp;lt;User, Order, User&amp;gt;(
            sql,
            (user, order) =&amp;gt;
            {
                if (!userDict.TryGetValue(user.Id, out var userEntry))
                {
                    userEntry = user;
                    userEntry.Orders = new List&amp;lt;Order&amp;gt;();
                    userDict.Add(userEntry.Id, userEntry);
                }

                if (order != null)
                {
                    userEntry.Orders.Add(order);
                }

                return userEntry;
            },
            splitOn: "Id");

        return userDict.Values;
    }

    public async Task&amp;lt;dynamic&amp;gt; GetUserDynamicAsync(int userId)
    {
        const string sql = @"
            SELECT 
                u.Id, u.Username, u.Email,
                COUNT(o.Id) as OrderCount,
                SUM(o.TotalAmount) as TotalSpent
            FROM Users u
            LEFT JOIN Orders o ON u.Id = o.UserId
            WHERE u.Id = @UserId
            GROUP BY u.Id, u.Username, u.Email";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;dynamic&amp;gt;(sql, new { UserId = userId });
    }
}

public class UserStatistics
{
    public int TotalOrders { get; set; }
    public decimal TotalSpent { get; set; }
    public decimal AverageOrderValue { get; set; }
    public DateTime? LastOrderDate { get; set; }
    public DateTime? FirstOrderDate { get; set; }
}

public class PaginatedResult&amp;lt;T&amp;gt;
{
    public IEnumerable&amp;lt;T&amp;gt; Items { get; set; }
    public int TotalCount { get; set; }
    public int PageNumber { get; set; }
    public int PageSize { get; set; }
    public int TotalPages =&amp;gt; (int)Math.Ceiling(TotalCount / (double)PageSize);
    public bool HasPrevious =&amp;gt; PageNumber &amp;gt; 1;
    public bool HasNext =&amp;gt; PageNumber &amp;lt; TotalPages;

    public PaginatedResult(IEnumerable&amp;lt;T&amp;gt; items, int totalCount, int pageNumber, int pageSize)
    {
        Items = items;
        TotalCount = totalCount;
        PageNumber = pageNumber;
        PageSize = pageSize;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Advanced Query Building&lt;br&gt;
Services/QueryBuilderService.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;br&gt;
using System.Text;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IQueryBuilderService&lt;br&gt;
    {&lt;br&gt;
        Task&amp;gt; SearchProductsAsync(ProductSearchCriteria criteria);&lt;br&gt;
        Task&amp;gt; GetUsersByCriteriaAsync(UserSearchCriteria criteria);&lt;br&gt;
        string BuildProductSearchQuery(ProductSearchCriteria criteria, out DynamicParameters parameters);&lt;br&gt;
        string BuildUserSearchQuery(UserSearchCriteria criteria, out DynamicParameters parameters);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class QueryBuilderService : IQueryBuilderService
{
    private readonly IDbConnection _connection;

    public QueryBuilderService(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; SearchProductsAsync(ProductSearchCriteria criteria)
    {
        var query = BuildProductSearchQuery(criteria, out var parameters);
        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(query, parameters);
    }

    public async Task&amp;lt;IEnumerable&amp;lt;User&amp;gt;&amp;gt; GetUsersByCriteriaAsync(UserSearchCriteria criteria)
    {
        var query = BuildUserSearchQuery(criteria, out var parameters);
        return await _connection.QueryAsync&amp;lt;User&amp;gt;(query, parameters);
    }

    public string BuildProductSearchQuery(ProductSearchCriteria criteria, out DynamicParameters parameters)
    {
        parameters = new DynamicParameters();
        var sqlBuilder = new StringBuilder("SELECT * FROM Products WHERE 1=1");

        if (!string.IsNullOrEmpty(criteria.Name))
        {
            sqlBuilder.Append(" AND Name LIKE '%' + @Name + '%'");
            parameters.Add("Name", criteria.Name);
        }

        if (!string.IsNullOrEmpty(criteria.Category))
        {
            sqlBuilder.Append(" AND Category = @Category");
            parameters.Add("Category", criteria.Category);
        }

        if (criteria.MinPrice.HasValue)
        {
            sqlBuilder.Append(" AND Price &amp;gt;= @MinPrice");
            parameters.Add("MinPrice", criteria.MinPrice.Value);
        }

        if (criteria.MaxPrice.HasValue)
        {
            sqlBuilder.Append(" AND Price &amp;lt;= @MaxPrice");
            parameters.Add("MaxPrice", criteria.MaxPrice.Value);
        }

        if (criteria.InStockOnly)
        {
            sqlBuilder.Append(" AND StockQuantity &amp;gt; 0");
        }

        if (criteria.IsActive.HasValue)
        {
            sqlBuilder.Append(" AND IsActive = @IsActive");
            parameters.Add("IsActive", criteria.IsActive.Value);
        }

        // Order by
        sqlBuilder.Append(" ORDER BY ");
        sqlBuilder.Append(criteria.SortBy?.ToLower() switch
        {
            "name" =&amp;gt; "Name",
            "price" =&amp;gt; "Price",
            "created" =&amp;gt; "CreatedAt",
            _ =&amp;gt; "CreatedAt"
        });

        sqlBuilder.Append(criteria.SortDescending ? " DESC" : " ASC");

        // Pagination
        if (criteria.PageSize &amp;gt; 0 &amp;amp;&amp;amp; criteria.PageNumber &amp;gt; 0)
        {
            var offset = (criteria.PageNumber - 1) * criteria.PageSize;
            sqlBuilder.Append(" OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY");
            parameters.Add("Offset", offset);
            parameters.Add("PageSize", criteria.PageSize);
        }

        return sqlBuilder.ToString();
    }

    public string BuildUserSearchQuery(UserSearchCriteria criteria, out DynamicParameters parameters)
    {
        parameters = new DynamicParameters();
        var sqlBuilder = new StringBuilder("SELECT * FROM Users WHERE 1=1");

        if (!string.IsNullOrEmpty(criteria.Username))
        {
            sqlBuilder.Append(" AND Username LIKE '%' + @Username + '%'");
            parameters.Add("Username", criteria.Username);
        }

        if (!string.IsNullOrEmpty(criteria.Email))
        {
            sqlBuilder.Append(" AND Email LIKE '%' + @Email + '%'");
            parameters.Add("Email", criteria.Email);
        }

        if (!string.IsNullOrEmpty(criteria.FirstName))
        {
            sqlBuilder.Append(" AND FirstName LIKE '%' + @FirstName + '%'");
            parameters.Add("FirstName", criteria.FirstName);
        }

        if (!string.IsNullOrEmpty(criteria.LastName))
        {
            sqlBuilder.Append(" AND LastName LIKE '%' + @LastName + '%'");
            parameters.Add("LastName", criteria.LastName);
        }

        if (criteria.CreatedAfter.HasValue)
        {
            sqlBuilder.Append(" AND CreatedAt &amp;gt;= @CreatedAfter");
            parameters.Add("CreatedAfter", criteria.CreatedAfter.Value);
        }

        if (criteria.CreatedBefore.HasValue)
        {
            sqlBuilder.Append(" AND CreatedAt &amp;lt;= @CreatedBefore");
            parameters.Add("CreatedBefore", criteria.CreatedBefore.Value);
        }

        if (criteria.IsActive.HasValue)
        {
            sqlBuilder.Append(" AND IsActive = @IsActive");
            parameters.Add("IsActive", criteria.IsActive.Value);
        }

        // Order by
        sqlBuilder.Append(" ORDER BY ");
        sqlBuilder.Append(criteria.SortBy?.ToLower() switch
        {
            "username" =&amp;gt; "Username",
            "email" =&amp;gt; "Email",
            "created" =&amp;gt; "CreatedAt",
            _ =&amp;gt; "CreatedAt"
        });

        sqlBuilder.Append(criteria.SortDescending ? " DESC" : " ASC");

        // Pagination
        if (criteria.PageSize &amp;gt; 0 &amp;amp;&amp;amp; criteria.PageNumber &amp;gt; 0)
        {
            var offset = (criteria.PageNumber - 1) * criteria.PageSize;
            sqlBuilder.Append(" OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY");
            parameters.Add("Offset", offset);
            parameters.Add("PageSize", criteria.PageSize);
        }

        return sqlBuilder.ToString();
    }
}

public class ProductSearchCriteria
{
    public string? Name { get; set; }
    public string? Category { get; set; }
    public decimal? MinPrice { get; set; }
    public decimal? MaxPrice { get; set; }
    public bool InStockOnly { get; set; } = false;
    public bool? IsActive { get; set; } = true;
    public string? SortBy { get; set; } = "created";
    public bool SortDescending { get; set; } = true;
    public int PageNumber { get; set; } = 1;
    public int PageSize { get; set; } = 20;
}

public class UserSearchCriteria
{
    public string? Username { get; set; }
    public string? Email { get; set; }
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public DateTime? CreatedAfter { get; set; }
    public DateTime? CreatedBefore { get; set; }
    public bool? IsActive { get; set; } = true;
    public string? SortBy { get; set; } = "created";
    public bool SortDescending { get; set; } = true;
    public int PageNumber { get; set; } = 1;
    public int PageSize { get; set; } = 20;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performance Optimization Strategies
Connection Management and Pooling
Services/ConnectionFactory.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Microsoft.Data.SqlClient;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IConnectionFactory&lt;br&gt;
    {&lt;br&gt;
        IDbConnection CreateConnection();&lt;br&gt;
        Task CreateOpenConnectionAsync();&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ConnectionFactory : IConnectionFactory
{
    private readonly string _connectionString;

    public ConnectionFactory(string connectionString)
    {
        _connectionString = connectionString;
    }

    public IDbConnection CreateConnection()
    {
        var connection = new SqlConnection(_connectionString);

        // Configure connection for optimal performance
        var builder = new SqlConnectionStringBuilder(_connectionString)
        {
            MaxPoolSize = 100,
            MinPoolSize = 0,
            Pooling = true,
            ConnectionTimeout = 30,
            CommandTimeout = 30
        };

        connection.ConnectionString = builder.ConnectionString;
        return connection;
    }

    public async Task&amp;lt;IDbConnection&amp;gt; CreateOpenConnectionAsync()
    {
        var connection = CreateConnection();
        await connection.OpenAsync();
        return connection;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Performance Monitoring&lt;br&gt;
Services/PerformanceMonitor.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using System.Data;&lt;br&gt;
using System.Diagnostics;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IPerformanceMonitor&lt;br&gt;
    {&lt;br&gt;
        Task MonitorQueryAsync(Func&amp;gt; query, string operationName);&lt;br&gt;
        Task MonitorActionAsync(Func action, string operationName);&lt;br&gt;
        void LogPerformanceMetrics(string operation, TimeSpan duration, int? recordsAffected = null);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class PerformanceMonitor : IPerformanceMonitor
{
    private readonly ILogger&amp;lt;PerformanceMonitor&amp;gt; _logger;

    public PerformanceMonitor(ILogger&amp;lt;PerformanceMonitor&amp;gt; logger)
    {
        _logger = logger;
    }

    public async Task&amp;lt;T&amp;gt; MonitorQueryAsync&amp;lt;T&amp;gt;(Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; query, string operationName)
    {
        var stopwatch = Stopwatch.StartNew();
        try
        {
            var result = await query();
            stopwatch.Stop();

            LogPerformanceMetrics(operationName, stopwatch.Elapsed);
            return result;
        }
        catch (Exception ex)
        {
            stopwatch.Stop();
            _logger.LogError(ex, "Error executing {OperationName} after {ElapsedMs}ms", 
                operationName, stopwatch.ElapsedMilliseconds);
            throw;
        }
    }

    public async Task MonitorActionAsync(Func&amp;lt;Task&amp;gt; action, string operationName)
    {
        var stopwatch = Stopwatch.StartNew();
        try
        {
            await action();
            stopwatch.Stop();

            LogPerformanceMetrics(operationName, stopwatch.Elapsed);
        }
        catch (Exception ex)
        {
            stopwatch.Stop();
            _logger.LogError(ex, "Error executing {OperationName} after {ElapsedMs}ms", 
                operationName, stopwatch.ElapsedMilliseconds);
            throw;
        }
    }

    public void LogPerformanceMetrics(string operation, TimeSpan duration, int? recordsAffected = null)
    {
        var logMessage = $"Operation '{operation}' completed in {duration.TotalMilliseconds}ms";
        if (recordsAffected.HasValue)
        {
            logMessage += $", Records affected: {recordsAffected.Value}";
        }

        if (duration.TotalMilliseconds &amp;gt; 1000)
        {
            _logger.LogWarning(logMessage);
        }
        else if (duration.TotalMilliseconds &amp;gt; 100)
        {
            _logger.LogInformation(logMessage);
        }
        else
        {
            _logger.LogDebug(logMessage);
        }
    }
}

// Performance-optimized repository
public class OptimizedProductRepository
{
    private readonly IDbConnection _connection;
    private readonly IPerformanceMonitor _performanceMonitor;

    public OptimizedProductRepository(IDbConnection connection, IPerformanceMonitor performanceMonitor)
    {
        _connection = connection;
        _performanceMonitor = performanceMonitor;
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetProductsOptimizedAsync()
    {
        return await _performanceMonitor.MonitorQueryAsync(
            async () =&amp;gt;
            {
                const string sql = @"
                    SELECT 
                        Id, Name, Price, StockQuantity, Category
                    FROM Products 
                    WHERE IsActive = 1
                    ORDER BY CreatedAt DESC";

                return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql);
            },
            "GetProductsOptimized");
    }

    public async Task&amp;lt;Product?&amp;gt; GetProductByIdOptimizedAsync(int id)
    {
        return await _performanceMonitor.MonitorQueryAsync(
            async () =&amp;gt;
            {
                const string sql = @"
                    SELECT 
                        Id, Name, Price, StockQuantity, Category
                    FROM Products 
                    WHERE Id = @Id";

                return await _connection.QueryFirstOrDefaultAsync&amp;lt;Product&amp;gt;(sql, new { Id = id });
            },
            "GetProductByIdOptimized");
    }

    public async Task&amp;lt;bool&amp;gt; BulkUpdateProductsAsync(IEnumerable&amp;lt;Product&amp;gt; products)
    {
        return await _performanceMonitor.MonitorQueryAsync(
            async () =&amp;gt;
            {
                const string sql = @"
                    UPDATE Products 
                    SET Price = @Price, StockQuantity = @StockQuantity
                    WHERE Id = @Id";

                var affectedRows = await _connection.ExecuteAsync(sql, products);
                return affectedRows &amp;gt; 0;
            },
            "BulkUpdateProducts");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Caching Strategies&lt;br&gt;
Services/CacheService.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Microsoft.Extensions.Caching.Memory;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface ICacheService&lt;br&gt;
    {&lt;br&gt;
        Task GetOrCreateAsync(string key, Func&amp;gt; factory, TimeSpan? expiration = null);&lt;br&gt;
        void Remove(string key);&lt;br&gt;
        void Clear();&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CacheService : ICacheService
{
    private readonly IMemoryCache _memoryCache;
    private readonly ILogger&amp;lt;CacheService&amp;gt; _logger;

    public CacheService(IMemoryCache memoryCache, ILogger&amp;lt;CacheService&amp;gt; logger)
    {
        _memoryCache = memoryCache;
        _logger = logger;
    }

    public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, TimeSpan? expiration = null)
    {
        if (_memoryCache.TryGetValue(key, out T cachedValue))
        {
            _logger.LogDebug("Cache hit for key: {Key}", key);
            return cachedValue;
        }

        _logger.LogDebug("Cache miss for key: {Key}", key);
        var value = await factory();

        var cacheOptions = new MemoryCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = expiration ?? TimeSpan.FromMinutes(5)
        };

        _memoryCache.Set(key, value, cacheOptions);
        return value;
    }

    public void Remove(string key)
    {
        _memoryCache.Remove(key);
        _logger.LogDebug("Cache removed for key: {Key}", key);
    }

    public void Clear()
    {
        // Note: IMemoryCache doesn't have a Clear method by default
        // This would need to be implemented with a custom cache implementation
        // For now, we'll log a warning
        _logger.LogWarning("Clear operation not supported by default IMemoryCache");
    }
}

// Cached repository example
public class CachedProductRepository
{
    private readonly IProductRepository _productRepository;
    private readonly ICacheService _cacheService;

    public CachedProductRepository(IProductRepository productRepository, ICacheService cacheService)
    {
        _productRepository = productRepository;
        _cacheService = cacheService;
    }

    public async Task&amp;lt;Product?&amp;gt; GetByIdAsync(int id)
    {
        var cacheKey = $"product_{id}";
        return await _cacheService.GetOrCreateAsync(cacheKey,
            () =&amp;gt; _productRepository.GetByIdAsync(id),
            TimeSpan.FromMinutes(10));
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetByCategoryAsync(string category)
    {
        var cacheKey = $"products_category_{category}";
        return await _cacheService.GetOrCreateAsync(cacheKey,
            () =&amp;gt; _productRepository.GetByCategoryAsync(category),
            TimeSpan.FromMinutes(5));
    }

    public async Task&amp;lt;bool&amp;gt; UpdateAsync(Product product)
    {
        var result = await _productRepository.UpdateAsync(product);
        if (result)
        {
            // Invalidate cache for this product
            _cacheService.Remove($"product_{product.Id}");
            // Invalidate category cache as well
            _cacheService.Remove($"products_category_{product.Category}");
        }
        return result;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multi-Mapping and Complex Relationships
One-to-Many Relationships
Repositories/OrderRepository.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public interface IOrderRepository&lt;br&gt;
    {&lt;br&gt;
        Task GetOrderWithDetailsAsync(int orderId);&lt;br&gt;
        Task&amp;gt; GetUserOrdersWithDetailsAsync(int userId);&lt;br&gt;
        Task GetOrderSummaryAsync(int orderId);&lt;br&gt;
        Task CreateOrderWithItemsAsync(Order order, List items);&lt;br&gt;
        Task UpdateOrderStatusAsync(int orderId, string status);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class OrderRepository : IOrderRepository
{
    private readonly IDbConnection _connection;

    public OrderRepository(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;Order?&amp;gt; GetOrderWithDetailsAsync(int orderId)
    {
        const string sql = @"
            SELECT 
                o.*,
                u.*,
                oi.*,
                p.*
            FROM Orders o
            INNER JOIN Users u ON o.UserId = u.Id
            LEFT JOIN OrderItems oi ON o.Id = oi.OrderId
            LEFT JOIN Products p ON oi.ProductId = p.Id
            WHERE o.Id = @OrderId
            ORDER BY oi.Id";

        var orderDict = new Dictionary&amp;lt;int, Order&amp;gt;();

        var order = await _connection.QueryAsync&amp;lt;Order, User, OrderItem, Product, Order&amp;gt;(
            sql,
            (order, user, orderItem, product) =&amp;gt;
            {
                if (!orderDict.TryGetValue(order.Id, out var orderEntry))
                {
                    orderEntry = order;
                    orderEntry.User = user;
                    orderEntry.OrderItems = new List&amp;lt;OrderItem&amp;gt;();
                    orderDict.Add(orderEntry.Id, orderEntry);
                }

                if (orderItem != null)
                {
                    orderItem.Product = product;
                    orderEntry.OrderItems.Add(orderItem);
                }

                return orderEntry;
            },
            new { OrderId = orderId },
            splitOn: "Id,Id,Id");

        return orderDict.Values.FirstOrDefault();
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Order&amp;gt;&amp;gt; GetUserOrdersWithDetailsAsync(int userId)
    {
        const string sql = @"
            SELECT 
                o.*,
                oi.*,
                p.*
            FROM Orders o
            LEFT JOIN OrderItems oi ON o.Id = oi.OrderId
            LEFT JOIN Products p ON oi.ProductId = p.Id
            WHERE o.UserId = @UserId
            ORDER BY o.OrderDate DESC, oi.Id";

        var orderDict = new Dictionary&amp;lt;int, Order&amp;gt;();

        var orders = await _connection.QueryAsync&amp;lt;Order, OrderItem, Product, Order&amp;gt;(
            sql,
            (order, orderItem, product) =&amp;gt;
            {
                if (!orderDict.TryGetValue(order.Id, out var orderEntry))
                {
                    orderEntry = order;
                    orderEntry.OrderItems = new List&amp;lt;OrderItem&amp;gt;();
                    orderDict.Add(orderEntry.Id, orderEntry);
                }

                if (orderItem != null)
                {
                    orderItem.Product = product;
                    orderEntry.OrderItems.Add(orderItem);
                }

                return orderEntry;
            },
            new { UserId = userId },
            splitOn: "Id,Id");

        return orderDict.Values;
    }

    public async Task&amp;lt;OrderSummary&amp;gt; GetOrderSummaryAsync(int orderId)
    {
        const string sql = @"
            SELECT 
                o.Id,
                o.OrderDate,
                o.TotalAmount,
                o.Status,
                u.Username,
                u.Email,
                COUNT(oi.Id) as ItemCount,
                SUM(oi.Quantity) as TotalQuantity
            FROM Orders o
            INNER JOIN Users u ON o.UserId = u.Id
            LEFT JOIN OrderItems oi ON o.Id = oi.OrderId
            WHERE o.Id = @OrderId
            GROUP BY o.Id, o.OrderDate, o.TotalAmount, o.Status, u.Username, u.Email";

        return await _connection.QueryFirstOrDefaultAsync&amp;lt;OrderSummary&amp;gt;(sql, new { OrderId = orderId });
    }

    public async Task&amp;lt;int&amp;gt; CreateOrderWithItemsAsync(Order order, List&amp;lt;OrderItem&amp;gt; items)
    {
        using var transaction = _connection.BeginTransaction();

        try
        {
            // Insert order
            const string orderSql = @"
                INSERT INTO Orders (UserId, OrderDate, TotalAmount, Status, ShippingAddress)
                OUTPUT INSERTED.Id
                VALUES (@UserId, @OrderDate, @TotalAmount, @Status, @ShippingAddress)";

            var orderId = await _connection.ExecuteScalarAsync&amp;lt;int&amp;gt;(orderSql, order, transaction);

            // Insert order items
            const string itemsSql = @"
                INSERT INTO OrderItems (OrderId, ProductId, Quantity, UnitPrice, TotalPrice)
                VALUES (@OrderId, @ProductId, @Quantity, @UnitPrice, @TotalPrice)";

            foreach (var item in items)
            {
                item.OrderId = orderId;
                await _connection.ExecuteAsync(itemsSql, item, transaction);
            }

            transaction.Commit();
            return orderId;
        }
        catch
        {
            transaction.Rollback();
            throw;
        }
    }

    public async Task&amp;lt;bool&amp;gt; UpdateOrderStatusAsync(int orderId, string status)
    {
        const string sql = "UPDATE Orders SET Status = @Status WHERE Id = @OrderId";
        var affectedRows = await _connection.ExecuteAsync(sql, 
            new { OrderId = orderId, Status = status });

        return affectedRows &amp;gt; 0;
    }
}

public class OrderSummary
{
    public int Id { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public int ItemCount { get; set; }
    public int TotalQuantity { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Many-to-Many Relationships&lt;br&gt;
Repositories/TagRepository.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public class Tag&lt;br&gt;
    {&lt;br&gt;
        public int Id { get; set; }&lt;br&gt;
        public string Name { get; set; } = string.Empty;&lt;br&gt;
        public string Description { get; set; } = string.Empty;&lt;br&gt;
        public DateTime CreatedAt { get; set; }&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ProductTag
{
    public int ProductId { get; set; }
    public int TagId { get; set; }
    public DateTime AssociatedAt { get; set; }
}

public interface ITagRepository
{
    Task&amp;lt;IEnumerable&amp;lt;Tag&amp;gt;&amp;gt; GetProductTagsAsync(int productId);
    Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetProductsByTagAsync(int tagId);
    Task&amp;lt;bool&amp;gt; AddTagToProductAsync(int productId, int tagId);
    Task&amp;lt;bool&amp;gt; RemoveTagFromProductAsync(int productId, int tagId);
    Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetProductsByMultipleTagsAsync(IEnumerable&amp;lt;int&amp;gt; tagIds);
}

public class TagRepository : ITagRepository
{
    private readonly IDbConnection _connection;

    public TagRepository(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Tag&amp;gt;&amp;gt; GetProductTagsAsync(int productId)
    {
        const string sql = @"
            SELECT t.*
            FROM Tags t
            INNER JOIN ProductTags pt ON t.Id = pt.TagId
            WHERE pt.ProductId = @ProductId
            ORDER BY t.Name";

        return await _connection.QueryAsync&amp;lt;Tag&amp;gt;(sql, new { ProductId = productId });
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetProductsByTagAsync(int tagId)
    {
        const string sql = @"
            SELECT p.*
            FROM Products p
            INNER JOIN ProductTags pt ON p.Id = pt.ProductId
            WHERE pt.TagId = @TagId AND p.IsActive = 1
            ORDER BY p.Name";

        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql, new { TagId = tagId });
    }

    public async Task&amp;lt;bool&amp;gt; AddTagToProductAsync(int productId, int tagId)
    {
        const string sql = @"
            INSERT INTO ProductTags (ProductId, TagId, AssociatedAt)
            VALUES (@ProductId, @TagId, GETUTCDATE())";

        try
        {
            var affectedRows = await _connection.ExecuteAsync(sql, 
                new { ProductId = productId, TagId = tagId });

            return affectedRows &amp;gt; 0;
        }
        catch (SqlException ex) when (ex.Number == 2627) // Primary key violation
        {
            // Tag already associated with product
            return false;
        }
    }

    public async Task&amp;lt;bool&amp;gt; RemoveTagFromProductAsync(int productId, int tagId)
    {
        const string sql = @"
            DELETE FROM ProductTags 
            WHERE ProductId = @ProductId AND TagId = @TagId";

        var affectedRows = await _connection.ExecuteAsync(sql, 
            new { ProductId = productId, TagId = tagId });

        return affectedRows &amp;gt; 0;
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetProductsByMultipleTagsAsync(IEnumerable&amp;lt;int&amp;gt; tagIds)
    {
        const string sql = @"
            SELECT p.*
            FROM Products p
            WHERE p.Id IN (
                SELECT pt.ProductId
                FROM ProductTags pt
                WHERE pt.TagId IN @TagIds
                GROUP BY pt.ProductId
                HAVING COUNT(DISTINCT pt.TagId) = @TagCount
            ) AND p.IsActive = 1
            ORDER BY p.Name";

        var tagIdList = tagIds.ToList();
        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql, 
            new { TagIds = tagIdList, TagCount = tagIdList.Count });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stored Procedures and Dynamic Parameters
Stored Procedure Integration
Repositories/StoredProcedureRepository.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Repositories&lt;br&gt;
{&lt;br&gt;
    public interface IStoredProcedureRepository&lt;br&gt;
    {&lt;br&gt;
        Task&amp;gt; GetTopSellingProductsAsync(int count);&lt;br&gt;
        Task GetUserLifetimeValueAsync(int userId);&lt;br&gt;
        Task&amp;gt; SearchUsersAdvancedAsync(UserSearchParameters parameters);&lt;br&gt;
        Task GenerateSalesReportAsync(DateTime startDate, DateTime endDate);&lt;br&gt;
        Task ArchiveOldOrdersAsync(DateTime cutoffDate);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class StoredProcedureRepository : IStoredProcedureRepository
{
    private readonly IDbConnection _connection;

    public StoredProcedureRepository(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetTopSellingProductsAsync(int count)
    {
        const string sql = "EXEC GetTopSellingProducts @Count";
        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql, new { Count = count });
    }

    public async Task&amp;lt;decimal&amp;gt; GetUserLifetimeValueAsync(int userId)
    {
        const string sql = "EXEC GetUserLifetimeValue @UserId";
        return await _connection.ExecuteScalarAsync&amp;lt;decimal&amp;gt;(sql, new { UserId = userId });
    }

    public async Task&amp;lt;IEnumerable&amp;lt;User&amp;gt;&amp;gt; SearchUsersAdvancedAsync(UserSearchParameters parameters)
    {
        var dynamicParams = new DynamicParameters();
        dynamicParams.Add("@SearchTerm", parameters.SearchTerm);
        dynamicParams.Add("@MinOrderCount", parameters.MinOrderCount);
        dynamicParams.Add("@MinTotalSpent", parameters.MinTotalSpent);
        dynamicParams.Add("@StartDate", parameters.StartDate);
        dynamicParams.Add("@EndDate", parameters.EndDate);
        dynamicParams.Add("@PageNumber", parameters.PageNumber);
        dynamicParams.Add("@PageSize", parameters.PageSize);

        const string sql = "EXEC SearchUsersAdvanced @SearchTerm, @MinOrderCount, @MinTotalSpent, @StartDate, @EndDate, @PageNumber, @PageSize";

        return await _connection.QueryAsync&amp;lt;User&amp;gt;(sql, dynamicParams);
    }

    public async Task&amp;lt;SalesReport&amp;gt; GenerateSalesReportAsync(DateTime startDate, DateTime endDate)
    {
        const string sql = "EXEC GenerateSalesReport @StartDate, @EndDate";

        using var multi = await _connection.QueryMultipleAsync(sql, 
            new { StartDate = startDate, EndDate = endDate });

        var report = await multi.ReadFirstAsync&amp;lt;SalesReport&amp;gt;();
        report.DailySales = await multi.ReadAsync&amp;lt;DailySales&amp;gt;();
        report.TopProducts = await multi.ReadAsync&amp;lt;TopProduct&amp;gt;();

        return report;
    }

    public async Task&amp;lt;bool&amp;gt; ArchiveOldOrdersAsync(DateTime cutoffDate)
    {
        const string sql = "EXEC ArchiveOldOrders @CutoffDate";
        var affectedRows = await _connection.ExecuteAsync(sql, new { CutoffDate = cutoffDate });
        return affectedRows &amp;gt; 0;
    }
}

public class UserSearchParameters
{
    public string? SearchTerm { get; set; }
    public int? MinOrderCount { get; set; }
    public decimal? MinTotalSpent { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public int PageNumber { get; set; } = 1;
    public int PageSize { get; set; } = 20;
}

public class SalesReport
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int TotalOrders { get; set; }
    public decimal TotalRevenue { get; set; }
    public decimal AverageOrderValue { get; set; }
    public int UniqueCustomers { get; set; }
    public IEnumerable&amp;lt;DailySales&amp;gt; DailySales { get; set; } = new List&amp;lt;DailySales&amp;gt;();
    public IEnumerable&amp;lt;TopProduct&amp;gt; TopProducts { get; set; } = new List&amp;lt;TopProduct&amp;gt;();
}

public class DailySales
{
    public DateTime Date { get; set; }
    public int OrderCount { get; set; }
    public decimal TotalRevenue { get; set; }
}

public class TopProduct
{
    public int ProductId { get; set; }
    public string ProductName { get; set; } = string.Empty;
    public int QuantitySold { get; set; }
    public decimal TotalRevenue { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Dynamic Parameters and Output Parameters&lt;br&gt;
Services/DynamicParameterService.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IDynamicParameterService&lt;br&gt;
    {&lt;br&gt;
        Task&amp;lt;(int TotalRecords, IEnumerable Users)&amp;gt; GetUsersWithOutputParameterAsync(&lt;br&gt;
            int pageNumber, int pageSize);&lt;br&gt;
        Task CalculateOrderTotalWithOutputAsync(int orderId);&lt;br&gt;
        Task RegisterUserWithValidationAsync(UserRegistration registration);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class DynamicParameterService : IDynamicParameterService
{
    private readonly IDbConnection _connection;

    public DynamicParameterService(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;(int TotalRecords, IEnumerable&amp;lt;User&amp;gt; Users)&amp;gt; GetUsersWithOutputParameterAsync(
        int pageNumber, int pageSize)
    {
        var parameters = new DynamicParameters();
        parameters.Add("@PageNumber", pageNumber);
        parameters.Add("@PageSize", pageSize);
        parameters.Add("@TotalRecords", dbType: DbType.Int32, direction: ParameterDirection.Output);

        const string sql = @"
            SELECT 
                Id, Username, Email, FirstName, LastName
            FROM Users 
            WHERE IsActive = 1
            ORDER BY CreatedAt DESC
            OFFSET (@PageNumber - 1) * @PageSize ROWS 
            FETCH NEXT @PageSize ROWS ONLY;

            SELECT @TotalRecords = COUNT(*) FROM Users WHERE IsActive = 1;";

        using var multi = await _connection.QueryMultipleAsync(sql, parameters);

        var users = await multi.ReadAsync&amp;lt;User&amp;gt;();
        var totalRecords = parameters.Get&amp;lt;int&amp;gt;("@TotalRecords");

        return (totalRecords, users);
    }

    public async Task&amp;lt;decimal&amp;gt; CalculateOrderTotalWithOutputAsync(int orderId)
    {
        var parameters = new DynamicParameters();
        parameters.Add("@OrderId", orderId);
        parameters.Add("@TotalAmount", dbType: DbType.Decimal, 
            direction: ParameterDirection.Output, size: 18);

        await _connection.ExecuteAsync(
            "CalculateOrderTotal", 
            parameters, 
            commandType: CommandType.StoredProcedure);

        return parameters.Get&amp;lt;decimal&amp;gt;("@TotalAmount");
    }

    public async Task&amp;lt;bool&amp;gt; RegisterUserWithValidationAsync(UserRegistration registration)
    {
        var parameters = new DynamicParameters();
        parameters.Add("@Username", registration.Username);
        parameters.Add("@Email", registration.Email);
        parameters.Add("@FirstName", registration.FirstName);
        parameters.Add("@LastName", registration.LastName);
        parameters.Add("@PasswordHash", registration.PasswordHash);
        parameters.Add("@IsSuccess", dbType: DbType.Boolean, direction: ParameterDirection.Output);
        parameters.Add("@ErrorMessage", dbType: DbType.String, direction: ParameterDirection.Output, size: 500);

        await _connection.ExecuteAsync(
            "RegisterUser", 
            parameters, 
            commandType: CommandType.StoredProcedure);

        var isSuccess = parameters.Get&amp;lt;bool&amp;gt;("@IsSuccess");
        var errorMessage = parameters.Get&amp;lt;string&amp;gt;("@ErrorMessage");

        if (!isSuccess &amp;amp;&amp;amp; !string.IsNullOrEmpty(errorMessage))
        {
            throw new InvalidOperationException(errorMessage);
        }

        return isSuccess;
    }
}

public class UserRegistration
{
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string PasswordHash { get; set; } = string.Empty;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bulk Operations and Performance
Bulk Insert and Update Operations
Services/BulkOperationService.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;br&gt;
using Microsoft.Data.SqlClient;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IBulkOperationService&lt;br&gt;
    {&lt;br&gt;
        Task BulkInsertProductsAsync(IEnumerable products);&lt;br&gt;
        Task BulkUpdateProductPricesAsync(IEnumerable updates);&lt;br&gt;
        Task BulkMergeProductsAsync(IEnumerable products);&lt;br&gt;
        Task BulkInsertUsersAsync(IEnumerable users);&lt;br&gt;
        Task ExecuteBulkOperationsAsync(BulkOperationRequest request);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class BulkOperationService : IBulkOperationService
{
    private readonly IDbConnection _connection;
    private readonly ILogger&amp;lt;BulkOperationService&amp;gt; _logger;

    public BulkOperationService(IDbConnection connection, ILogger&amp;lt;BulkOperationService&amp;gt; logger)
    {
        _connection = connection;
        _logger = logger;
    }

    public async Task&amp;lt;int&amp;gt; BulkInsertProductsAsync(IEnumerable&amp;lt;Product&amp;gt; products)
    {
        const string sql = @"
            INSERT INTO Products (Name, Description, Price, StockQuantity, Category)
            VALUES (@Name, @Description, @Price, @StockQuantity, @Category)";

        var productList = products.ToList();
        var affectedRows = await _connection.ExecuteAsync(sql, productList);

        _logger.LogInformation("Bulk inserted {Count} products", affectedRows);
        return affectedRows;
    }

    public async Task&amp;lt;int&amp;gt; BulkUpdateProductPricesAsync(IEnumerable&amp;lt;ProductPriceUpdate&amp;gt; updates)
    {
        const string sql = @"
            UPDATE Products 
            SET Price = @NewPrice, 
                Description = CASE 
                    WHEN @UpdateDescription = 1 THEN 
                        Description + ' (Price updated: ' + CAST(Price AS NVARCHAR(20)) + ' -&amp;gt; ' + CAST(@NewPrice AS NVARCHAR(20)) + ')'
                    ELSE Description
                END
            WHERE Id = @ProductId";

        var affectedRows = await _connection.ExecuteAsync(sql, updates);

        _logger.LogInformation("Bulk updated prices for {Count} products", affectedRows);
        return affectedRows;
    }

    public async Task&amp;lt;int&amp;gt; BulkMergeProductsAsync(IEnumerable&amp;lt;Product&amp;gt; products)
    {
        // Using MERGE statement for upsert operations
        const string sql = @"
            MERGE Products AS target
            USING (VALUES (@Id, @Name, @Description, @Price, @StockQuantity, @Category)) 
                AS source (Id, Name, Description, Price, StockQuantity, Category)
            ON target.Id = source.Id
            WHEN MATCHED THEN
                UPDATE SET 
                    Name = source.Name,
                    Description = source.Description,
                    Price = source.Price,
                    StockQuantity = source.StockQuantity,
                    Category = source.Category
            WHEN NOT MATCHED THEN
                INSERT (Name, Description, Price, StockQuantity, Category)
                VALUES (source.Name, source.Description, source.Price, source.StockQuantity, source.Category);";

        var affectedRows = await _connection.ExecuteAsync(sql, products);

        _logger.LogInformation("Bulk merged {Count} products", affectedRows);
        return affectedRows;
    }

    public async Task&amp;lt;int&amp;gt; BulkInsertUsersAsync(IEnumerable&amp;lt;User&amp;gt; users)
    {
        const string sql = @"
            INSERT INTO Users (Username, Email, FirstName, LastName, DateOfBirth)
            VALUES (@Username, @Email, @FirstName, @LastName, @DateOfBirth)";

        var userList = users.ToList();
        var affectedRows = await _connection.ExecuteAsync(sql, userList);

        _logger.LogInformation("Bulk inserted {Count} users", affectedRows);
        return affectedRows;
    }

    public async Task&amp;lt;BulkOperationResult&amp;gt; ExecuteBulkOperationsAsync(BulkOperationRequest request)
    {
        var result = new BulkOperationResult();
        var stopwatch = System.Diagnostics.Stopwatch.StartNew();

        using var transaction = _connection.BeginTransaction();

        try
        {
            if (request.ProductsToInsert?.Any() == true)
            {
                result.ProductsInserted = await BulkInsertProductsAsync(request.ProductsToInsert);
            }

            if (request.ProductsToUpdate?.Any() == true)
            {
                result.ProductsUpdated = await BulkUpdateProductPricesAsync(request.ProductsToUpdate);
            }

            if (request.UsersToInsert?.Any() == true)
            {
                result.UsersInserted = await BulkInsertUsersAsync(request.UsersToInsert);
            }

            transaction.Commit();
            result.Success = true;
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            result.Success = false;
            result.ErrorMessage = ex.Message;
            _logger.LogError(ex, "Bulk operations failed");
        }
        finally
        {
            stopwatch.Stop();
            result.Duration = stopwatch.Elapsed;
        }

        return result;
    }
}

public class ProductPriceUpdate
{
    public int ProductId { get; set; }
    public decimal NewPrice { get; set; }
    public bool UpdateDescription { get; set; } = false;
}

public class BulkOperationRequest
{
    public IEnumerable&amp;lt;Product&amp;gt;? ProductsToInsert { get; set; }
    public IEnumerable&amp;lt;ProductPriceUpdate&amp;gt;? ProductsToUpdate { get; set; }
    public IEnumerable&amp;lt;User&amp;gt;? UsersToInsert { get; set; }
}

public class BulkOperationResult
{
    public bool Success { get; set; }
    public string? ErrorMessage { get; set; }
    public TimeSpan Duration { get; set; }
    public int ProductsInserted { get; set; }
    public int ProductsUpdated { get; set; }
    public int UsersInserted { get; set; }
    public int TotalOperations =&amp;gt; ProductsInserted + ProductsUpdated + UsersInserted;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Performance Comparison Utilities&lt;br&gt;
Services/PerformanceComparisonService.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;br&gt;
using System.Diagnostics;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IPerformanceComparisonService&lt;br&gt;
    {&lt;br&gt;
        Task CompareQueryMethodsAsync();&lt;br&gt;
        Task CompareBulkOperationsAsync(int recordCount);&lt;br&gt;
        Task CompareMappingStrategiesAsync();&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class PerformanceComparisonService : IPerformanceComparisonService
{
    private readonly IDbConnection _connection;
    private readonly ILogger&amp;lt;PerformanceComparisonService&amp;gt; _logger;

    public PerformanceComparisonService(IDbConnection connection, ILogger&amp;lt;PerformanceComparisonService&amp;gt; logger)
    {
        _connection = connection;
        _logger = logger;
    }

    public async Task&amp;lt;PerformanceComparisonResult&amp;gt; CompareQueryMethodsAsync()
    {
        var result = new PerformanceComparisonResult("Query Methods Comparison");
        var stopwatch = new Stopwatch();

        // Test 1: Dapper QueryAsync
        stopwatch.Start();
        var dapperResult = await _connection.QueryAsync&amp;lt;Product&amp;gt;(
            "SELECT * FROM Products WHERE IsActive = 1");
        stopwatch.Stop();
        result.AddResult("Dapper QueryAsync", stopwatch.Elapsed, dapperResult.Count());

        // Test 2: Dapper QueryFirstOrDefaultAsync
        stopwatch.Restart();
        var singleResult = await _connection.QueryFirstOrDefaultAsync&amp;lt;Product&amp;gt;(
            "SELECT * FROM Products WHERE Id = 1");
        stopwatch.Stop();
        result.AddResult("Dapper QueryFirstOrDefault", stopwatch.Elapsed, 1);

        // Test 3: Multiple queries with QueryMultiple
        stopwatch.Restart();
        using var multi = await _connection.QueryMultipleAsync(@"
            SELECT * FROM Products WHERE IsActive = 1;
            SELECT COUNT(*) FROM Products;");
        var products = await multi.ReadAsync&amp;lt;Product&amp;gt;();
        var count = await multi.ReadSingleAsync&amp;lt;int&amp;gt;();
        stopwatch.Stop();
        result.AddResult("Dapper QueryMultiple", stopwatch.Elapsed, products.Count());

        return result;
    }

    public async Task&amp;lt;PerformanceComparisonResult&amp;gt; CompareBulkOperationsAsync(int recordCount)
    {
        var result = new PerformanceComparisonResult($"Bulk Operations Comparison ({recordCount} records)");
        var testProducts = GenerateTestProducts(recordCount);

        // Test 1: Individual inserts
        var stopwatch = Stopwatch.StartNew();
        foreach (var product in testProducts)
        {
            await _connection.ExecuteAsync(
                "INSERT INTO Products (Name, Price, StockQuantity) VALUES (@Name, @Price, @StockQuantity)",
                product);
        }
        stopwatch.Stop();
        result.AddResult("Individual Inserts", stopwatch.Elapsed, recordCount);

        // Clean up
        await _connection.ExecuteAsync("DELETE FROM Products WHERE Name LIKE 'TestProduct%'");

        // Test 2: Bulk insert with Dapper
        stopwatch.Restart();
        await _connection.ExecuteAsync(
            "INSERT INTO Products (Name, Price, StockQuantity) VALUES (@Name, @Price, @StockQuantity)",
            testProducts);
        stopwatch.Stop();
        result.AddResult("Dapper Bulk Insert", stopwatch.Elapsed, recordCount);

        // Clean up
        await _connection.ExecuteAsync("DELETE FROM Products WHERE Name LIKE 'TestProduct%'");

        return result;
    }

    public async Task&amp;lt;PerformanceComparisonResult&amp;gt; CompareMappingStrategiesAsync()
    {
        var result = new PerformanceComparisonResult("Mapping Strategies Comparison");

        // Test 1: Simple mapping
        var stopwatch = Stopwatch.StartNew();
        var simpleResults = await _connection.QueryAsync&amp;lt;Product&amp;gt;(
            "SELECT * FROM Products WHERE IsActive = 1");
        stopwatch.Stop();
        result.AddResult("Simple Mapping", stopwatch.Elapsed, simpleResults.Count());

        // Test 2: Complex mapping with joins
        stopwatch.Restart();
        const string complexSql = @"
            SELECT 
                o.*,
                u.*,
                oi.*,
                p.*
            FROM Orders o
            INNER JOIN Users u ON o.UserId = u.Id
            LEFT JOIN OrderItems oi ON o.Id = oi.OrderId
            LEFT JOIN Products p ON oi.ProductId = p.Id
            WHERE o.OrderDate &amp;gt;= DATEADD(day, -30, GETUTCDATE())";

        var orderDict = new Dictionary&amp;lt;int, Order&amp;gt;();
        var complexResults = await _connection.QueryAsync&amp;lt;Order, User, OrderItem, Product, Order&amp;gt;(
            complexSql,
            (order, user, orderItem, product) =&amp;gt;
            {
                if (!orderDict.TryGetValue(order.Id, out var orderEntry))
                {
                    orderEntry = order;
                    orderEntry.User = user;
                    orderEntry.OrderItems = new List&amp;lt;OrderItem&amp;gt;();
                    orderDict.Add(orderEntry.Id, orderEntry);
                }

                if (orderItem != null)
                {
                    orderItem.Product = product;
                    orderEntry.OrderItems.Add(orderItem);
                }

                return orderEntry;
            },
            splitOn: "Id,Id,Id");

        stopwatch.Stop();
        result.AddResult("Complex Multi-Mapping", stopwatch.Elapsed, orderDict.Count);

        return result;
    }

    private IEnumerable&amp;lt;Product&amp;gt; GenerateTestProducts(int count)
    {
        for (int i = 0; i &amp;lt; count; i++)
        {
            yield return new Product
            {
                Name = $"TestProduct_{i}",
                Price = i * 10.0m,
                StockQuantity = i * 5
            };
        }
    }
}

public class PerformanceComparisonResult
{
    public string TestName { get; set; }
    public List&amp;lt;MethodResult&amp;gt; Results { get; set; } = new List&amp;lt;MethodResult&amp;gt;();

    public PerformanceComparisonResult(string testName)
    {
        TestName = testName;
    }

    public void AddResult(string methodName, TimeSpan duration, int recordsProcessed)
    {
        Results.Add(new MethodResult
        {
            MethodName = methodName,
            Duration = duration,
            RecordsProcessed = recordsProcessed,
            RecordsPerSecond = duration.TotalSeconds &amp;gt; 0 ? recordsProcessed / duration.TotalSeconds : 0
        });
    }

    public MethodResult? GetFastestMethod()
    {
        return Results.OrderBy(r =&amp;gt; r.Duration).FirstOrDefault();
    }

    public MethodResult? GetSlowestMethod()
    {
        return Results.OrderByDescending(r =&amp;gt; r.Duration).FirstOrDefault();
    }
}

public class MethodResult
{
    public string MethodName { get; set; } = string.Empty;
    public TimeSpan Duration { get; set; }
    public int RecordsProcessed { get; set; }
    public double RecordsPerSecond { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Real-World Enterprise Scenarios
E-Commerce Application Services
Services/ECommerceService.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IECommerceService&lt;br&gt;
    {&lt;br&gt;
        Task PlaceOrderAsync(OrderRequest request);&lt;br&gt;
        Task CheckInventoryAsync(int productId, int quantity);&lt;br&gt;
        Task CalculateOrderTotalAsync(OrderCalculationRequest request);&lt;br&gt;
        Task&amp;gt; GetRecommendedProductsAsync(int userId);&lt;br&gt;
        Task GetCustomerDashboardAsync(int userId);&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ECommerceService : IECommerceService
{
    private readonly IDbConnection _connection;
    private readonly ILogger&amp;lt;ECommerceService&amp;gt; _logger;

    public ECommerceService(IDbConnection connection, ILogger&amp;lt;ECommerceService&amp;gt; logger)
    {
        _connection = connection;
        _logger = logger;
    }

    public async Task&amp;lt;OrderResult&amp;gt; PlaceOrderAsync(OrderRequest request)
    {
        using var transaction = _connection.BeginTransaction();

        try
        {
            // 1. Validate inventory
            var inventoryStatus = await CheckInventoryAsync(request.ProductId, request.Quantity);
            if (!inventoryStatus.IsAvailable)
            {
                return new OrderResult
                {
                    Success = false,
                    Message = $"Insufficient inventory. Available: {inventoryStatus.AvailableQuantity}"
                };
            }

            // 2. Calculate order total
            var calculationRequest = new OrderCalculationRequest
            {
                ProductId = request.ProductId,
                Quantity = request.Quantity,
                UserId = request.UserId
            };
            var totalAmount = await CalculateOrderTotalAsync(calculationRequest);

            // 3. Create order
            var order = new Order
            {
                UserId = request.UserId,
                TotalAmount = totalAmount,
                Status = "Pending",
                ShippingAddress = request.ShippingAddress
            };

            const string orderSql = @"
                INSERT INTO Orders (UserId, TotalAmount, Status, ShippingAddress)
                OUTPUT INSERTED.Id
                VALUES (@UserId, @TotalAmount, @Status, @ShippingAddress)";

            var orderId = await _connection.ExecuteScalarAsync&amp;lt;int&amp;gt;(orderSql, order, transaction);

            // 4. Create order item
            var orderItem = new OrderItem
            {
                OrderId = orderId,
                ProductId = request.ProductId,
                Quantity = request.Quantity,
                UnitPrice = inventoryStatus.UnitPrice,
                TotalPrice = totalAmount
            };

            const string itemSql = @"
                INSERT INTO OrderItems (OrderId, ProductId, Quantity, UnitPrice, TotalPrice)
                VALUES (@OrderId, @ProductId, @Quantity, @UnitPrice, @TotalPrice)";

            await _connection.ExecuteAsync(itemSql, orderItem, transaction);

            // 5. Update inventory
            const string updateInventorySql = @"
                UPDATE Products 
                SET StockQuantity = StockQuantity - @Quantity 
                WHERE Id = @ProductId";

            await _connection.ExecuteAsync(updateInventorySql, 
                new { ProductId = request.ProductId, Quantity = request.Quantity }, 
                transaction);

            transaction.Commit();

            _logger.LogInformation("Order {OrderId} placed successfully for user {UserId}", 
                orderId, request.UserId);

            return new OrderResult
            {
                Success = true,
                OrderId = orderId,
                TotalAmount = totalAmount,
                Message = "Order placed successfully"
            };
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            _logger.LogError(ex, "Failed to place order for user {UserId}", request.UserId);

            return new OrderResult
            {
                Success = false,
                Message = "Failed to place order: " + ex.Message
            };
        }
    }

    public async Task&amp;lt;InventoryStatus&amp;gt; CheckInventoryAsync(int productId, int quantity)
    {
        const string sql = @"
            SELECT 
                StockQuantity as AvailableQuantity,
                Price as UnitPrice,
                CASE WHEN StockQuantity &amp;gt;= @Quantity THEN 1 ELSE 0 END as IsAvailable
            FROM Products 
            WHERE Id = @ProductId AND IsActive = 1";

        var status = await _connection.QueryFirstOrDefaultAsync&amp;lt;InventoryStatus&amp;gt;(sql, 
            new { ProductId = productId, Quantity = quantity });

        return status ?? new InventoryStatus { IsAvailable = false };
    }

    public async Task&amp;lt;decimal&amp;gt; CalculateOrderTotalAsync(OrderCalculationRequest request)
    {
        const string sql = @"
            DECLARE @BasePrice DECIMAL(18,2);
            DECLARE @Discount DECIMAL(18,2) = 0;

            -- Get base price
            SELECT @BasePrice = Price 
            FROM Products 
            WHERE Id = @ProductId;

            -- Check for user discounts
            SELECT @Discount = DiscountPercent 
            FROM UserDiscounts 
            WHERE UserId = @UserId AND IsActive = 1;

            -- Calculate total
            SELECT (@BasePrice * @Quantity) * (1 - ISNULL(@Discount, 0) / 100) as TotalAmount;";

        return await _connection.ExecuteScalarAsync&amp;lt;decimal&amp;gt;(sql, request);
    }

    public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetRecommendedProductsAsync(int userId)
    {
        const string sql = @"
            -- Based on user's order history
            SELECT DISTINCT p.*
            FROM Products p
            INNER JOIN OrderItems oi ON p.Id = oi.ProductId
            INNER JOIN Orders o ON oi.OrderId = o.Id
            WHERE o.UserId = @UserId
               AND p.IsActive = 1
               AND p.Id NOT IN (
                   SELECT ProductId 
                   FROM OrderItems oi2
                   INNER JOIN Orders o2 ON oi2.OrderId = o2.Id
                   WHERE o2.UserId = @UserId
                   AND o2.OrderDate &amp;gt;= DATEADD(day, -30, GETUTCDATE())
               )
            ORDER BY p.CreatedAt DESC";

        return await _connection.QueryAsync&amp;lt;Product&amp;gt;(sql, new { UserId = userId });
    }

    public async Task&amp;lt;CustomerDashboard&amp;gt; GetCustomerDashboardAsync(int userId)
    {
        const string sql = @"
            -- Customer basic info
            SELECT 
                u.Id, u.Username, u.Email, u.FirstName, u.LastName,
                COUNT(o.Id) as TotalOrders,
                SUM(o.TotalAmount) as TotalSpent,
                MAX(o.OrderDate) as LastOrderDate
            FROM Users u
            LEFT JOIN Orders o ON u.Id = o.UserId
            WHERE u.Id = @UserId
            GROUP BY u.Id, u.Username, u.Email, u.FirstName, u.LastName;

            -- Recent orders
            SELECT 
                o.Id, o.OrderDate, o.TotalAmount, o.Status
            FROM Orders o
            WHERE o.UserId = @UserId
            ORDER BY o.OrderDate DESC
            OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY;

            -- Favorite categories
            SELECT 
                p.Category,
                COUNT(oi.Id) as OrderCount,
                SUM(oi.Quantity) as TotalQuantity
            FROM OrderItems oi
            INNER JOIN Products p ON oi.ProductId = p.Id
            INNER JOIN Orders o ON oi.OrderId = o.Id
            WHERE o.UserId = @UserId
            GROUP BY p.Category
            ORDER BY TotalQuantity DESC;";

        using var multi = await _connection.QueryMultipleAsync(sql, new { UserId = userId });

        var customerInfo = await multi.ReadFirstOrDefaultAsync&amp;lt;CustomerDashboard&amp;gt;();
        var recentOrders = await multi.ReadAsync&amp;lt;OrderSummary&amp;gt;();
        var favoriteCategories = await multi.ReadAsync&amp;lt;FavoriteCategory&amp;gt;();

        if (customerInfo != null)
        {
            customerInfo.RecentOrders = recentOrders.ToList();
            customerInfo.FavoriteCategories = favoriteCategories.ToList();
        }

        return customerInfo ?? new CustomerDashboard();
    }
}

public class OrderRequest
{
    public int UserId { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public string ShippingAddress { get; set; } = string.Empty;
}

public class OrderResult
{
    public bool Success { get; set; }
    public int OrderId { get; set; }
    public decimal TotalAmount { get; set; }
    public string Message { get; set; } = string.Empty;
}

public class InventoryStatus
{
    public int AvailableQuantity { get; set; }
    public decimal UnitPrice { get; set; }
    public bool IsAvailable { get; set; }
}

public class OrderCalculationRequest
{
    public int UserId { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }
}

public class CustomerDashboard
{
    public int Id { get; set; }
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public int TotalOrders { get; set; }
    public decimal TotalSpent { get; set; }
    public DateTime? LastOrderDate { get; set; }
    public List&amp;lt;OrderSummary&amp;gt; RecentOrders { get; set; } = new List&amp;lt;OrderSummary&amp;gt;();
    public List&amp;lt;FavoriteCategory&amp;gt; FavoriteCategories { get; set; } = new List&amp;lt;FavoriteCategory&amp;gt;();
}

public class FavoriteCategory
{
    public string Category { get; set; } = string.Empty;
    public int OrderCount { get; set; }
    public int TotalQuantity { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Reporting and Analytics&lt;br&gt;
Services/ReportingService.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Services&lt;br&gt;
{&lt;br&gt;
    public interface IReportingService&lt;br&gt;
    {&lt;br&gt;
        Task GetSalesReportAsync(SalesReportRequest request);&lt;br&gt;
        Task&amp;gt; GetMonthlySalesTrendAsync(int year);&lt;br&gt;
        Task GetProductPerformanceReportAsync(ProductReportRequest request);&lt;br&gt;
        Task GetCustomerAnalyticsAsync();&lt;br&gt;
        Task&amp;gt; GetGeographicSalesAsync();&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ReportingService : IReportingService
{
    private readonly IDbConnection _connection;

    public ReportingService(IDbConnection connection)
    {
        _connection = connection;
    }

    public async Task&amp;lt;SalesReport&amp;gt; GetSalesReportAsync(SalesReportRequest request)
    {
        const string sql = @"
            -- Total sales and orders
            SELECT 
                COUNT(o.Id) as TotalOrders,
                SUM(o.TotalAmount) as TotalRevenue,
                AVG(o.TotalAmount) as AverageOrderValue,
                MIN(o.OrderDate) as FirstOrderDate,
                MAX(o.OrderDate) as LastOrderDate
            FROM Orders o
            WHERE o.OrderDate BETWEEN @StartDate AND @EndDate;

            -- Daily breakdown
            SELECT 
                CAST(o.OrderDate as DATE) as Date,
                COUNT(o.Id) as OrderCount,
                SUM(o.TotalAmount) as DailyRevenue,
                AVG(o.TotalAmount) as AverageOrderValue
            FROM Orders o
            WHERE o.OrderDate BETWEEN @StartDate AND @EndDate
            GROUP BY CAST(o.OrderDate as DATE)
            ORDER BY Date;

            -- Top products
            SELECT 
                p.Id,
                p.Name,
                p.Category,
                SUM(oi.Quantity) as TotalQuantity,
                SUM(oi.TotalPrice) as TotalRevenue
            FROM OrderItems oi
            INNER JOIN Products p ON oi.ProductId = p.Id
            INNER JOIN Orders o ON oi.OrderId = o.Id
            WHERE o.OrderDate BETWEEN @StartDate AND @EndDate
            GROUP BY p.Id, p.Name, p.Category
            ORDER BY TotalRevenue DESC
            OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

            -- Customer segments
            SELECT 
                CASE 
                    WHEN COUNT(o.Id) = 1 THEN 'One-Time'
                    WHEN COUNT(o.Id) BETWEEN 2 AND 5 THEN 'Regular'
                    ELSE 'VIP'
                END as Segment,
                COUNT(DISTINCT u.Id) as CustomerCount,
                SUM(o.TotalAmount) as SegmentRevenue
            FROM Users u
            INNER JOIN Orders o ON u.Id = o.UserId
            WHERE o.OrderDate BETWEEN @StartDate AND @EndDate
            GROUP BY 
                CASE 
                    WHEN COUNT(o.Id) = 1 THEN 'One-Time'
                    WHEN COUNT(o.Id) BETWEEN 2 AND 5 THEN 'Regular'
                    ELSE 'VIP'
                END;";

        using var multi = await _connection.QueryMultipleAsync(sql, request);

        var report = await multi.ReadFirstAsync&amp;lt;SalesReport&amp;gt;();
        report.DailySales = await multi.ReadAsync&amp;lt;DailySales&amp;gt;();
        report.TopProducts = await multi.ReadAsync&amp;lt;TopProduct&amp;gt;();
        report.CustomerSegments = await multi.ReadAsync&amp;lt;CustomerSegment&amp;gt;();
        report.StartDate = request.StartDate;
        report.EndDate = request.EndDate;

        return report;
    }

    public async Task&amp;lt;IEnumerable&amp;lt;MonthlySales&amp;gt;&amp;gt; GetMonthlySalesTrendAsync(int year)
    {
        const string sql = @"
            SELECT 
                YEAR(OrderDate) as Year,
                MONTH(OrderDate) as Month,
                COUNT(Id) as OrderCount,
                SUM(TotalAmount) as TotalRevenue,
                AVG(TotalAmount) as AverageOrderValue
            FROM Orders
            WHERE YEAR(OrderDate) = @Year
            GROUP BY YEAR(OrderDate), MONTH(OrderDate)
            ORDER BY Year, Month";

        return await _connection.QueryAsync&amp;lt;MonthlySales&amp;gt;(sql, new { Year = year });
    }

    public async Task&amp;lt;ProductPerformanceReport&amp;gt; GetProductPerformanceReportAsync(ProductReportRequest request)
    {
        const string sql = @"
            -- Product performance summary
            SELECT 
                p.Id,
                p.Name,
                p.Category,
                p.Price,
                p.StockQuantity,
                COUNT(oi.Id) as TimesOrdered,
                SUM(oi.Quantity) as TotalSold,
                SUM(oi.TotalPrice) as TotalRevenue,
                AVG(oi.Quantity) as AverageOrderQuantity
            FROM Products p
            LEFT JOIN OrderItems oi ON p.Id = oi.ProductId
            LEFT JOIN Orders o ON oi.OrderId = o.Id
            WHERE (@Category IS NULL OR p.Category = @Category)
              AND (@StartDate IS NULL OR o.OrderDate &amp;gt;= @StartDate)
              AND (@EndDate IS NULL OR o.OrderDate &amp;lt;= @EndDate)
            GROUP BY p.Id, p.Name, p.Category, p.Price, p.StockQuantity
            ORDER BY TotalRevenue DESC NULLS LAST;

            -- Monthly trend for top products
            WITH TopProducts AS (
                SELECT TOP 5 p.Id
                FROM Products p
                LEFT JOIN OrderItems oi ON p.Id = oi.ProductId
                LEFT JOIN Orders o ON oi.OrderId = o.Id
                WHERE (@Category IS NULL OR p.Category = @Category)
                  AND (@StartDate IS NULL OR o.OrderDate &amp;gt;= @StartDate)
                  AND (@EndDate IS NULL OR o.OrderDate &amp;lt;= @EndDate)
                GROUP BY p.Id
                ORDER BY SUM(oi.TotalPrice) DESC NULLS LAST
            )
            SELECT 
                p.Id as ProductId,
                p.Name as ProductName,
                YEAR(o.OrderDate) as Year,
                MONTH(o.OrderDate) as Month,
                SUM(oi.Quantity) as MonthlyQuantity,
                SUM(oi.TotalPrice) as MonthlyRevenue
            FROM OrderItems oi
            INNER JOIN Products p ON oi.ProductId = p.Id
            INNER JOIN Orders o ON oi.OrderId = o.Id
            WHERE p.Id IN (SELECT Id FROM TopProducts)
              AND (@StartDate IS NULL OR o.OrderDate &amp;gt;= @StartDate)
              AND (@EndDate IS NULL OR o.OrderDate &amp;lt;= @EndDate)
            GROUP BY p.Id, p.Name, YEAR(o.OrderDate), MONTH(o.OrderDate)
            ORDER BY p.Name, Year, Month;";

        using var multi = await _connection.QueryMultipleAsync(sql, request);

        var products = await multi.ReadAsync&amp;lt;ProductPerformance&amp;gt;();
        var monthlyTrends = await multi.ReadAsync&amp;lt;ProductMonthlyTrend&amp;gt;();

        return new ProductPerformanceReport
        {
            Products = products.ToList(),
            MonthlyTrends = monthlyTrends.ToList()
        };
    }

    public async Task&amp;lt;CustomerAnalytics&amp;gt; GetCustomerAnalyticsAsync()
    {
        const string sql = @"
            -- Customer acquisition trends
            SELECT 
                YEAR(CreatedAt) as Year,
                MONTH(CreatedAt) as Month,
                COUNT(Id) as NewCustomers
            FROM Users
            WHERE CreatedAt &amp;gt;= DATEADD(year, -1, GETUTCDATE())
            GROUP BY YEAR(CreatedAt), MONTH(CreatedAt)
            ORDER BY Year, Month;

            -- Customer lifetime value
            SELECT 
                u.Id,
                u.Username,
                u.Email,
                COUNT(o.Id) as TotalOrders,
                SUM(o.TotalAmount) as LifetimeValue,
                MIN(o.OrderDate) as FirstOrderDate,
                MAX(o.OrderDate) as LastOrderDate,
                DATEDIFF(day, MIN(o.OrderDate), MAX(o.OrderDate)) as CustomerLifetimeDays
            FROM Users u
            INNER JOIN Orders o ON u.Id = o.UserId
            GROUP BY u.Id, u.Username, u.Email
            HAVING COUNT(o.Id) &amp;gt;= 1
            ORDER BY LifetimeValue DESC;

            -- Repeat customer rate
            SELECT 
                COUNT(*) as TotalCustomers,
                SUM(CASE WHEN OrderCount &amp;gt; 1 THEN 1 ELSE 0 END) as RepeatCustomers,
                CAST(SUM(CASE WHEN OrderCount &amp;gt; 1 THEN 1 ELSE 0 END) AS FLOAT) / COUNT(*) as RepeatRate
            FROM (
                SELECT u.Id, COUNT(o.Id) as OrderCount
                FROM Users u
                LEFT JOIN Orders o ON u.Id = o.UserId
                GROUP BY u.Id
            ) CustomerOrders;";

        using var multi = await _connection.QueryMultipleAsync(sql);

        var acquisitionTrends = await multi.ReadAsync&amp;lt;CustomerAcquisition&amp;gt;();
        var customerLifetimeValues = await multi.ReadAsync&amp;lt;CustomerLifetimeValue&amp;gt;();
        var repeatCustomerStats = await multi.ReadFirstAsync&amp;lt;RepeatCustomerStats&amp;gt;();

        return new CustomerAnalytics
        {
            AcquisitionTrends = acquisitionTrends.ToList(),
            CustomerLifetimeValues = customerLifetimeValues.ToList(),
            RepeatCustomerStats = repeatCustomerStats
        };
    }

    public async Task&amp;lt;IEnumerable&amp;lt;GeographicSales&amp;gt;&amp;gt; GetGeographicSalesAsync()
    {
        const string sql = @"
            -- Extract state from shipping address (simplified)
            SELECT 
                CASE 
                    WHEN CHARINDEX(',', ShippingAddress) &amp;gt; 0 THEN
                        LTRIM(RTRIM(SUBSTRING(ShippingAddress, 
                            CHARINDEX(',', ShippingAddress) + 1, 
                            LEN(ShippingAddress))))
                    ELSE 'Unknown'
                END as State,
                COUNT(Id) as OrderCount,
                SUM(TotalAmount) as TotalRevenue,
                AVG(TotalAmount) as AverageOrderValue
            FROM Orders
            WHERE ShippingAddress IS NOT NULL
              AND ShippingAddress != ''
            GROUP BY 
                CASE 
                    WHEN CHARINDEX(',', ShippingAddress) &amp;gt; 0 THEN
                        LTRIM(RTRIM(SUBSTRING(ShippingAddress, 
                            CHARINDEX(',', ShippingAddress) + 1, 
                            LEN(ShippingAddress))))
                    ELSE 'Unknown'
                END
            ORDER BY TotalRevenue DESC";

        return await _connection.QueryAsync&amp;lt;GeographicSales&amp;gt;(sql);
    }
}

// ... (DTO classes for reporting)
public class SalesReportRequest
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

public class ProductReportRequest
{
    public string? Category { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
}

public class ProductPerformance
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Category { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
    public int TimesOrdered { get; set; }
    public int TotalSold { get; set; }
    public decimal TotalRevenue { get; set; }
    public decimal AverageOrderQuantity { get; set; }
}

// ... (Additional DTO classes for various reports)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Integration with ASP.NET Core
Controllers
Controllers/UsersController.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using DapperDeepDive.Repositories;&lt;br&gt;
using DapperDeepDive.Services;&lt;br&gt;
using Microsoft.AspNetCore.Mvc;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Controllers&lt;br&gt;
{&lt;br&gt;
    [ApiController]&lt;br&gt;
    [Route("api/[controller]")]&lt;br&gt;
    public class UsersController : ControllerBase&lt;br&gt;
    {&lt;br&gt;
        private readonly IUserRepository _userRepository;&lt;br&gt;
        private readonly IAdvancedUserRepository _advancedUserRepository;&lt;br&gt;
        private readonly IPerformanceMonitor _performanceMonitor;&lt;br&gt;
        private readonly ILogger _logger;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public UsersController(
        IUserRepository userRepository,
        IAdvancedUserRepository advancedUserRepository,
        IPerformanceMonitor performanceMonitor,
        ILogger&amp;lt;UsersController&amp;gt; logger)
    {
        _userRepository = userRepository;
        _advancedUserRepository = advancedUserRepository;
        _performanceMonitor = performanceMonitor;
        _logger = logger;
    }

    [HttpGet]
    public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;User&amp;gt;&amp;gt;&amp;gt; GetUsers()
    {
        try
        {
            var users = await _performanceMonitor.MonitorQueryAsync(
                () =&amp;gt; _userRepository.GetAllAsync(),
                "GetAllUsers");

            return Ok(users);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving users");
            return StatusCode(500, "An error occurred while retrieving users");
        }
    }

    [HttpGet("{id}")]
    public async Task&amp;lt;ActionResult&amp;lt;User&amp;gt;&amp;gt; GetUser(int id)
    {
        try
        {
            var user = await _userRepository.GetByIdAsync(id);
            if (user == null)
            {
                return NotFound();
            }

            return Ok(user);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving user with ID {UserId}", id);
            return StatusCode(500, "An error occurred while retrieving the user");
        }
    }

    [HttpPost]
    public async Task&amp;lt;ActionResult&amp;lt;User&amp;gt;&amp;gt; CreateUser(User user)
    {
        try
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var userId = await _userRepository.CreateAsync(user);
            user.Id = userId;

            return CreatedAtAction(nameof(GetUser), new { id = userId }, user);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating user");
            return StatusCode(500, "An error occurred while creating the user");
        }
    }

    [HttpPut("{id}")]
    public async Task&amp;lt;IActionResult&amp;gt; UpdateUser(int id, User user)
    {
        try
        {
            if (id != user.Id)
            {
                return BadRequest("User ID mismatch");
            }

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var existingUser = await _userRepository.GetByIdAsync(id);
            if (existingUser == null)
            {
                return NotFound();
            }

            var success = await _userRepository.UpdateAsync(user);
            if (!success)
            {
                return StatusCode(500, "Failed to update user");
            }

            return NoContent();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error updating user with ID {UserId}", id);
            return StatusCode(500, "An error occurred while updating the user");
        }
    }

    [HttpDelete("{id}")]
    public async Task&amp;lt;IActionResult&amp;gt; DeleteUser(int id)
    {
        try
        {
            var existingUser = await _userRepository.GetByIdAsync(id);
            if (existingUser == null)
            {
                return NotFound();
            }

            var success = await _userRepository.DeleteAsync(id);
            if (!success)
            {
                return StatusCode(500, "Failed to delete user");
            }

            return NoContent();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error deleting user with ID {UserId}", id);
            return StatusCode(500, "An error occurred while deleting the user");
        }
    }

    [HttpGet("{id}/orders")]
    public async Task&amp;lt;ActionResult&amp;lt;UserWithOrders&amp;gt;&amp;gt; GetUserWithOrders(int id)
    {
        try
        {
            var (user, orders) = await _advancedUserRepository.GetUserWithOrdersAsync(id);
            if (user == null)
            {
                return NotFound();
            }

            var result = new UserWithOrders
            {
                User = user,
                Orders = orders.ToList()
            };

            return Ok(result);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving user orders for user ID {UserId}", id);
            return StatusCode(500, "An error occurred while retrieving user orders");
        }
    }

    [HttpGet("search")]
    public async Task&amp;lt;ActionResult&amp;lt;PaginatedResult&amp;lt;User&amp;gt;&amp;gt;&amp;gt; SearchUsers(
        [FromQuery] UserSearchCriteria criteria)
    {
        try
        {
            var result = await _advancedUserRepository.GetUsersPaginatedAsync(
                criteria.PageNumber, criteria.PageSize);

            return Ok(result);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error searching users");
            return StatusCode(500, "An error occurred while searching users");
        }
    }
}

public class UserWithOrders
{
    public User User { get; set; } = new User();
    public List&amp;lt;Order&amp;gt; Orders { get; set; } = new List&amp;lt;Order&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Controllers/ProductsController.cs&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using DapperDeepDive.Models;&lt;br&gt;
using DapperDeepDive.Repositories;&lt;br&gt;
using DapperDeepDive.Services;&lt;br&gt;
using Microsoft.AspNetCore.Mvc;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.Controllers&lt;br&gt;
{&lt;br&gt;
    [ApiController]&lt;br&gt;
    [Route("api/[controller]")]&lt;br&gt;
    public class ProductsController : ControllerBase&lt;br&gt;
    {&lt;br&gt;
        private readonly IProductRepository _productRepository;&lt;br&gt;
        private readonly ICacheService _cacheService;&lt;br&gt;
        private readonly IQueryBuilderService _queryBuilderService;&lt;br&gt;
        private readonly ILogger _logger;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public ProductsController(
        IProductRepository productRepository,
        ICacheService cacheService,
        IQueryBuilderService queryBuilderService,
        ILogger&amp;lt;ProductsController&amp;gt; logger)
    {
        _productRepository = productRepository;
        _cacheService = cacheService;
        _queryBuilderService = queryBuilderService;
        _logger = logger;
    }

    [HttpGet]
    public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt;&amp;gt; GetProducts(
        [FromQuery] ProductSearchCriteria criteria)
    {
        try
        {
            var cacheKey = $"products_search_{criteria.GetHashCode()}";

            var products = await _cacheService.GetOrCreateAsync(cacheKey,
                async () =&amp;gt;
                {
                    if (HasSearchCriteria(criteria))
                    {
                        return await _queryBuilderService.SearchProductsAsync(criteria);
                    }
                    else
                    {
                        return await _productRepository.GetActiveProductsAsync();
                    }
                },
                TimeSpan.FromMinutes(5));

            return Ok(products);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving products");
            return StatusCode(500, "An error occurred while retrieving products");
        }
    }

    [HttpGet("{id}")]
    public async Task&amp;lt;ActionResult&amp;lt;Product&amp;gt;&amp;gt; GetProduct(int id)
    {
        try
        {
            var product = await _productRepository.GetByIdAsync(id);
            if (product == null)
            {
                return NotFound();
            }

            return Ok(product);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving product with ID {ProductId}", id);
            return StatusCode(500, "An error occurred while retrieving the product");
        }
    }

    [HttpGet("category/{category}")]
    public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt;&amp;gt; GetProductsByCategory(string category)
    {
        try
        {
            var products = await _productRepository.GetByCategoryAsync(category);
            return Ok(products);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving products for category {Category}", category);
            return StatusCode(500, "An error occurred while retrieving products");
        }
    }

    [HttpGet("search/{searchTerm}")]
    public async Task&amp;lt;ActionResult&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt;&amp;gt; SearchProducts(string searchTerm)
    {
        try
        {
            var products = await _productRepository.SearchProductsAsync(searchTerm);
            return Ok(products);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error searching products with term {SearchTerm}", searchTerm);
            return StatusCode(500, "An error occurred while searching products");
        }
    }

    [HttpPost]
    public async Task&amp;lt;ActionResult&amp;lt;Product&amp;gt;&amp;gt; CreateProduct(Product product)
    {
        try
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var productId = await _productRepository.CreateAsync(product);
            product.Id = productId;

            // Invalidate relevant caches
            _cacheService.Remove($"products_category_{product.Category}");
            _cacheService.Remove("products_search_*"); // Would need custom implementation for pattern removal

            return CreatedAtAction(nameof(GetProduct), new { id = productId }, product);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating product");
            return StatusCode(500, "An error occurred while creating the product");
        }
    }

    [HttpPut("{id}")]
    public async Task&amp;lt;IActionResult&amp;gt; UpdateProduct(int id, Product product)
    {
        try
        {
            if (id != product.Id)
            {
                return BadRequest("Product ID mismatch");
            }

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var existingProduct = await _productRepository.GetByIdAsync(id);
            if (existingProduct == null)
            {
                return NotFound();
            }

            var success = await _productRepository.UpdateAsync(product);
            if (!success)
            {
                return StatusCode(500, "Failed to update product");
            }

            // Invalidate caches
            _cacheService.Remove($"product_{id}");
            _cacheService.Remove($"products_category_{existingProduct.Category}");
            if (existingProduct.Category != product.Category)
            {
                _cacheService.Remove($"products_category_{product.Category}");
            }

            return NoContent();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error updating product with ID {ProductId}", id);
            return StatusCode(500, "An error occurred while updating the product");
        }
    }

    [HttpDelete("{id}")]
    public async Task&amp;lt;IActionResult&amp;gt; DeleteProduct(int id)
    {
        try
        {
            var existingProduct = await _productRepository.GetByIdAsync(id);
            if (existingProduct == null)
            {
                return NotFound();
            }

            var success = await _productRepository.DeleteAsync(id);
            if (!success)
            {
                return StatusCode(500, "Failed to delete product");
            }

            // Invalidate caches
            _cacheService.Remove($"product_{id}");
            _cacheService.Remove($"products_category_{existingProduct.Category}");

            return NoContent();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error deleting product with ID {ProductId}", id);
            return StatusCode(500, "An error occurred while deleting the product");
        }
    }

    [HttpGet("inventory/value")]
    public async Task&amp;lt;ActionResult&amp;lt;decimal&amp;gt;&amp;gt; GetTotalInventoryValue()
    {
        try
        {
            var value = await _productRepository.GetTotalInventoryValueAsync();
            return Ok(value);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error calculating inventory value");
            return StatusCode(500, "An error occurred while calculating inventory value");
        }
    }

    [HttpGet("categories/stats")]
    public async Task&amp;lt;ActionResult&amp;lt;Dictionary&amp;lt;string, int&amp;gt;&amp;gt;&amp;gt; GetProductCountByCategory()
    {
        try
        {
            var stats = await _productRepository.GetProductCountByCategoryAsync();
            return Ok(stats);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving category statistics");
            return StatusCode(500, "An error occurred while retrieving category statistics");
        }
    }

    private bool HasSearchCriteria(ProductSearchCriteria criteria)
    {
        return !string.IsNullOrEmpty(criteria.Name) ||
               !string.IsNullOrEmpty(criteria.Category) ||
               criteria.MinPrice.HasValue ||
               criteria.MaxPrice.HasValue ||
               criteria.InStockOnly;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Dependency Injection Configuration&lt;br&gt;
Program.cs (Extended)&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
using DapperDeepDive.Data;&lt;br&gt;
using DapperDeepDive.Repositories;&lt;br&gt;
using DapperDeepDive.Services;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;var builder = WebApplication.CreateBuilder(args);&lt;/p&gt;

&lt;p&gt;// Add services to container&lt;br&gt;
builder.Services.AddControllers();&lt;br&gt;
builder.Services.AddEndpointsApiExplorer();&lt;br&gt;
builder.Services.AddSwaggerGen();&lt;/p&gt;

&lt;p&gt;// Database connection&lt;br&gt;
builder.Services.AddScoped(provider =&amp;gt;&lt;br&gt;
{&lt;br&gt;
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");&lt;br&gt;
    return new Microsoft.Data.SqlClient.SqlConnection(connectionString);&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;// Repositories&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;/p&gt;

&lt;p&gt;// Services&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
builder.Services.AddScoped();&lt;/p&gt;

&lt;p&gt;// Caching&lt;br&gt;
builder.Services.AddMemoryCache();&lt;/p&gt;

&lt;p&gt;// Logging&lt;br&gt;
builder.Services.AddLogging();&lt;/p&gt;

&lt;p&gt;var app = builder.Build();&lt;/p&gt;

&lt;p&gt;// Initialize database&lt;br&gt;
using (var scope = app.Services.CreateScope())&lt;br&gt;
{&lt;br&gt;
    var initializer = new DatabaseInitializer(&lt;br&gt;
        builder.Configuration.GetConnectionString("DefaultConnection"));&lt;br&gt;
    await initializer.InitializeDatabaseAsync();&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// Configure pipeline&lt;br&gt;
if (app.Environment.IsDevelopment())&lt;br&gt;
{&lt;br&gt;
    app.UseDeveloperExceptionPage();&lt;br&gt;
    app.UseSwagger();&lt;br&gt;
    app.UseSwaggerUI();&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;app.UseRouting();&lt;br&gt;
app.MapControllers();&lt;/p&gt;

&lt;p&gt;app.Run();&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Best Practices and Advanced Patterns
Best Practices Guide
BestPractices/DapperBestPractices.cs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;csharp&lt;br&gt;
using Dapper;&lt;br&gt;
using System.Data;&lt;/p&gt;

&lt;p&gt;namespace DapperDeepDive.BestPractices&lt;br&gt;
{&lt;br&gt;
    public static class DapperBestPractices&lt;br&gt;
    {&lt;br&gt;
        public static class ConnectionManagement&lt;br&gt;
        {&lt;br&gt;
            public static IDbConnection CreateConnection(string connectionString)&lt;br&gt;
            {&lt;br&gt;
                return new Microsoft.Data.SqlClient.SqlConnection(connectionString);&lt;br&gt;
            }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        public static async Task&amp;lt;IDbConnection&amp;gt; CreateOpenConnectionAsync(string connectionString)
        {
            var connection = CreateConnection(connectionString);
            await connection.OpenAsync();
            return connection;
        }

        public static void UseConnectionPooling(string connectionString)
        {
            // Connection pooling is handled by the connection string
            // Ensure proper configuration:
            // - Max Pool Size
            // - Min Pool Size  
            // - Connection Timeout
            var builder = new Microsoft.Data.SqlClient.SqlConnectionStringBuilder(connectionString)
            {
                MaxPoolSize = 100,
                MinPoolSize = 0,
                Pooling = true,
                ConnectionTimeout = 30
            };
        }
    }

    public static class QueryExecution
    {
        public static void UseParameterizedQueries(IDbConnection connection, string sql, object parameters)
        {
            // GOOD: Parameterized query (prevents SQL injection)
            var result = connection.Query&amp;lt;User&amp;gt;("SELECT * FROM Users WHERE Id = @Id", new { Id = userId });

            // BAD: String concatenation (vulnerable to SQL injection)
            // var result = connection.Query&amp;lt;User&amp;gt;($"SELECT * FROM Users WHERE Id = {userId}");
        }

        public static void SetAppropriateCommandTimeout(IDbCommand command, int timeoutSeconds = 30)
        {
            command.CommandTimeout = timeoutSeconds;
        }

        public static async Task&amp;lt;T&amp;gt; QueryWithTimeoutAsync&amp;lt;T&amp;gt;(
            IDbConnection connection, 
            string sql, 
            object parameters, 
            int timeoutSeconds = 30)
        {
            using var command = new Microsoft.Data.SqlClient.SqlCommand(sql, 
                (Microsoft.Data.SqlClient.SqlConnection)connection);
            command.Parameters.AddRange(GetParameters(parameters));
            command.CommandTimeout = timeoutSeconds;

            // Execute query...
            // This is a simplified example - in practice, use Dapper's methods
            return await connection.QueryFirstOrDefaultAsync&amp;lt;T&amp;gt;(sql, parameters);
        }
    }

    public static class Performance
    {
        public static void UseAppropriateFetchSize(int fetchSize = 5000)
        {
            // For large datasets, consider using buffered: false
            var results = connection.Query&amp;lt;User&amp;gt;("SELECT * FROM Users", buffered: false);
        }

        public static void OptimizeLargeResultSets()
        {
            // Use streaming for large result sets
            var results = connection.Query&amp;lt;User&amp;gt;("SELECT * FROM Users", buffered: false);

            // Process results incrementally
            foreach (var user in results)
            {
                ProcessUser(user);
            }
        }

        public static void UseStoredProceduresForComplexOperations()
        {
            // Complex business logic is better handled in stored procedures
            var result = connection.Query&amp;lt;User&amp;gt;("GetUserWithOrders", 
                new { UserId = userId }, 
                commandType: CommandType.StoredProcedure);
        }
    }

    public static class Mapping
    {
        public static void UseExplicitColumnMapping()
        {
            // Use custom mapping for complex scenarios
            SqlMapper.SetTypeMap(typeof(User), new CustomPropertyTypeMap(typeof(User),
                (type, columnName) =&amp;gt;
                {
                    if (columnName == "user_id") return type.GetProperty("Id");
                    if (columnName == "user_name") return type.GetProperty("Username");
                    // ... other mappings
                    return null;
                }));
        }

        public static void HandleNullValues()
        {
            // Use nullable types and proper null checking
            var user = connection.QuerySingleOrDefault&amp;lt;User&amp;gt;(
                "SELECT * FROM Users WHERE Id = @Id", new { Id = userId });

            if (user != null)
            {
                // Process user
            }
        }
    }

    public static class ErrorHandling
    {
        public static async Task&amp;lt;T&amp;gt; ExecuteWithRetryAsync&amp;lt;T&amp;gt;(
            Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; operation, 
            int maxRetries = 3)
        {
            var retries = 0;
            while (true)
            {
                try
                {
                    return await operation();
                }
                catch (SqlException ex) when (IsTransientError(ex) &amp;amp;&amp;amp; retries &amp;lt; maxRetries)
                {
                    retries++;
                    await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, retries))); // Exponential backoff
                }
            }
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;📘ASP.NET Core Mastery with Latest Features : 40-Part Series 🎯 Visit Free Learning Zone&lt;/p&gt;

</description>
      <category>programming</category>
      <category>framework</category>
      <category>aspnet</category>
      <category>webdev</category>
    </item>
    <item>
      <title>ERP Success in Bangladesh: Step-by-Step Realistic Roadmap to Avoid Project Failure - FreeLearning365.com</title>
      <dc:creator>FreeLearning365.com</dc:creator>
      <pubDate>Tue, 14 Oct 2025 04:54:28 +0000</pubDate>
      <link>https://forem.com/freelearning365/erp-success-in-bangladesh-step-by-step-realistic-roadmap-to-avoid-project-failure--b39</link>
      <guid>https://forem.com/freelearning365/erp-success-in-bangladesh-step-by-step-realistic-roadmap-to-avoid-project-failure--b39</guid>
      <description>&lt;p&gt;My Main Article: &lt;a href="https://www.freelearning365.com/2025/10/erp-success-in-bangladesh-step-by-step.html" rel="noopener noreferrer"&gt;https://www.freelearning365.com/2025/10/erp-success-in-bangladesh-step-by-step.html&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🧭 How to Make ERP Projects Successful in Bangladesh — The Complete Realistic Roadmap
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;💡 From Failure to Future: Practical, Proven, and Bangladeshi-Context ERP Implementation Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;🌍 1️⃣ Define Clear Business Goals Before Coding&lt;/strong&gt;**&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conduct Business Process Study Workshops (BPSW) for each department.&lt;/li&gt;
&lt;li&gt;Document existing manual workflows → identify inefficiencies → map “To-Be” processes.&lt;/li&gt;
&lt;li&gt;Assign process owners (not just IT) to approve each step.&lt;/li&gt;
&lt;li&gt;Use Lucidchart / Visio / Draw.io to create visual workflows before any development.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: A visual process eliminates ambiguity. When everyone understands the flow, developers can build logic accurately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📋 2️⃣ Conduct a Feasibility &amp;amp; ROI Study&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculate measurable KPIs: time saved, error reduction, faster reporting.&lt;/li&gt;
&lt;li&gt;Prepare a 3-year ROI Projection Sheet (excel-based).&lt;/li&gt;
&lt;li&gt;Share with management to set realistic expectations.&lt;/li&gt;
&lt;li&gt;Revisit ROI quarterly to show progress.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Realistic expectations = long-term confidence = reduced pressure on project team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;🧍‍♀️ 3️⃣ Drive Employee Adoption from Day One&lt;/strong&gt;**&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Involve employees in early testing and feedback loops.&lt;/li&gt;
&lt;li&gt;Conduct short “Show &amp;amp; Tell” demo sessions 🧑‍💻 every Friday.&lt;/li&gt;
&lt;li&gt;Launch ERP Awareness Campaigns inside the company (email posters, short videos).&lt;/li&gt;
&lt;li&gt;Reward top ERP users (“ERP Champion of the Month” 🏅).&lt;/li&gt;
&lt;li&gt;🧠 Why it works: ERP success is 70% psychology and 30% technology.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚒️ 4️⃣ Balance Customization with Standardization&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep 80% standard and only 20% customized.&lt;/li&gt;
&lt;li&gt;Maintain a “Customization Register” to track changes.&lt;/li&gt;
&lt;li&gt;Avoid unnecessary stored procedure overrides.&lt;/li&gt;
&lt;li&gt;Prefer configuration over hard-coded customization.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: When your ERP upgrades later, minimal breakage and faster support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;🧹 5️⃣ Data Cleaning &amp;amp; Governance Policy&lt;/strong&gt;**&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a “Data Steward” per department.&lt;/li&gt;
&lt;li&gt;Run Excel-based data validation before importing.&lt;/li&gt;
&lt;li&gt;Use scripts to detect duplicates, missing codes, invalid IDs.&lt;/li&gt;
&lt;li&gt;Define data entry SOPs: Naming conventions, date formats (YYYY-MM-DD).&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Clean data ensures dashboard accuracy and user trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;💰 6️⃣ Smart Vendor Selection Framework&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prepare an ERP Vendor Scorecard based on:&lt;/li&gt;
&lt;li&gt;Technical depth (30%)&lt;/li&gt;
&lt;li&gt;Post-Go-Live Support (25%)&lt;/li&gt;
&lt;li&gt;Domain Experience (25%)&lt;/li&gt;
&lt;li&gt;Pricing (20%)&lt;/li&gt;
&lt;li&gt;Check existing clients and support feedback.&lt;/li&gt;
&lt;li&gt;Prefer vendors offering SLA (Service Level Agreement) with defined response time.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: You’re selecting a partner, not just a software vendor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🧑‍🏫 7️⃣ Continuous Training Culture&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conduct training in phases: Pre-Go-Live, Go-Live Week, Post-Go-Live.&lt;/li&gt;
&lt;li&gt;Use video-based micro learning (2–3 min clips).&lt;/li&gt;
&lt;li&gt;Create an internal “ERP Knowledge Base” using Google Sites / Notion.&lt;/li&gt;
&lt;li&gt;Conduct quarterly refresh sessions.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Sustained training ensures ERP remains alive and relevant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚡ 8️⃣ Strengthen Infrastructure &amp;amp; Backup&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Cloud hosting or hybrid (local+cloud) with daily automated backups.&lt;/li&gt;
&lt;li&gt;Set up power redundancy (UPS, inverter, generator).&lt;/li&gt;
&lt;li&gt;Monitor system health via Power BI dashboards (uptime %, latency, user sessions).&lt;/li&gt;
&lt;li&gt;Use SSL &amp;amp; firewall for all API endpoints.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Stable system → user confidence → adoption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🤝 9️⃣ Foster Inter-Departmental Collaboration&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form an ERP Steering Committee (Finance, HR, Production, IT).&lt;/li&gt;
&lt;li&gt;Monthly cross-department meetings to discuss issues.&lt;/li&gt;
&lt;li&gt;Build dashboards that show how one department’s data impacts another.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Collaboration = Shared Ownership = Long-term success.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🕵️ 🔟 Capture Hidden Requirements Early&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conduct UAT simulation workshops before final build.&lt;/li&gt;
&lt;li&gt;Use mock data and screen prototypes for review.&lt;/li&gt;
&lt;li&gt;Apply “Requirement Traceability Matrix (RTM)” — maps each requirement to its test case.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: You catch surprises before they become disasters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🏦 11️⃣ Budget for Quality &amp;amp; Scalability&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep a 10–15% contingency budget for change requests.&lt;/li&gt;
&lt;li&gt;Invest in cloud scalability and security audits.&lt;/li&gt;
&lt;li&gt;Pay for SLA-based annual support — it’s cheaper than downtime.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Predictable cost → zero panic during crisis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;🕰️ 12️⃣ Plan Practical Timelines&lt;/strong&gt;**&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a Gantt Chart (Excel or MS Project).&lt;/li&gt;
&lt;li&gt;Include time for testing, training, and data migration.&lt;/li&gt;
&lt;li&gt;Define clear milestones with acceptance criteria.&lt;/li&gt;
&lt;li&gt;Avoid festival seasons for go-live (production load &amp;amp; staff leaves).&lt;/li&gt;
&lt;li&gt;🧠 Why it works: A well-paced project = fewer mistakes, better adoption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;🧩 13️⃣ Strong Project Management Framework&lt;/strong&gt;**&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assign a dedicated Project Manager (PM).&lt;/li&gt;
&lt;li&gt;Weekly progress reports with traffic-light status (Green/Amber/Red).&lt;/li&gt;
&lt;li&gt;Use collaboration tools like Trello, Asana, or Jira.&lt;/li&gt;
&lt;li&gt;Keep management engaged with short, visual summaries.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Visibility ensures accountability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;👓 14️⃣ Empower Skilled Business Analysts&lt;/strong&gt;**&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hire BAs with domain + technical blend (Finance, Supply Chain, HR).&lt;/li&gt;
&lt;li&gt;BA should write clear BRD (Business Requirement Document) and FRD (Functional Requirement Document).&lt;/li&gt;
&lt;li&gt;Conduct requirement review sessions before sign-off.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: A skilled BA translates chaos into clarity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔄 15️⃣ Master Data Migration Process&lt;/strong&gt;&lt;br&gt;
🧩 Realistic Resolution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run 3 mock migrations: dry run, pilot, final.&lt;/li&gt;
&lt;li&gt;Validate totals with finance team after each.&lt;/li&gt;
&lt;li&gt;Keep Excel-based reconciliation sheets.&lt;/li&gt;
&lt;li&gt;Backup all previous data securely before switching systems.&lt;/li&gt;
&lt;li&gt;🧠 Why it works: Reliable migration = confidence on Day 1 of Go-Live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🎯 Final Words: From ERP Chaos to ERP Confidence&lt;/strong&gt;&lt;br&gt;
ERP success doesn’t depend on big budgets —&lt;br&gt;
it depends on discipline, ownership, and continuous improvement.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bangladesh has the talent — what’s needed is structured execution.&lt;br&gt;
Once companies treat ERP as a strategic growth partner (not an IT tool),&lt;br&gt;
the success rate will skyrocket 🚀.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  ERPSuccess #ERPImplementation #BangladeshBusiness #DigitalBangladesh #TechTransformation #ERPStrategy #ProcessAutomation #ERPTraining #DataMigration #BusinessProcessReengineering #EnterpriseSoftware #BangladeshIT #FreeLearning365 #BusinessAutomation #TechLeadership #SAP #Oracle #MicrosoftDynamics #SAP #OracleERP #OracleFusion #MicrosoftDynamics365 #DynamicsERP #InforERP #WorkdayERP #EpicorERP #NetSuite #Odoo #Tally #ZohoBooks #SAPBusinessOne #SAPERPHANA #S4HANA #BangladeshERP #LocalERP #ERPforSME #ERPforBangladesh #PridesysERP #SouthtechERP #SmartERP #BEPZASolutions #TechnoVistaERP #DataSoftERP #BanglaSoft #DigitalERP #BangladeshIT #ERPConsultingBD
&lt;/h1&gt;

</description>
      <category>softwaredevelopment</category>
      <category>projectmanagement</category>
      <category>erpimplementation</category>
      <category>erp</category>
    </item>
    <item>
      <title>Repository Pattern in .NET and Java: Clean Data Access</title>
      <dc:creator>FreeLearning365.com</dc:creator>
      <pubDate>Sun, 14 Sep 2025 04:44:34 +0000</pubDate>
      <link>https://forem.com/freelearning365/repository-pattern-in-net-and-java-clean-data-access-4a32</link>
      <guid>https://forem.com/freelearning365/repository-pattern-in-net-and-java-clean-data-access-4a32</guid>
      <description>&lt;p&gt;Introduction&lt;br&gt;
In the world of software development, managing data access effectively is crucial for building scalable, maintainable applications. The Repository Pattern emerges as a powerful architectural solution to separate database logic from business logic, promoting clean, testable, and flexible code. This pattern acts as an abstraction layer between your application's domain model and the underlying data storage, whether it's a relational database like SQL Server or PostgreSQL, a NoSQL store, or even external APIs.&lt;/p&gt;

&lt;p&gt;At its core, the Repository Pattern encapsulates all data access operations—such as creating, reading, updating, and deleting (CRUD)—into dedicated classes or interfaces. This decoupling ensures that changes in the data layer (e.g., switching from Entity Framework in .NET to Dapper, or from JPA in Java to MyBatis) don't ripple through the entire application. It's particularly valuable in enterprise environments where business requirements evolve rapidly, and data sources may vary across microservices or hybrid systems.&lt;/p&gt;

&lt;p&gt;This blog post dives deep into the Repository Pattern, exploring its implementation in both .NET and Java ecosystems. We'll walk through step-by-step guides with real-life examples centered around an e-commerce inventory management system—a common business scenario where products are stored, retrieved, and updated frequently. We'll cover pros and cons, real-life usage, and business implications, drawing from practical experiences in building robust applications.&lt;/p&gt;

&lt;p&gt;Whether you're a .NET developer using ASP.NET Core or a Java enthusiast working with Spring Boot, this guide will equip you with actionable insights to implement clean data access in your projects.&lt;/p&gt;

&lt;p&gt;What is the Repository Pattern?&lt;br&gt;
The Repository Pattern, popularized by Domain-Driven Design (DDD) principles from Eric Evans' book Domain-Driven Design, treats data access as a collection-like interface. Instead of scattering SQL queries or ORM calls throughout your business logic, you centralize them in repositories. These repositories provide methods that mimic in-memory collection operations (e.g., GetAll(), FindById(), Add(), Update()), hiding the complexities of persistence.&lt;/p&gt;

&lt;p&gt;Key components include:&lt;/p&gt;

&lt;p&gt;Interface: Defines the contract for data operations, ensuring abstraction.&lt;br&gt;
Implementation: Handles the actual data access, often using ORMs like Entity Framework (EF) in .NET or Hibernate/JPA in Java.&lt;br&gt;
Dependency Injection (DI): Wires the interface to its implementation, allowing easy swapping for testing or migration.&lt;br&gt;
In real-life terms, imagine an online retail business where inventory levels must be checked in real-time. Without the pattern, your order processing service might directly query the database, mixing concerns. With repositories, the service calls IProductRepository.GetById(id), keeping logic clean and focused on business rules like stock validation.&lt;/p&gt;

&lt;p&gt;This pattern aligns with Clean Architecture by keeping the domain layer "persistence-agnostic," meaning your core business entities remain unaware of how data is stored.&lt;/p&gt;

&lt;p&gt;Why Use the Repository Pattern? Benefits and Real-Life Scenarios&lt;br&gt;
The Repository Pattern shines in scenarios demanding maintainability and scalability. Here's why it's a go-to choice:&lt;/p&gt;

&lt;p&gt;Separation of Concerns&lt;br&gt;
By isolating data access, business logic stays pure. In a real-life e-commerce app, your OrderService can focus on calculating discounts and taxes without worrying about SQL joins or connection strings.&lt;/p&gt;

&lt;p&gt;Improved Testability&lt;br&gt;
Repositories make unit testing straightforward. You can mock the interface for in-memory fakes, testing business rules without a database. For instance, in a financial services firm, testers can simulate high-volume transactions without hitting production databases.&lt;/p&gt;

&lt;p&gt;Flexibility and Decoupling&lt;br&gt;
Switch data sources effortlessly. A healthcare business migrating from on-premises SQL Server to cloud-based Azure Cosmos DB in .NET, or from MySQL to MongoDB in Java, only updates the repository implementation.&lt;/p&gt;

&lt;p&gt;Reusability&lt;br&gt;
Centralized logic reduces duplication. In a multi-tenant SaaS platform, multiple modules (e.g., reporting and analytics) can reuse the same UserRepository.&lt;/p&gt;

&lt;p&gt;Real-Life Usage&lt;br&gt;
In business contexts, this pattern is ubiquitous. Consider a logistics company like UPS: Their route optimization service uses repositories to fetch shipment data from various sources (databases, APIs), ensuring seamless integration. In banking apps, repositories handle secure data access for transaction histories, complying with regulations like GDPR by abstracting sensitive queries.&lt;/p&gt;

&lt;p&gt;During the COVID-19 pandemic, many e-commerce platforms scaled rapidly using this pattern to handle surging inventory queries, allowing quick pivots to new data providers without downtime.&lt;/p&gt;

&lt;p&gt;Implementing the Repository Pattern in .NET&lt;br&gt;
.NET, with its robust ecosystem including ASP.NET Core and Entity Framework Core (EF Core), makes Repository implementation seamless. We'll use a generic repository for reusability, focusing on an e-commerce example with products.&lt;/p&gt;

&lt;p&gt;Step 1: Define the Domain Model&lt;br&gt;
Start with entities in your Domain layer. For our inventory system:&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
// Domain/Entities/Product.cs&lt;br&gt;
public class Product&lt;br&gt;
{&lt;br&gt;
    public int Id { get; set; }&lt;br&gt;
    public string Name { get; set; }&lt;br&gt;
    public decimal Price { get; set; }&lt;br&gt;
    public int StockQuantity { get; set; }&lt;br&gt;
    public DateTime LastUpdated { get; set; }&lt;br&gt;
}&lt;br&gt;
This represents a simple product entity, central to business operations like stock checks.&lt;/p&gt;

&lt;p&gt;Step 2: Create the Repository Interface&lt;br&gt;
In the Application or Domain layer, define a generic interface for CRUD operations:&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
// Application/Interfaces/IRepository.cs&lt;br&gt;
using System.Linq.Expressions;&lt;/p&gt;

&lt;p&gt;public interface IRepository where T : class&lt;br&gt;
{&lt;br&gt;
    Task&amp;gt; GetAllAsync();&lt;br&gt;
    Task GetByIdAsync(int id);&lt;br&gt;
    Task&amp;gt; FindAsync(Expression&amp;gt; predicate);&lt;br&gt;
    Task AddAsync(T entity);&lt;br&gt;
    Task UpdateAsync(T entity);&lt;br&gt;
    Task DeleteAsync(int id);&lt;br&gt;
    void Attach(T entity); // For EF tracking&lt;br&gt;
}&lt;br&gt;
For specificity, create IProductRepository : IRepository with custom methods like GetLowStockProductsAsync(int threshold).&lt;/p&gt;

&lt;p&gt;Step 3: Implement the Repository Using EF Core&lt;br&gt;
In the Infrastructure layer, implement using EF Core. Assume a DbContext for the database.&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
// Infrastructure/Repositories/Repository.cs&lt;br&gt;
using Microsoft.EntityFrameworkCore;&lt;br&gt;
using Application.Interfaces;&lt;/p&gt;

&lt;p&gt;public class Repository : IRepository where T : class&lt;br&gt;
{&lt;br&gt;
    protected readonly DbContext _context;&lt;br&gt;
    private readonly DbSet _dbSet;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Repository(DbContext context)
{
    _context = context;
    _dbSet = context.Set&amp;lt;T&amp;gt;();
}

public async Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; GetAllAsync()
{
    return await _dbSet.ToListAsync();
}

public async Task&amp;lt;T&amp;gt; GetByIdAsync(int id)
{
    return await _dbSet.FindAsync(id);
}

public async Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; FindAsync(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; predicate)
{
    return await _dbSet.Where(predicate).ToListAsync();
}

public async Task AddAsync(T entity)
{
    await _dbSet.AddAsync(entity);
    await _context.SaveChangesAsync(); // Or handle in Unit of Work
}

public async Task UpdateAsync(T entity)
{
    _dbSet.Attach(entity);
    _context.Entry(entity).State = EntityState.Modified;
    await _context.SaveChangesAsync();
}

public async Task DeleteAsync(int id)
{
    var entity = await GetByIdAsync(id);
    if (entity != null)
    {
        _dbSet.Remove(entity);
        await _context.SaveChangesAsync();
    }
}

public void Attach(T entity)
{
    _dbSet.Attach(entity);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
For ProductRepository:&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
// Infrastructure/Repositories/ProductRepository.cs&lt;br&gt;
public class ProductRepository : Repository, IProductRepository&lt;br&gt;
{&lt;br&gt;
    public ProductRepository(DbContext context) : base(context) { }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public async Task&amp;lt;IEnumerable&amp;lt;Product&amp;gt;&amp;gt; GetLowStockProductsAsync(int threshold)
{
    return await _dbSet.Where(p =&amp;gt; p.StockQuantity &amp;lt; threshold).ToListAsync();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Step 4: Configure Dependency Injection&lt;br&gt;
In Program.cs (ASP.NET Core):&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
builder.Services.AddDbContext(options =&amp;gt;&lt;br&gt;
    options.UseSqlServer(connectionString));&lt;/p&gt;

&lt;p&gt;builder.Services.AddScoped(typeof(IRepository&amp;lt;&amp;gt;), typeof(Repository&amp;lt;&amp;gt;));&lt;br&gt;
builder.Services.AddScoped();&lt;br&gt;
Step 5: Use in Business Logic&lt;br&gt;
In a service class:&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
// Application/Services/ProductService.cs&lt;br&gt;
public class ProductService&lt;br&gt;
{&lt;br&gt;
    private readonly IProductRepository _productRepository;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public ProductService(IProductRepository productRepository)
{
    _productRepository = productRepository;
}

public async Task&amp;lt;Product&amp;gt; GetProductAsync(int id)
{
    return await _productRepository.GetByIdAsync(id);
}

public async Task UpdateStockAsync(int productId, int newQuantity)
{
    var product = await _productRepository.GetByIdAsync(productId);
    if (product != null)
    {
        product.StockQuantity = newQuantity;
        product.LastUpdated = DateTime.UtcNow;
        await _productRepository.UpdateAsync(product);
    }
}

// Real-life: Alert for low stock
public async Task CheckLowStockAsync(int threshold)
{
    var lowStock = await _productRepository.GetLowStockProductsAsync(threshold);
    // Business logic: Send email or notify warehouse
    foreach (var p in lowStock)
    {
        // Simulate notification
        Console.WriteLine($"Low stock for {p.Name}");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
In a controller:&lt;/p&gt;

&lt;p&gt;csharp&lt;br&gt;
[ApiController]&lt;br&gt;
[Route("api/[controller]")]&lt;br&gt;
public class ProductsController : ControllerBase&lt;br&gt;
{&lt;br&gt;
    private readonly ProductService _service;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public ProductsController(ProductService service)
{
    _service = service;
}

[HttpGet("{id}")]
public async Task&amp;lt;IActionResult&amp;gt; Get(int id)
{
    var product = await _service.GetProductAsync(id);
    return Ok(product);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
This setup allows injecting mocks in tests, e.g., using Moq for unit tests simulating inventory depletion during peak sales.&lt;/p&gt;

&lt;p&gt;Implementing the Repository Pattern in Java&lt;br&gt;
Java's Spring framework pairs excellently with the Repository Pattern via Spring Data JPA. We'll mirror the .NET example for consistency.&lt;/p&gt;

&lt;p&gt;Step 1: Define the Domain Model&lt;br&gt;
Use JPA annotations for entities:&lt;/p&gt;

&lt;p&gt;java&lt;br&gt;
// domain/entities/Product.java&lt;br&gt;
import jakarta.persistence.*;&lt;/p&gt;

&lt;p&gt;@Entity&lt;br&gt;
@Table(name = "Products")&lt;br&gt;
public class Product {&lt;br&gt;
    &lt;a class="mentioned-user" href="https://dev.to/id"&gt;@id&lt;/a&gt;&lt;br&gt;
    @GeneratedValue(strategy = GenerationType.IDENTITY)&lt;br&gt;
    private Integer id;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private String name;
private BigDecimal price;
private Integer stockQuantity;
private LocalDateTime lastUpdated = LocalDateTime.now();

// Constructors, getters, setters
public Product() {}

public Product(String name, BigDecimal price, Integer stockQuantity) {
    this.name = name;
    this.price = price;
    this.stockQuantity = stockQuantity;
}

// Getters and setters...
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public BigDecimal getPrice() { return price; }
public void setPrice(BigDecimal price) { this.price = price; }
public Integer getStockQuantity() { return stockQuantity; }
public void setStockQuantity(Integer stockQuantity) { this.stockQuantity = stockQuantity; }
public LocalDateTime getLastUpdated() { return lastUpdated; }
public void setLastUpdated(LocalDateTime lastUpdated) { this.lastUpdated = lastUpdated; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Step 2: Create the Repository Interface&lt;br&gt;
Leverage Spring Data's JpaRepository for built-in CRUD:&lt;/p&gt;

&lt;p&gt;java&lt;br&gt;
// application/interfaces/ProductRepository.java&lt;br&gt;
import org.springframework.data.jpa.repository.JpaRepository;&lt;br&gt;
import org.springframework.data.jpa.repository.Query;&lt;br&gt;
import org.springframework.stereotype.Repository;&lt;br&gt;
import java.util.List;&lt;/p&gt;

&lt;p&gt;@Repository&lt;br&gt;
public interface ProductRepository extends JpaRepository {&lt;br&gt;
    List findByStockQuantityLessThan(Integer threshold);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Query("SELECT p FROM Product p WHERE p.name LIKE %?1%")
List&amp;lt;Product&amp;gt; findByNameContaining(String name);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
For a generic base, extend PagingAndSortingRepository if needed.&lt;/p&gt;

&lt;p&gt;Step 3: Implement Custom Logic (If Beyond Spring Data)&lt;br&gt;
Spring Data handles most CRUD, but for custom queries:&lt;/p&gt;

&lt;p&gt;java&lt;br&gt;
// infrastructure/repositories/CustomProductRepositoryImpl.java&lt;br&gt;
import org.springframework.beans.factory.annotation.Autowired;&lt;br&gt;
import org.springframework.stereotype.Repository;&lt;br&gt;
import jakarta.persistence.EntityManager;&lt;br&gt;
import jakarta.persistence.PersistenceContext;&lt;br&gt;
import java.util.List;&lt;/p&gt;

&lt;p&gt;@Repository&lt;br&gt;
public class CustomProductRepositoryImpl {&lt;br&gt;
    @PersistenceContext&lt;br&gt;
    private EntityManager entityManager;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;Product&amp;gt; getLowStockProducts(int threshold) {
    // Custom JPQL or native query
    return entityManager.createQuery(
        "SELECT p FROM Product p WHERE p.stockQuantity &amp;lt; :threshold", Product.class)
        .setParameter("threshold", threshold)
        .getResultList();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
Extend the interface to use this.&lt;/p&gt;

&lt;p&gt;Step 4: Configure Dependency Injection&lt;br&gt;
In Spring Boot's application.properties:&lt;/p&gt;

&lt;p&gt;text&lt;br&gt;
spring.datasource.url=jdbc:postgresql://localhost:5432/ecommerce&lt;br&gt;
spring.jpa.hibernate.ddl-auto=update&lt;br&gt;
In a configuration class or auto-wired via @EnableJpaRepositories.&lt;/p&gt;

&lt;p&gt;Step 5: Use in Business Logic&lt;br&gt;
In a service:&lt;/p&gt;

&lt;p&gt;java&lt;br&gt;
// application/services/ProductService.java&lt;br&gt;
import org.springframework.beans.factory.annotation.Autowired;&lt;br&gt;
import org.springframework.stereotype.Service;&lt;br&gt;
import org.springframework.transaction.annotation.Transactional;&lt;br&gt;
import java.time.LocalDateTime;&lt;br&gt;
import java.util.List;&lt;/p&gt;

&lt;p&gt;@Service&lt;br&gt;
@Transactional&lt;br&gt;
public class ProductService {&lt;br&gt;
    @Autowired&lt;br&gt;
    private ProductRepository productRepository;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Product getProductById(Integer id) {
    return productRepository.findById(id).orElse(null);
}

public void updateStock(Integer productId, Integer newQuantity) {
    Product product = productRepository.findById(productId).orElse(null);
    if (product != null) {
        product.setStockQuantity(newQuantity);
        product.setLastUpdated(LocalDateTime.now());
        productRepository.save(product);
    }
}

// Real-life: Check low stock
public List&amp;lt;Product&amp;gt; checkLowStock(Integer threshold) {
    List&amp;lt;Product&amp;gt; lowStock = productRepository.findByStockQuantityLessThan(threshold);
    // Business logic: Integrate with email service or inventory alert
    lowStock.forEach(p -&amp;gt; System.out.println("Low stock for " + p.getName()));
    return lowStock;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
In a REST controller:&lt;/p&gt;

&lt;p&gt;java&lt;br&gt;
// web/controllers/ProductController.java&lt;br&gt;
import org.springframework.beans.factory.annotation.Autowired;&lt;br&gt;
import org.springframework.http.ResponseEntity;&lt;br&gt;
import org.springframework.web.bind.annotation.*;&lt;/p&gt;

&lt;p&gt;@RestController&lt;br&gt;
@RequestMapping("/api/products")&lt;br&gt;
public class ProductController {&lt;br&gt;
    @Autowired&lt;br&gt;
    private ProductService productService;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GetMapping("/{id}")
public ResponseEntity&amp;lt;Product&amp;gt; get(@PathVariable Integer id) {
    Product product = productService.getProductById(id);
    return product != null ? ResponseEntity.ok(product) : ResponseEntity.notFound().build();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
This enables easy testing with @MockBean in Spring Boot tests, simulating scenarios like supply chain disruptions.&lt;/p&gt;

&lt;p&gt;Pros and Cons of the Repository Pattern&lt;br&gt;
Pros&lt;br&gt;
Maintainability: Centralized data logic simplifies debugging and refactoring. In a growing business like an online marketplace, updating query optimizations affects one place.&lt;br&gt;
Testability: Mocking interfaces speeds up CI/CD pipelines, crucial for agile teams in finance where compliance testing is rigorous.&lt;br&gt;
Scalability: Supports microservices; each service can have tailored repositories. Real-life: Netflix uses similar abstractions for personalized recommendations.&lt;br&gt;
Consistency: Enforces uniform data access, reducing errors in distributed teams.&lt;br&gt;
Integration with ORMs: Enhances EF Core or JPA, adding caching or logging via decorators.&lt;br&gt;
Cons&lt;br&gt;
Overhead in Small Apps: Adds boilerplate for simple CRUD apps, like a personal blog, where direct ORM use suffices.&lt;br&gt;
Leaky Abstractions: If not careful, domain-specific queries can expose data details, as noted in some critiques.&lt;br&gt;
Learning Curve: Teams new to DDD may struggle initially, delaying projects.&lt;br&gt;
Performance Tuning: Custom implementations might require manual optimization, unlike raw SQL.&lt;br&gt;
Generic vs. Specific: Overly generic repositories can lead to bloated methods; balance with specific ones for complex queries.&lt;br&gt;
In business, pros outweigh cons for mid-to-large projects, but evaluate based on scale—start simple and refactor.&lt;/p&gt;

&lt;p&gt;Usage in Real Life and Business Applications&lt;br&gt;
In real life, the Repository Pattern is a staple in enterprise software. For businesses, it drives efficiency:&lt;/p&gt;

&lt;p&gt;E-Commerce (e.g., Amazon-like Systems): Repositories manage product catalogs, enabling quick switches between databases during Black Friday traffic spikes. Business value: Reduced downtime, faster feature rollouts.&lt;br&gt;
Financial Services (e.g., Banking Apps): Secure transaction repositories abstract sensitive data access, aiding audits and compliance. A bank might use it to integrate legacy mainframes with modern cloud services, minimizing risk.&lt;br&gt;
Healthcare (e.g., Patient Management): Repositories handle HIPAA-compliant data retrieval, allowing seamless migration to telehealth platforms during pandemics.&lt;br&gt;
Logistics and Supply Chain: In companies like FedEx, repositories aggregate data from IoT sensors and ERPs, optimizing routes. Business impact: Cost savings through reusable logic across global operations.&lt;br&gt;
In a real project I consulted on, a retail chain used .NET repositories to unify data from multiple vendors, cutting maintenance costs by 30% and enabling real-time inventory syncing.&lt;/p&gt;

&lt;p&gt;For Java, Spring-based enterprise apps in telecom use it for billing systems, where data volume is massive, ensuring high availability.&lt;/p&gt;

&lt;p&gt;Pair it with Unit of Work for transaction management in complex ops, like order processing involving multiple repositories.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;The Repository Pattern is indispensable for clean data access in .NET and Java, fostering maintainable architectures that adapt to business needs. By following the step-by-step implementations above, you can apply it to real-life scenarios like inventory management, reaping benefits in testability and flexibility while mitigating cons through thoughtful design.&lt;/p&gt;

</description>
      <category>aspnet</category>
      <category>repositorypattern</category>
      <category>programming</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
