> This is part 1 of 2 of the full documentation (pages 1–100 of 143).
> The content is paginated: fetch every part to see all of it.
> Next part: https://docs.flexbase.in/llms-full.txt/1
> Page index: https://docs.flexbase.in/llms.txt

# Flexbase

High productivity framework for building ENDURING enterprise applications that helps you rediscover the #JoyofCoding!

### 🚀 Stop Writing Boilerplate Code

**Tired of spending weeks on controllers, DTOs, and database setup?**

* ⚡ **Generate complete modules** quickly
* 🏗️ **Enterprise architecture** built-in automatically
* 💰 **Save months** of development time
* 🎯 **Focus on what matters** - your business logic

#### The Problem

Most of your time is spent on repetitive infrastructure code instead of solving business problems.

#### The Solution

Define your business model, add your rules. Flexbase generates everything else.

```csharp
public partial class Order : DomainModelBridge
{
    [Required] public string CustomerId { get; set; }
    [Range(0.01, double.MaxValue)] public decimal TotalAmount { get; set; }
    
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // Your business logic here
        return this;
    }
}
```

*Finally, a framework that gets out of your way and lets you build.*

{% embed url="<https://www.flexbase.in>" %}
Visit the website
{% endembed %}


# Introduction

{% embed url="<https://www.youtube.com/watch?v=AdPpPe4YbvE&t=12s>" %}

## Flexbase - Enterprise Application Framework

### 🚀 Finally, a Framework That Gets It

**Stop wasting time on repetitive code. Start building what matters.**

Flexbase is the .NET Core framework that eliminates the tedious parts of enterprise development, so you can focus on solving real business problems.

#### ⚡ Why Developers Love Flexbase

* **No More Boilerplate** - Generate complete modules automatically
* **Enterprise Ready** - All patterns built-in from day one
* **Quick Setup** - Works immediately out of the box
* **Focus on Logic** - Write business rules, not infrastructure

#### 🏗️ What Happens Automatically

REST APIs, database integration, validation, message bus, DTOs, command handlers, event publishing, testing ready - everything you need, generated perfectly.

#### 🎯 What You Actually Write

Just your business model and rules. That's it.

```csharp
public partial class Order : DomainModelBridge
{
    [Required]
    public string CustomerId { get; set; }
    
    [Range(0.01, double.MaxValue)]
    public decimal TotalAmount { get; set; }
    
    // Your business logic here
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // Custom business rules
        return this;
    }
}
```

#### 💰 The Numbers Don't Lie

* **Massive Time Savings** - Complete modules in minutes
* **Huge Cost Reduction** - Save millions in development
* **Faster Delivery** - Ship features when you need them
* **Better Quality** - Consistent, tested patterns

#### 🚀 Ready to See the Magic?

1. **Install**: Use Flexbase Studio and Gen to define features and generate code
2. **Define**: Your domain model
3. **Generate**: Complete module
4. **Deploy**: Production-ready application

***

**Discover why thousands of developers have already made the switch. Your future self will thank you.**


# #JoyofCoding with Flexbase

Creating scalable, distributed Enterprise applications is now as easy as 1-2-3-4!!

{% embed url="<https://www.youtube.com/watch?v=oCfn7oRgBbY>" %}


# Before getting started

## 💸 The Million-Dollar Reality Check

### **The Million-Dollar Mistake**

*"We just need a simple application,"* said the project manager. *"How hard can it be?"*

**6 months later**: The team is drowning in technical debt, the application is unmaintainable, and the business is losing thousands every month due to bugs and downtime.

**The truth?** There's no such thing as a "simple" enterprise application. Every business process involves complex workflows, multiple systems, and real people trying to accomplish meaningful goals.

**Sound familiar?** You're not alone. According to industry research, **70% of organizations experience at least one project failure each financial year**, with **65-80% of IT projects considered failures by leadership** (Callibrity, 2024).

***

## 🚨 The Development Trap: Why Your Applications Are Failing

### **The Illusion of Simplicity**

When developers think about building applications, they often start with a simple question: *"What basic operations do I need?"*

**Create, Read, Update, Delete** - it sounds so straightforward. But here's the brutal truth:

> **Real applications aren't about simple operations. They're about complex business stories that span multiple systems, involve real people, and create real value.**

### **The Story Behind Every Great Application**

Every successful application tells a story. It's not about buttons and forms - it's about people trying to accomplish something meaningful. When you focus on the story first, everything else falls into place.

### **The Real Cost of Oversimplified Thinking**

| What You Think              | What You Actually Get        | The Hidden Cost                    |
| --------------------------- | ---------------------------- | ---------------------------------- |
| **"Simple Enterprise App"** | 500+ lines of spaghetti code | **$200K+ in refactoring**          |
| **"Quick Development"**     | 6 months of debugging        | **$150K+ in lost productivity**    |
| **"Easy Maintenance"**      | 2 years of technical debt    | **$500K+ in maintenance hell**     |
| **"Scalable Solution"**     | Performance bottlenecks      | **$300K+ in infrastructure costs** |

**Total Hidden Cost: Millions per application** 💸

*Source: Industry research shows that unsuccessful development projects in the U.S. cost $260 billion in 2020, a 46% increase since 2018 (Kingsmen Software, 2024)*

***

## 📖 The Story That Changes Everything

### **Meet Alex: The Professional Who Deserves Better**

Let me tell you about Alex, a busy professional who needs to order office supplies for their growing team. Their story isn't about CRUD operations - it's about a complete business journey that spans multiple systems, involves real people, and creates real value.

**But here's the kicker**: Most applications fail Alex at every step, creating frustration, delays, and business losses.

***

## 🔥 The 5 Stages of Application Hell

### **Stage 1: The Discovery Nightmare** 🔍

**Alex's Reality**: *"I need to find the right office chairs for my team. I want to see what's available, compare prices, and check if we have enough budget."*

**What Most Applications Do** ❌:

* Show a basic product list with no filtering
* No recommendations or personalization
* No real-time inventory checking
* No budget validation
* **Result**: Alex wastes 2 hours and gives up

**What Really Should Happen** ✅:

* Alex searches for "ergonomic office chairs"
* The system shows personalized recommendations based on their company's previous purchases
* They filter by price range, brand, and availability
* They compare different options side-by-side
* They check their department's budget allocation
* **Result**: Alex finds the perfect chairs in 5 minutes

**Behind the Scenes** (The Technical Reality):

* **Product Catalog Service** searches through thousands of products
* **Recommendation Engine** analyzes their company's purchase history
* **Inventory Service** checks real-time stock levels
* **Pricing Service** calculates dynamic pricing based on volume discounts
* **Budget Service** validates their spending authority

### **Stage 2: The Decision Disaster** 🤔

**Alex's Reality**: *"I found the perfect chairs! Now I need to add them to my cart and proceed to checkout. But first, let me check if we have any pending approvals or if I need manager approval for this amount."*

**What Most Applications Do** ❌:

* Simple "Add to Cart" button
* No approval workflow
* No budget validation
* No inventory reservation
* **Result**: Alex's order gets rejected later, wasting everyone's time

**What Really Should Happen** ✅:

* Alex adds 12 chairs to their cart
* The system calculates the total cost and applies volume discounts
* It checks their spending authority and approval requirements
* It validates the purchase against company policies
* It reserves the inventory while they complete checkout
* **Result**: Alex knows exactly what to expect before proceeding

**Behind the Scenes** (The Technical Reality):

* **Shopping Cart Service** manages their session and cart state
* **Pricing Engine** applies complex discount rules
* **Approval Workflow Service** checks their spending limits
* **Inventory Reservation Service** holds the stock
* **Policy Engine** validates against company rules

### **Stage 3: The Payment Purge** 💳

**Alex's Reality**: *"Perfect! The system approved my purchase. Now I need to enter our billing information and payment details. I want to use our corporate credit card and have it shipped to our main office."*

**What Most Applications Do** ❌:

* Basic payment form
* No integration with accounting systems
* No purchase order generation
* No logistics coordination
* **Result**: Alex has to manually create purchase orders and coordinate shipping

**What Really Should Happen** ✅:

* Alex enters billing and shipping information
* The system validates the corporate credit card
* It processes the payment through their bank
* It generates a purchase order for accounting
* It schedules the shipment with their preferred logistics partner
* **Result**: Everything is automated and coordinated

**Behind the Scenes** (The Technical Reality):

* **Payment Processing Service** handles credit card validation
* **Banking Integration** processes the transaction
* **Accounting System** creates purchase orders and invoices
* **Logistics Service** schedules pickup and delivery
* **Notification Service** sends confirmations to all stakeholders

### **Stage 4: The Fulfillment Fiasco** 📦

**Alex's Reality**: *"Great! I got the confirmation. Now I need to track the shipment and make sure someone is available to receive it. I also want to notify my team about the new chairs."*

**What Most Applications Do** ❌:

* Basic order confirmation
* No tracking integration
* No team notifications
* No delivery coordination
* **Result**: Alex has to manually track everything and coordinate with the team

**What Really Should Happen** ✅:

* Alex receives order confirmation and tracking information
* The system schedules delivery during business hours
* It notifies the receiving department
* It updates the team about the incoming delivery
* It tracks the shipment in real-time
* **Result**: Everyone is informed and coordinated automatically

**Behind the Scenes** (The Technical Reality):

* **Order Management Service** tracks the entire order lifecycle
* **Logistics Tracking Service** monitors shipment progress
* **Notification Service** sends updates to all parties
* **Team Communication Service** notifies relevant team members
* **Delivery Coordination Service** manages receiving schedules

### **Stage 5: The Delivery Debacle** 🚚

**Alex's Reality**: *"The chairs arrived! Now I need to confirm receipt, update our inventory, and make sure the invoice gets processed for payment. I also want to leave feedback about the experience."*

**What Most Applications Do** ❌:

* No delivery confirmation
* No inventory updates
* No invoice processing
* No feedback collection
* **Result**: Alex has to manually handle everything, creating more work

**What Really Should Happen** ✅:

* Alex confirms delivery and inspects the items
* The system updates inventory records
* It processes the invoice for payment
* It triggers the feedback collection process
* It updates the team's asset management system
* **Result**: Complete end-to-end automation

**Behind the Scenes** (The Technical Reality):

* **Delivery Confirmation Service** validates receipt
* **Inventory Management Service** updates stock levels
* **Accounts Payable Service** processes invoices
* **Feedback Collection Service** gathers customer experience data
* **Asset Management Service** tracks company assets

***

## 💸 The True Cost of Application Failure

### **The Hidden Costs That Kill Your Business**

| Problem                   | Direct Cost               | Indirect Cost                 | Total Impact       |
| ------------------------- | ------------------------- | ----------------------------- | ------------------ |
| **Poor User Experience**  | $50K in lost productivity | $200K in user frustration     | **$250K per year** |
| **Technical Debt**        | $100K in refactoring      | $300K in delayed features     | **$400K per year** |
| **Maintenance Nightmare** | $150K in bug fixes        | $250K in lost opportunities   | **$400K per year** |
| **Integration Failures**  | $75K in manual work       | $175K in process inefficiency | **$250K per year** |
| **Scalability Issues**    | $200K in infrastructure   | $300K in lost customers       | **$500K per year** |

**Total Annual Cost: $1.8 Million** 💀

*Source: Developers spend approximately 33% of their time dealing with technical debt, leading to significant productivity losses (Stepsize, 2024)*

### **The Opportunity Cost**

While you're struggling with technical debt and maintenance nightmares, your competitors are:

* **Launching new features** while you're fixing bugs
* **Scaling their business** while you're refactoring code
* **Capturing market share** while you're dealing with downtime
* **Innovating** while you're maintaining legacy systems

**The real cost isn't just what you spend - it's what you lose.**

***

## 🎯 The Real Application Architecture

### **What Alex's Story Reveals**

Alex's journey isn't about CRUD operations. It's about:

1. **Complex Business Workflows** that span multiple systems
2. **Real-time Integration** with external services
3. **State Management** across the entire journey
4. **Event-Driven Processing** that keeps everyone informed
5. **Business Rule Enforcement** that ensures compliance
6. **User Experience** that makes complex processes feel simple

### **The Technical Reality**

Behind Alex's simple story lies a complex technical architecture:

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Frontend      │    │   API Gateway   │    │   Microservices │
│   (React/Angular)│    │   (Routing)     │    │   (Business Logic)│
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         └───────────────────────┼───────────────────────┘
                                 │
         ┌───────────────────────┼───────────────────────┐
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   External      │    │   Message Bus   │    │   Database      │
│   Services      │    │   (Events)      │    │   (Data)        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

**This is why most applications fail**: They try to build this complex architecture with simple CRUD thinking.

***

## 🚀 Why FlexBase is the Game-Changer

### **The FlexBase Difference: Story-First Development**

**Traditional Approach** (The Path to Hell):

```
1. Create Order table
2. Create Order CRUD operations
3. Figure out how to connect everything
4. Hope it works for the business
5. Spend 2 years fixing the mess
```

**FlexBase Approach** (The Path to Success):

```
1. Understand Alex's complete journey
2. Identify all the systems and people involved
3. Map the business rules and workflows
4. Build the story using FlexBase modules and features
5. Deploy a maintainable, scalable solution
```

### **1. Story-Driven Development** 📚

**FlexBase doesn't start with CRUD. It starts with your story.**

```csharp
// Instead of thinking: "I need an Order CRUD"
// FlexBase thinks: "I need to tell Alex's ordering story"

// Alex discovers products
public class ProductDiscoveryService { }

// Alex adds to cart
public class ShoppingCartService { }

// Alex completes purchase
public class OrderProcessingService { }

// Alex tracks delivery
public class OrderTrackingService { }
```

### **2. Business Domain Focus** 🏢

**FlexBase organizes code around business concepts, not technical operations.**

```
YourApplication/
├── ProductCatalog/          # Alex's product discovery
│   ├── SearchProducts/
│   ├── CompareProducts/
│   └── GetRecommendations/
├── ShoppingCart/            # Alex's shopping experience
│   ├── AddToCart/
│   ├── UpdateCart/
│   └── ValidateCart/
├── OrderProcessing/         # Alex's purchase journey
│   ├── CreateOrder/
│   ├── ProcessPayment/
│   └── ConfirmOrder/
└── OrderFulfillment/        # Alex's delivery tracking
    ├── ScheduleDelivery/
    ├── TrackShipment/
    └── ConfirmDelivery/
```

### **3. Event-Driven Storytelling** 📡

**FlexBase uses events to tell the story across systems.**

```csharp
// When Alex adds items to cart
public class ItemAddedToCartEvent
{
    public string CustomerId { get; set; }
    public string ProductId { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
}

// This event triggers multiple story chapters
- InventoryService.ReserveStock()
- PricingService.CalculateDiscount()
- RecommendationService.UpdateSuggestions()
- NotificationService.SendCartUpdate()
```

### **4. State Machine Storytelling** 🎭

**FlexBase uses state machines to manage story progression.**

```csharp
// Alex's order has a story state
public class OrderState
{
    public OrderState DiscoverProducts() => new OrderState();
    public OrderState AddToCart() => new CartState();
    public OrderState ProcessPayment() => new PaymentState();
    public OrderState ConfirmOrder() => new ConfirmedState();
    public OrderState ShipOrder() => new ShippedState();
    public OrderState DeliverOrder() => new DeliveredState();
}
```

### **5. Microservices as Story Chapters** 📖

**Each microservice tells a part of the story.**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  Product        │    │  Shopping       │    │  Order          │
│  Discovery      │    │  Cart           │    │  Processing     │
│  Service        │    │  Service        │    │  Service        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         └───────────────────────┼───────────────────────┘
                                 │
         ┌───────────────────────┼───────────────────────┐
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  Payment        │    │  Fulfillment    │    │  Notification   │
│  Service        │    │  Service        │    │  Service        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

***

## 🎯 The FlexBase Advantage: Story-First Development

### **1. Start with the Story, Not the Code**

**Traditional Approach** (The Path to Hell):

```
1. Create Order table
2. Create Order CRUD operations
3. Figure out how to connect everything
4. Hope it works for the business
5. Spend 2 years fixing the mess
```

**FlexBase Approach** (The Path to Success):

```
1. Understand Alex's complete journey
2. Identify all the systems and people involved
3. Map the business rules and workflows
4. Build the story using FlexBase modules and features
5. Deploy a maintainable, scalable solution
```

### **2. Business Language, Not Technical Jargon**

**FlexBase uses business terminology that everyone understands:**

```csharp
// Instead of: OrderController.Create()
// FlexBase: OrderProcessingService.ProcessAlexsOrder()

// Instead of: ProductRepository.GetById()
// FlexBase: ProductDiscoveryService.FindPerfectChairs()

// Instead of: PaymentService.Process()
// FlexBase: PaymentProcessingService.CompleteAlexsPurchase()
```

### **3. Complete Story Coverage**

**FlexBase ensures no part of the story is missed:**

* **User Experience**: Clean, intuitive interfaces
* **Business Logic**: Complex rules and workflows
* **Integration**: External systems and services
* **Data Management**: Reliable data storage and retrieval
* **Event Processing**: Real-time updates and notifications
* **State Management**: Consistent story progression
* **Error Handling**: Graceful failure recovery
* **Audit Trail**: Complete story history

### **4. Scalable Storytelling**

**As your business grows, your stories can grow too:**

* **More Characters**: Add new user types and roles
* **More Plot Lines**: Add new business processes
* **More Settings**: Add new systems and integrations
* **More Chapters**: Add new features and capabilities

***

## 💰 The ROI of Story-First Development

### **Cost Comparison: Traditional vs FlexBase**

| Metric                | Traditional CRUD | FlexBase Story-First | Savings             |
| --------------------- | ---------------- | -------------------- | ------------------- |
| **Development Time**  | 12 months        | 4 months             | **67% faster**      |
| **Technical Debt**    | $500K+           | $50K                 | **90% reduction**   |
| **Maintenance Cost**  | $200K/year       | $25K/year            | **87% reduction**   |
| **Bug Count**         | 150+ bugs        | 15 bugs              | **90% reduction**   |
| **User Satisfaction** | 60%              | 95%                  | **58% improvement** |
| **Time to Market**    | 18 months        | 6 months             | **67% faster**      |

**Total 3-Year Savings: $2.1 Million** 💰

### **The Competitive Advantage**

While your competitors are struggling with technical debt and maintenance nightmares, you'll be:

* **Launching new features** every month
* **Scaling your business** without technical constraints
* **Capturing market share** with superior user experience
* **Innovating** while they're fixing bugs

***

## 🚀 Ready to Escape the CRUD Trap?

### **Your Next Steps**

1. **Identify Your Main Character**: Who is your primary user?
2. **Map Their Journey**: What story are they trying to tell?
3. **Identify Supporting Characters**: What systems and people are involved?
4. **Define the Plot**: What are the key business processes?
5. **Choose Your Setting**: What technology environment will you use?

### **FlexBase: The Perfect Storytelling Tool**

FlexBase isn't just a framework - it's a storytelling platform that helps you:

* **Build Complete Stories**: From beginning to end
* **Connect All Characters**: Users, systems, and processes
* **Manage Complex Plots**: Business rules and workflows
* **Scale Your Narratives**: As your business grows
* **Maintain Story Consistency**: Across all systems and teams

***

## 🎭 The Bottom Line

**Stop thinking about CRUD operations. Start thinking about stories.**

Every application is a story about people trying to accomplish something meaningful. FlexBase gives you the tools to tell those stories in a way that's:

* **Technically Sound**: Built on solid architectural principles
* **Business Focused**: Organized around real business needs
* **User Centric**: Designed for real user experiences
* **Scalable**: Ready to grow with your business
* **Maintainable**: Easy to understand and modify

**Ready to start telling your story? Let's begin with** [**Getting Started**](/solution-structure/getting-started)**!** 🚀

***

## 🎯 The Choice is Yours

**Option 1: Continue with CRUD thinking**

* Spend 2 years building a "simple" application
* Drown in technical debt and maintenance nightmares
* Watch your competitors capture your market share
* **Cost: $2+ million and your business**

**Option 2: Embrace story-first development with FlexBase**

* Build a complete business solution in 6 months
* Deploy maintainable, scalable applications
* Focus on innovation and growth
* **Cost: $500K and unlimited potential**

**The choice is yours. Choose wisely.** 🎯

***

*"The best applications don't just work - they tell a story that users love to be part of."* - The FlexBase Philosophy


# Core Concepts

## 🏗️ The Foundation of Enterprise Applications

Every great application starts with a story - a user journey that flows through business processes, integrates with external systems, and delivers real value. But building these applications shouldn't require you to become a framework expert or infrastructure specialist.

**FlexBase** is the architectural framework that transforms how you build enterprise applications. It provides the solid foundation, robust infrastructure, and scalable patterns that let you focus on what matters most - your business logic and user experience.

## 🎯 What Makes FlexBase Different

### **Strategic Abstraction, Not Over-Engineering**

* **Infrastructure Abstraction**: Abstracts database and message bus complexities while preserving full provider capabilities
* **Zero Framework Code**: No boilerplate, no repetitive patterns, no framework lock-in
* **Technology Evolution Ready**: Seamlessly adapts to new versions of EF Core, NServiceBus, and .NET

### **Built for Scale from Day One**

* **100 Users to Millions**: Start small, scale infinitely without rewriting business code
* **Configuration-Driven Scaling**: Infrastructure changes, not code changes
* **Cloud-Native Architecture**: Optimized for AWS, Azure, and Google Cloud

### **Enterprise-Grade Patterns**

* **Domain-Driven Design**: Business logic at the center, not an afterthought
* **CQRS**: Separate command and query execution for optimal performance
* **Event-Driven Architecture**: Loose coupling, high cohesion, real-time processing
* **Modular Monolith**: Start organized, evolve to microservices when needed

## 🚀 Core Architectural Principles

### **1. Domain-Centric Design**

```
Business Logic → Domain Models → State Machines → Business Rules
```

Your business logic drives the architecture, not the other way around.

### **2. Command Query Responsibility Segregation (CQRS)**

* **Commands**: Write operations with full business validation
* **Queries**: Read operations optimized for performance
* **Independent Scaling**: Scale reads and writes separately

### **3. Event-Driven Architecture**

* **Asynchronous Processing**: Non-blocking operations
* **Loose Coupling**: Services communicate through events
* **Real-Time Updates**: Instant notifications and state changes

### **4. Strategic Infrastructure Abstraction**

* **Database**: Full EF Core power with multi-provider support (SQL Server, MySQL, PostgreSQL, Oracle)
* **Message Bus**: Complete NServiceBus capabilities with multiple transport options
* **Zero Capability Loss**: Access to all advanced features when needed

## 🏢 Scaling Journey: From Startup to Enterprise

### **Phase 1: Modular Monolith (100-1,000 users)**

* Single application with organized modules
* Shared database with connection pooling
* In-memory message bus for development

### **Phase 2: Optimized Monolith (1,000-10,000 users)**

* Read/write database separation
* Message queue integration (RabbitMQ, Azure Service Bus)
* Load balancer configuration

### **Phase 3: Microservices (10,000-100,000 users)**

* Independent FlexBase applications
* Dedicated databases per service
* API Gateway and service discovery

### **Phase 4: Cloud-Native (100,000+ users)**

* Auto-scaling containers
* Managed databases and message queues
* Global distribution and CDN
* **Cloud Agnostic**: Deploy on any cloud platform or hybrid environments

## 🛠️ Technology Stack

### **Core Framework**

* **.NET 8 & .NET 9**: Microsoft .NET platform support
* **Cross-Platform**: Runs on Windows, Linux, and macOS
* **Cloud Agnostic**: Deploy anywhere - AWS, Azure, Google Cloud, or on-premises
* **Entity Framework Core**: Multi-provider ORM with full capabilities
* **NServiceBus**: Enterprise message bus with multiple transports
* **ASP.NET Core**: High-performance web API framework

### **Database Support**

* **SQL Server**: Enterprise-grade relational database
* **MySQL**: Open-source relational database
* **PostgreSQL**: Advanced open-source database
* **Oracle**: Enterprise database with advanced features

### **Message Bus Transports**

* **Learning**: Development and testing
* **RabbitMQ**: High-performance message broker
* **SQL Server**: Database-based messaging
* **Azure Service Bus**: Cloud-native messaging
* **Azure Storage Queue**: Simple cloud messaging
* **Amazon SQS**: AWS messaging service

## 🎨 The FlexBase Advantage

### **For Developers**

* **Focus on Business Logic**: No infrastructure distractions
* **Familiar Patterns**: Standard .NET and EF Core patterns
* **Full Capabilities**: Access to all advanced features when needed
* **Rapid Development**: Generate enterprise-ready code in minutes

### **For Architects**

* **Scalable Design**: Built for growth from day one
* **Technology Flexibility**: Switch providers without code changes
* **Maintainable Code**: Clean architecture with clear separation of concerns
* **Future-Proof**: Evolves with technology without rewrites

### **For Organizations**

* **Reduced Technical Debt**: Clean, maintainable codebase
* **Faster Time to Market**: Focus on features, not infrastructure
* **Lower Total Cost**: Efficient resource utilization and scaling
* **Cloud Flexibility**: Deploy anywhere without vendor lock-in
* **Competitive Advantage**: Enterprise-grade applications at startup speed

## 🚀 Getting Started

FlexBase is built for Microsoft .NET development teams and is available on **.NET 8 and .NET 9**. Whether you're building your first enterprise application or scaling an existing system, FlexBase provides the foundation you need to succeed.

**Ready to transform how you build applications?** Let's dive into the specific concepts and patterns that make FlexBase the choice for modern enterprise development.


# Flexbase

## ⚡ What is Flexbase?

**Flexbase** is a revolutionary .NET Core framework library and code generator that transforms how you build enterprise applications. Instead of spending weeks writing boilerplate code, Flexbase generates **complete, production-ready business modules in just 30 minutes**.

***

## 🎯 The Problem Flexbase Solves

### **Traditional Enterprise Development:**

* ⏰ **2-3 weeks** to build a single business module
* 🔧 **Weeks of boilerplate** - controllers, DTOs, repositories, validation
* 🐛 **Inconsistent patterns** across teams and modules
* 💸 **High maintenance costs** and technical debt
* 😤 **Developer frustration** with repetitive, mundane tasks

### **With Flexbase:**

* ⚡ **30 minutes** to generate a complete business module
* 🎯 **95% less code** - focus on business logic, not infrastructure
* 🏗️ **Enterprise patterns** built-in from day one
* 💰 **Massive cost savings** - 75-80% reduction in development time
* 😊 **Happy developers** who focus on solving business problems

***

## 🏗️ What Flexbase Generates Automatically

### **Complete Business Module in 30 Minutes:**

```
📦 Your Business Module
├── 🎯 Domain Models (with business logic)
├── 🌐 REST API Controllers (full CRUD)
├── 📊 Database Integration (auto-migrations)
├── 🔄 Message Bus Integration (events/commands)
├── 📝 DTOs & Validation (input/output)
├── 🗺️ AutoMapper Configuration (complex projections)
├── 🔧 Command/Query Handlers (CQRS pattern)
├── 📡 Event Publishers/Subscribers (event-driven)
└── 🧪 Testing Infrastructure (unit/integration)
```

### **Enterprise Architecture Patterns Built-In:**

* ✅ **Clean Architecture** - Domain, Application, Infrastructure layers
* ✅ **CQRS** - Command Query Responsibility Segregation
* ✅ **Event-Driven Architecture** - Loose coupling through events
* ✅ **Repository Pattern** - Database abstraction
* ✅ **Domain-Driven Design** - Rich domain models
* ✅ **Dependency Injection** - Full IoC container integration

***

## 🎯 What You Actually Write

### **Instead of 2-3 weeks of infrastructure code, you write:**

```csharp
// 1. Define your domain model (5 minutes)
public partial class Order : DomainModelBridge
{
    [Required]
    [StringLength(50)]
    public string CustomerId { get; set; }

    [Range(0.01, double.MaxValue)]
    public decimal TotalAmount { get; set; }

    // 2. Add your business logic (10 minutes)
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // Your custom business rules here
        if (cmd.Dto.TotalAmount > 10000)
        {
            throw new BusinessException("Order amount exceeds limit");
        }
        
        this.Convert(cmd.Dto);
        this.SetAdded(cmd.Dto.GetGeneratedId());
        return this;
    }
}

// 3. Run code generation (15 minutes)
// That's it! Complete enterprise module ready.
```

**Result:** Full REST API, database integration, message bus, validation, and more - all generated automatically!

***

## 🚀 Real-World Impact

### **Development Speed:**

* **Traditional:** 2-3 weeks per module
* **Flexbase:** 30 minutes per module
* **Time Savings:** 95% reduction

### **Cost Savings:**

* **10-Module Enterprise App:**
  * Traditional: 1.5-2.5 years, $2-4 million
  * Flexbase: 8-13 months, $800K-1.5 million
  * **Savings:** $1.2-2.5 million, 6-11 months

### **Quality Improvements:**

* **Consistent Architecture** - Every module follows identical patterns
* **Best Practices** - Enterprise patterns built-in
* **Type Safety** - Compile-time validation throughout
* **Maintainability** - Clear separation of concerns

***

## 🎯 Perfect For

### **Enterprise Development Teams:**

* 🏢 **Large Organizations** - Standardize development across teams
* 🚀 **Startups** - Move fast without sacrificing quality
* 🔄 **Legacy Modernization** - Quickly rebuild existing systems
* 📈 **Scaling Teams** - Onboard developers faster

### **Use Cases:**

* 💼 **E-Commerce Platforms** - Orders, products, payments, customers
* 🏦 **Financial Systems** - Transactions, accounts, reporting
* 🏥 **Healthcare Applications** - Patients, appointments, records
* 🏭 **Manufacturing** - Inventory, production, quality control
* 📊 **Business Applications** - Any domain with complex business logic

***

## 🛠️ Getting Started is Simple

### **1. Install Flexbase**

Use Flexbase Studio to model your application and generate solution and project structure within minutes using FlexGen

### **2. Define Your Domain**

```csharp
public partial class Product : DomainModelBridge
{
    [Required]
    public string Name { get; set; }
    
    [Range(0.01, double.MaxValue)]
    public decimal Price { get; set; }
}
```

### **3. Generate Your Module**

Use Flexbase Studio to model your application and generate solution and project structure within minutes using FlexGen

### **4. Add Business Logic**

```csharp
// Add your custom business rules
public virtual Product AddProduct(AddProductCommand cmd)
{
    // Your business logic here
    return this;
}
```

### **5. Deploy**

Use your favourite Dev Ops tool to deploy your application

**Total Time: 37 minutes for a complete enterprise module!**

***

## 🌟 Why Choose Flexbase?

### **For Developers:**

* ⚡ **Upto 95% faster development** - Focus on business logic, not plumbing
* 🎯 **Consistent patterns** - Same structure across all modules
* 🧪 **Easy testing** - Built-in test infrastructure
* 📚 **Great documentation** - Self-documenting generated code

### **For Business:**

* 💰 **Massive cost savings** - 75-80% reduction in development costs
* 🚀 **Faster time-to-market** - Ship features in days, not months
* 🔒 **Enterprise-grade quality** - Battle-tested patterns
* 📈 **Scalable architecture** - Ready for growth

### **For Organizations:**

* 🏗️ **Standardized development** - Consistent across all teams
* 👥 **Faster onboarding** - New developers productive immediately
* 🔧 **Easy maintenance** - Clear, readable generated code
* 🎯 **Focus on business value** - Less time on infrastructure

***

## 🎉 The Bottom Line

**Flexbase transforms enterprise development from a slow, expensive, error-prone process into a fast, cost-effective, and enjoyable experience.**

Instead of spending weeks on infrastructure code, you focus on what matters most: **solving business problems and delivering value to your users**.

***

*Transform your development process today. Join thousands of developers who have already discovered the power of Flexbase.*

**Start building enterprise applications the way they should be built - fast, consistent, and focused on business value.**


# Architecture Overview

## 🏗️ Solution Overview

The Application created with Flexbase is a modern, enterprise-grade .NET 9 application built using **Clean Architecture** principles with **Domain-Driven Design (DDD)** patterns. It leverages the **Sumeru.Flex** framework to provide a robust, scalable foundation for business applications.

## 📋 Table of Contents

1. [Architecture Overview](#architecture-overview)
2. [Solution Structure](#solution-structure)
3. [Core Architectural Patterns](#core-architectural-patterns)
4. [Technology Stack](#technology-stack)
5. [Best Practices Implemented](#best-practices-implemented)
6. [Configuration Management](#configuration-management)
7. [Database Strategy](#database-strategy)
8. [Messaging & Communication](#messaging--communication)
9. [Multi-Tenancy Support](#multi-tenancy-support)
10. [Deployment & Scalability](#deployment--scalability)

***

## 🏛️ Architecture Overview

### High-Level Architecture

```mermaid
graph TB
    subgraph "Presentation Layer"
        WebAPI[Web API Endpoints]
        Controllers[Controllers]
        CronJobs[Background Jobs]
    end
    
    subgraph "Application Layer"
        Handlers[Command Handlers]
        Queries[Query Handlers]
        Services[Application Services]
        DTOs[Data Transfer Objects]
    end
    
    subgraph "Domain Layer"
        Models[Domain Models]
        Events[Domain Events]
        Rules[Business Rules]
    end
    
    subgraph "Infrastructure Layer"
        Database[(Database)]
        MessageBus[Message Bus]
        ExternalAPIs[External APIs]
    end
    
    subgraph "Framework Layer"
        FlexCore[Sumeru.Flex Core]
        Bridges[Framework Bridges]
    end
    
    WebAPI --> Controllers
    Controllers --> Handlers
    Controllers --> Queries
    Handlers --> Models
    Queries --> Models
    Handlers --> MessageBus
    MessageBus --> Database
    FlexCore --> Bridges
    Bridges --> Handlers
    Bridges --> Queries
```

### Key Architectural Principles

* **Separation of Concerns**: Clear boundaries between layers
* **Dependency Inversion**: High-level modules don't depend on low-level modules
* **Single Responsibility**: Each component has one reason to change
* **Open/Closed Principle**: Open for extension, closed for modification
* **Interface Segregation**: Clients depend only on interfaces they use

***

## 📁 Solution Structure

### Project Organization

```
YourApplication_blank_sol/
├── YourApplication.Application/           # Application Layer
│   ├── ControlContracts/           # API Contracts & DTOs
│   │   ├── YourApplication.DTOs/        # Data Transfer Objects
│   │   ├── YourApplication.Messages/    # Message Contracts
│   │   └── YourApplication.SharedEvents/ # Shared Domain Events
│   ├── ControlHub/                 # API Controllers & Jobs
│   │   ├── YourApplication.WebControllers/
│   │   └── YourApplication.CronJobs/
│   ├── Domain/                     # Domain Layer
│   │   ├── YourApplication.CommonLib/   # Common Utilities
│   │   ├── YourApplication.DomainModels/ # Domain Entities
│   │   └── YourApplication.Mappers/     # Object Mapping
│   ├── DomainHandler/              # CQRS Implementation
│   │   ├── YourApplication.Handlers/    # Command Handlers
│   │   ├── YourApplication.Queries/     # Query Handlers
│   │   ├── YourApplication.PreBus/      # Message Preprocessing
│   │   └── YourApplication.RESTClients/ # External API Clients
│   ├── EndPoints/                  # Application Hosts
│   │   ├── YourApplication.EndPoint.WebAPI/
│   │   ├── YourApplication.EndPoint.Handlers.Default/
│   │   ├── YourApplication.EndPoint.Subscribers.Default/
│   │   ├── YourApplication.EndPoint.CronJob/
│   │   └── DbMigrations/          # Database Migrations
│   └── Infrastructure/             # Infrastructure Layer
│       ├── Bus/                   # Message Bus (NServiceBus)
│       └── Db/                    # Database Implementations
└── YourApplication.Framework/            # Framework Layer
    ├── Bridge/                    # Framework Bridges
    └── PostBus/                   # Message Bus Interfaces
```

***

## 🎯 Core Architectural Patterns

### 1. Clean Architecture

The solution follows Clean Architecture principles with clear layer separation:

* **Domain Layer**: Contains business logic and entities
* **Application Layer**: Contains use cases and application services
* **Infrastructure Layer**: Contains external concerns (database, messaging)
* **Presentation Layer**: Contains controllers and API endpoints

### 2. CQRS (Command Query Responsibility Segregation)

```csharp
// Command Pattern
public abstract class FlexCommandBridge : FlexCommand, IFlexCommandBridge
{
    // Command implementation
}

// Query Pattern  
public abstract class FlexQueryBridge : FlexQuery, IFlexQueryBridge
{
    // Query implementation
}
```

**Benefits:**

* Clear separation between read and write operations
* Independent scaling of read/write workloads
* Optimized data models for each operation type

### 3. Domain-Driven Design (DDD)

* **Domain Models**: Rich business entities with behavior
* **Value Objects**: Immutable objects representing concepts
* **Domain Events**: Business events that occur in the domain
* **Aggregates**: Consistency boundaries for domain objects

### 4. Event-Driven Architecture

```csharp
public abstract class FlexEventBridge : FlexEvent, IFlexEventBridge
{
    // Event implementation
}
```

**Features:**

* Loose coupling between components
* Asynchronous processing
* Event sourcing capabilities
* Eventual consistency

### 5. Vertical Slice Architecture (Partial Implementation)

The solution demonstrates elements of **Vertical Slice Architecture** by organizing functionality around business capabilities rather than technical layers:

#### Identified Vertical Slices

```mermaid
graph TB
    subgraph "Business Capabilities (Vertical Slices)"
        subgraph "Web API Slice"
            WebAPI[Web API Endpoint]
            WebControllers[Web Controllers]
            WebDTOs[API DTOs]
        end
        
        subgraph "Command Processing Slice"
            Handlers[Command Handlers]
            HandlerEndPoint[Handler Endpoint]
            HandlerMessages[Command Messages]
        end
        
        subgraph "Query Processing Slice"
            Queries[Query Handlers]
            QueryDTOs[Query DTOs]
            QueryMappers[Query Mappers]
        end
        
        subgraph "Event Processing Slice"
            Subscribers[Event Subscribers]
            SubscriberEndPoint[Subscriber Endpoint]
            SharedEvents[Shared Events]
        end
        
        subgraph "Background Processing Slice"
            CronJobs[Background Jobs]
            CronJobEndPoint[Cron Job Endpoint]
            JobSchedules[Job Schedules]
        end
        
        subgraph "External Integration Slice"
            RESTClients[External API Clients]
            RetryPolicies[Retry Policies]
            ExternalDTOs[External DTOs]
        end
    end
    
    WebAPI --> WebControllers
    Handlers --> HandlerEndPoint
    Queries --> QueryDTOs
    Subscribers --> SubscriberEndPoint
    CronJobs --> CronJobEndPoint
    RESTClients --> ExternalDTOs
```

#### Vertical Slice Characteristics

**1. Feature-Based Organization**

* Each slice represents a complete business capability
* Contains all layers needed for that capability
* Minimal coupling between slices

**2. Self-Contained Slices**

```csharp
// Example: Web API Slice
YourApplication.WebControllers/          # Presentation
├── Controllers/                   # API Controllers
└── DTOs/                         # API Contracts

// Example: Command Processing Slice  
YourApplication.Handlers/               # Application Logic
├── CommandHandlers/              # Business Logic
└── Messages/                     # Command Contracts

// Example: External Integration Slice
YourApplication.RESTClients/            # Infrastructure
├── ExternalAPIs/                 # External Services
└── RetryPolicies/                # Resilience Patterns
```

**3. Independent Deployment**

* Each endpoint can be deployed independently
* Separate scaling for different capabilities
* Technology-agnostic slice boundaries

**4. Shared Infrastructure**

* Common framework bridges
* Shared domain models
* Centralized configuration

#### Benefits of Vertical Slice Architecture

* **Business Alignment**: Code organization matches business capabilities
* **Team Autonomy**: Teams can work on slices independently
* **Reduced Coupling**: Changes in one slice don't affect others
* **Easier Testing**: Each slice can be tested in isolation
* **Independent Scaling**: Scale slices based on business needs

***

## 🛠️ Technology Stack

### Core Technologies

| Component      | Technology            | Version | Purpose             |
| -------------- | --------------------- | ------- | ------------------- |
| **Runtime**    | .NET                  | 9.0     | Application runtime |
| **Framework**  | Sumeru.Flex           | 9.0.0   | Core framework      |
| **ORM**        | Entity Framework Core | Latest  | Data access         |
| **Messaging**  | NServiceBus           | Latest  | Message bus         |
| **Mapping**    | AutoMapper            | 13.0.1  | Object mapping      |
| **Logging**    | Serilog               | Latest  | Structured logging  |
| **Validation** | FluentValidation      | Latest  | Input validation    |

### Database Support

* **SQL Server** - Primary database
* **MySQL** - Alternative database
* **PostgreSQL** - Alternative database
* **Multi-tenant** - Separate database per tenant

### Message Bus Options

* **RabbitMQ** - Open-source message broker
* **Azure Service Bus** - Cloud messaging service
* **SQL Server** - Database-based messaging
* **Learning Transport** - Development/testing

***

## ✅ Best Practices Implemented

### 1. Configuration Management

#### Multi-Source Configuration Strategy

```csharp
public class AutoConfigurationProvider : IHostConfigurationProvider
{
    public void Configure(IConfigurationBuilder configBuilder, HostBuilderContext context, string? userSecretName = null)
    {
        configBuilder
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
            
        if (!string.IsNullOrEmpty(userSecretName) && context.HostingEnvironment.IsDevelopment())
        {
            configBuilder.AddUserSecrets(userSecretName);
        }
        
        // Azure Key Vault integration
        var keyVaultName = tempConfig["Azure:KeyVaultName"];
        if (!string.IsNullOrEmpty(keyVaultName))
        {
            var keyVaultUri = new Uri($"https://{keyVaultName}.vault.azure.net/");
            configBuilder.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());
        }
    }
}
```

**Configuration Priority (Highest to Lowest):**

1. Command Line Arguments
2. Azure Key Vault
3. User Secrets (Development only)
4. Environment Variables
5. appsettings.{Environment}.json
6. appsettings.json

### 2. Dependency Injection

#### Service Registration Pattern

```csharp
public static class DbEndPointConfig
{
    public static void AddFlexBaseDbServices(this IServiceCollection services)
    {
        // Single Tenant Configuration
        EnableSingleTenant(services);
        
        // Multi Tenant Configuration (commented)
        //EnableMultitenant(services);
    }
    
    private static void EnableSingleTenant(IServiceCollection services)
    {
        ConfigureSingleTenantDb(services);
        ConfigureFlexDb.ForRepositoryForSqlServer(services);
    }
}
```

### 3. Error Handling

#### Custom Exception Types

```csharp
public class BadRequestException : Exception
{
    public BadRequestException(string message) : base(message) { }
}

public class InternalServerErrorException : Exception
{
    public InternalServerErrorException(string message) : base(message) { }
}
```

### 4. Logging Strategy

* **Structured Logging** with Serilog
* **Correlation IDs** for request tracing
* **Environment-specific** log levels
* **Centralized** logging configuration

### 5. Database Patterns

#### Repository Pattern with Unit of Work

```csharp
// Single Tenant
services.AddTransient<IWriteDbConnectionProviderBridge, AppSettingsWriteDbConnectionProvider>();
services.AddTransient<IReadDbConnectionProviderBridge, AppSettingsReadDbConnectionProvider>();

// Multi Tenant Support
ConfigureFlexDb.ForMultitenantMasterDbForSqlServer(services);
ConfigureFlexDb.ForRepositoryForSqlServer(services);
```

### 6. Object Mapping

#### AutoMapper Configuration

```csharp
public class CoreMapperConfiguration : FlexMapperProfile
{
    public CoreMapperConfiguration() : base()
    {
        #region Input
        //CreateMap<YourAPIModel, YourDomainModel>();
        #endregion

        #region Output
        //CreateMap<YourDomainModel, YourOutputAPIModel>();
        #endregion
    }
}
```

***

## ⚙️ Configuration Management

### Environment-Specific Configuration

The solution supports multiple environments with specific configuration files:

* `appsettings.json` - Base configuration
* `appsettings.Development.json` - Development overrides
* `appsettings.Staging.json` - Staging overrides
* `appsettings.Production.json` - Production overrides
* `appsettings.EndPoint.json` - Endpoint-specific configuration

### Security Best Practices

1. **Secrets Management**
   * User Secrets for development
   * Azure Key Vault for production
   * Environment variables for containers
2. **Configuration Validation**
   * Strongly-typed configuration classes
   * Runtime validation of required settings
   * Fail-fast on missing critical configuration

***

## 🗄️ Database Strategy

### Multi-Database Support

The solution supports multiple database providers:

#### Single Tenant

```csharp
private static void EnableSingleTenant(IServiceCollection services)
{
    ConfigureSingleTenantDb(services);
    ConfigureFlexDb.ForRepositoryForSqlServer(services);
}
```

#### Multi Tenant

```csharp
private static void EnableMultitenant(IServiceCollection services)
{
    ConfigureMultiTenantMasterDb(services);
    ConfigureFlexDb.ForMultitenantMasterDbForSqlServer(services);
    ConfigureFlexDb.ForRepositoryForSqlServer(services);
}
```

### Migration Strategy

Separate migration projects for each database type:

* `YourApplication.Migrations.SqlServer`
* `YourApplication.Migrations.MySql`
* `YourApplication.Migrations.PostgreSql`
* `YourApplication.Migrations.Tenant.*` (for multi-tenant)

### Database Factory Pattern

```csharp
public class ApplicationEFDbContextFactory : IDesignTimeDbContextFactory<ApplicationEFDbMigrationContext>
{
    public ApplicationEFDbMigrationContext CreateDbContext(string[] args)
    {
        // Configuration and service setup
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables().Build();
            
        // Service collection setup
        var services = new ServiceCollection();
        services.AddSingleton<IConfiguration>(configuration);
        
        // FlexBase configuration
        services.AddFlexBase(new List<AssembliesToLoad> { 
            new AssembliesToLoad("YourApplication*.dll") 
        });
        
        return serviceProvider.GetRequiredService<ApplicationEFDbMigrationContext>();
    }
}
```

***

## 📨 Messaging & Communication

### NServiceBus Integration

The solution uses NServiceBus for reliable messaging with multiple transport options:

#### RabbitMQ Configuration

```csharp
public class RabbitMqNsbConfiguration : NsbBaseConfiguration
{
    public RabbitMqNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, 
        IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endpointName, configuration, env, errorQueueName)
    {
        // Persistence configuration
        var persistence = this.UsePersistence<SqlPersistence>();
        persistence.SqlDialect<SqlDialect.MsSqlServer>();
        persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));

        // Transport configuration
        var transport = this.UseTransport<RabbitMQTransport>();
        transport.ConnectionString(rabbitMqConnectionString);
        transport.UseConventionalRoutingTopology(QueueType.Classic);

        // Routing configuration
        var routing = transport.Routing();
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

#### Azure Service Bus Configuration

```csharp
public class AzureServiceNsbConfiguration : NsbBaseConfiguration
{
    public AzureServiceNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, 
        IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endpointName, configuration, env, errorQueueName)
    {
        // Azure Service Bus transport
        var transport = new AzureServiceBusTransport(azureServiceBusConnectionString);
        this.UseTransport(transport);

        // Routing configuration
        var routing = this.UseTransport(transport);
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

### Message Types

* **Commands**: Request for action
* **Events**: Notification of something that happened
* **Queries**: Request for data

***

## 🏢 Multi-Tenancy Support

### Tenant Isolation Strategies

1. **Database per Tenant**: Complete isolation
2. **Schema per Tenant**: Shared database, separate schemas
3. **Row-level Security**: Shared database with tenant filtering

### Implementation

```csharp
public class TenantMigrationContext : ApplicationTenantEFDbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        
        var connectionString = _configuration.GetSection("FlexBase")["AppDbTenantConnection"];
        optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
    }
}
```

***

## 🚀 Deployment & Scalability

### Application Endpoints

The solution provides multiple deployment options:

1. **Web API Endpoint** - REST API services
2. **Handler Endpoint** - Command processing
3. **Subscriber Endpoint** - Event processing
4. **Cron Job Endpoint** - Scheduled tasks

### Scalability Features

* **Horizontal Scaling**: Multiple instances of each endpoint
* **Load Balancing**: Built-in support for load balancers
* **Message Queuing**: Asynchronous processing
* **Database Sharding**: Multi-tenant database support
* **Caching**: Ready for implementation (not yet built-in)

### Container Support

* **Docker** ready configuration
* **Environment variables** for configuration
* **Health checks** for monitoring
* **Graceful shutdown** support

***

## 🎯 Key Benefits

### For Developers

1. **Rapid Development**: Pre-built patterns and infrastructure
2. **Type Safety**: Strong typing throughout the application
3. **Testability**: Easy to unit test with dependency injection
4. **Maintainability**: Clear separation of concerns
5. **Extensibility**: Easy to add new features

### For Operations

1. **Reliability**: Built-in error handling and retry mechanisms
2. **Monitoring**: Comprehensive logging and metrics
3. **Scalability**: Horizontal scaling capabilities
4. **Security**: Built-in security best practices
5. **Deployment**: Multiple deployment options

### For Business

1. **Time to Market**: Faster development cycles
2. **Cost Effective**: Reduced infrastructure costs
3. **Flexibility**: Easy to adapt to changing requirements
4. **Compliance**: Built-in audit trails and security
5. **Integration**: Easy integration with external systems

***

## 🔧 Getting Started

### Prerequisites

* .NET 8, 9 SDK
* Visual Studio 2022 or VS Code
* SQL Server, MySQL, or PostgreSQL
* RabbitMQ or Azure Service Bus or Azure Storage Queue Or Amazon Sqs (for messaging)

### Quick Start

1. **Clone the repository**
2. **Configure connection strings** in appsettings.json
3. **Run database migrations**
4. **Start the Web API endpoint**
5. **Start message handlers** (if using messaging)

### Configuration

1. **Update appsettings.json** with your database connection
2. **Configure message bus** settings
3. **Set up logging** configuration
4. **Configure multi-tenancy** (if needed)

***

## 🔮 Future Enhancements

### Caching Strategy (Planned)

While caching is not yet implemented, the architecture is designed to easily accommodate various caching strategies:

#### Recommended Caching Options

* **Redis**: Distributed caching for multi-instance scenarios
* **In-Memory Caching**: For single-instance applications
* **Response Caching**: HTTP response caching
* **Query Result Caching**: Database query result caching

#### Implementation Approach

```csharp
// Example future caching implementation
public class CachedQueryHandler<TQuery, TResult> : IQueryHandler<TQuery, TResult>
{
    private readonly IQueryHandler<TQuery, TResult> _decorated;
    private readonly IMemoryCache _cache;
    
    public async Task<TResult> HandleAsync(TQuery query)
    {
        var cacheKey = GenerateCacheKey(query);
        
        if (_cache.TryGetValue(cacheKey, out TResult cachedResult))
        {
            return cachedResult;
        }
        
        var result = await _decorated.HandleAsync(query);
        _cache.Set(cacheKey, result, TimeSpan.FromMinutes(5));
        
        return result;
    }
}
```

#### Benefits of Adding Caching

* **Performance**: Reduced database load and faster response times
* **Scalability**: Better handling of high-traffic scenarios
* **Cost Efficiency**: Reduced infrastructure costs
* **User Experience**: Improved application responsiveness

### Vertical Slice Architecture Enhancement (Recommended)

The current solution has a foundation for vertical slice architecture but can be enhanced to be more feature-centric:

#### Current State

* **Technical Slices**: Organized by technical concerns (Handlers, Queries, Controllers)
* **Shared Infrastructure**: Common framework and domain models
* **Independent Endpoints**: Each capability can be deployed separately

#### Recommended Enhancements

**1. Feature-Based Slices**

```
YourApplication.Features/
├── UserManagement/
│   ├── Controllers/
│   ├── Commands/
│   ├── Queries/
│   ├── Events/
│   └── DTOs/
├── OrderProcessing/
│   ├── Controllers/
│   ├── Commands/
│   ├── Queries/
│   ├── Events/
│   └── DTOs/
└── PaymentProcessing/
    ├── Controllers/
    ├── Commands/
    ├── Queries/
    ├── Events/
    └── DTOs/
```

**2. Slice-Specific Infrastructure**

```csharp
// Each slice can have its own infrastructure
public class UserManagementSlice
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Slice-specific services
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<IUserNotificationService, UserNotificationService>();
    }
}
```

**3. Cross-Slice Communication**

```csharp
// Events for cross-slice communication
public class UserCreatedEvent : IFlexEvent
{
    public Guid UserId { get; set; }
    public string Email { get; set; }
    public DateTime CreatedAt { get; set; }
}

// Other slices can subscribe to events
public class OrderProcessingSlice
{
    public void Handle(UserCreatedEvent @event)
    {
        // Create welcome order for new user
    }
}
```

#### Benefits of Enhanced Vertical Slices

* **Business Focus**: Code organization matches business domains
* **Team Ownership**: Clear ownership boundaries
* **Independent Evolution**: Features can evolve independently
* **Easier Onboarding**: New developers can focus on specific business areas
* **Reduced Complexity**: Smaller, focused codebases

***

***

*This architecture documentation provides a comprehensive overview of the Flexbase solution's design patterns, best practices, and implementation strategies. The solution demonstrates enterprise-grade .NET development practices with a focus on maintainability, scalability, and developer productivity.*


# Flexbase Edge

## 🚀 Complete Business Module Generation

The Flexbase automatically generates **complete, production-ready business modules** in minutes instead of weeks, following enterprise architectural patterns.

***

## ⚡ What Gets Generated Automatically

### **Complete Infrastructure & Plumbing Code**

```
Orders Module (30 minutes generation):
├── 🎯 Domain Models (Structure + Attributes)
├── 🌐 REST API Controllers (Full CRUD)
├── 📊 Database Integration (Auto-migrations)
├── 🔄 Message Bus Integration (Events/Commands)
├── 📝 DTOs & Validation (Input/Output)
├── 🗺️ AutoMapper Configuration (Quick SelectTo)
├── 🔧 Command/Query Handlers (Orchestration)
├── 📡 Event Publishers/Subscribers (Event Flow)
└── 🧪 Testing Infrastructure (Unit/Integration)
```

### **Developer Only Writes:**

* **Business Attributes** - Domain model attributes and validation rules
* **Quick Validation Logic** - Custom business rule plugins
* **State Machine Logic** - Business workflow transitions
* **Custom Mappings** - Special projection requirements

### **Enterprise Architecture Patterns (Auto-Generated)**

* **Clean Architecture**: Domain, Application, Infrastructure, Presentation layers
* **CQRS**: Separate Commands (write) and Queries (read) operations
* **Event-Driven**: Automatic event publishing and handling
* **Repository Pattern**: Database abstraction with multi-database support
* **Dependency Injection**: Full IoC container integration

***

## 🔄 End-to-End Operation Flow

### **Insert Operation - Complete Journey**

```
API Call → Controller → Service → Command → Handler → Domain → Database → Event → Subscriber
```

**What Happens Automatically (Generated Plumbing):**

1. **Input Validation** - Framework validates all inputs using developer-defined attributes
2. **Business Flow** - Generated handlers orchestrate the business process
3. **Database Persistence** - Automatic save with transaction management
4. **Event Publishing** - Side effects triggered automatically
5. **Response Generation** - Structured API response

**Developer Adds (Business Logic):**

* **Custom Validation Rules** - Business-specific validation logic
* **State Transitions** - Business workflow state changes
* **Domain Events** - Custom business events and side effects

### **Query Operation - Optimized Read Path**

```
API Call → Controller → Query Handler → AutoMapper SelectTo → Database → Response
```

**Generated Query Benefits:**

* **Quick SelectTo** - Complex queries with simple AutoMapper configuration
* **No Complex SELECT** - Framework generates optimized database queries
* **Type Safety** - Compile-time validation throughout
* **Database-Level Optimization** - Only fetch required data
* **Developer Flexibility** - Custom queries when needed

**Developer Query Options:**

```csharp
// Option 1: Quick AutoMapper SelectTo (Generated)
public class GetOrders : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        // Simple SelectTo - no complex SELECT statements
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()
            .ToList();
    }
}

// Option 2: Custom Query (Developer writes when needed)
public class GetOrdersWithCustomLogic : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        // Developer can write custom complex queries
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.CreatedDate >= DateTime.Now.AddDays(-30))
            .Join(_repoFactory.GetRepo().FindAll<Customer>(),
                  o => o.CustomerId,
                  c => c.Id,
                  (order, customer) => new { Order = order, Customer = customer })
            .Select(result => new GetOrdersDto
            {
                Id = result.Order.Id,
                CustomerName = result.Customer.Name,
                TotalAmount = result.Order.TotalAmount,
                // Custom projection logic
                StatusDisplay = GetStatusDisplay(result.Order.Status),
                DaysSinceCreated = (DateTime.UtcNow - result.Order.CreatedDate).Days
            })
            .ToList();
    }
}
```

***

## 📦 Generated Business Modules in Sample Application (EBusiness)

### **1. Orders Module - E-Commerce Order Management**

* ✅ **AddOrder** - Create orders with full validation
* ✅ **AddItemToOrder** - Add products to existing orders
* ✅ **Order Management** - Complete CRUD operations
* ✅ **Order Queries** - Retrieve order information with projections

### **2. Products Module - Product Catalog Management**

* ✅ **AddProduct** - Create new products
* ✅ **UpdateProduct** - Modify existing products
* ✅ **Product Management** - Full lifecycle management
* ✅ **Product Queries** - Search and retrieve products

### **3. Payments Module - Payment Processing**

* ✅ **MakePayment** - Process payment transactions
* ✅ **PaymentConfirmationCallBack** - Handle payment confirmations
* ✅ **Payment Management** - Complete payment lifecycle
* ✅ **Payment Queries** - Retrieve payment information

### **4. Customers Module - Customer Management**

* ✅ **GetCustomers** - Query customer information
* ✅ **Customer Management** - Complete customer lifecycle
* ✅ **Customer Queries** - Advanced search capabilities

***

## 🏗️ Architectural Benefits

### **1. Separation of Concerns**

* **Presentation Layer**: HTTP, validation, serialization
* **Application Layer**: Business orchestration, transactions
* **Domain Layer**: Business logic, rules, domain knowledge
* **Infrastructure Layer**: Data persistence, external services

### **2. Enterprise Patterns Built-In**

* **CQRS**: Commands and Queries automatically separated
* **Domain-Driven Design**: Rich domain models with business logic
* **Event-Driven Architecture**: Automatic event publishing and handling
* **Repository Pattern**: Database abstraction with multi-database support

### **3. Performance & Scalability**

* **Asynchronous Processing**: Non-blocking operations
* **Horizontal Scaling**: Stateless design ready for load balancing
* **Database Optimization**: Projection queries and connection pooling
* **Event-Driven**: Loose coupling through events

***

## 🎯 Business Value

### **For Development Teams**

* **95% Faster Development** - Complete infrastructure in 30 minutes vs 2-3 weeks
* **Focus on Business Logic** - Developers write only attributes and validation rules
* **Consistent Patterns** - Same structure across all modules
* **Zero Configuration** - Auto-generated dependency injection and routing
* **Type Safety** - Compile-time validation throughout

### **For Operations Teams**

* **Reliable Deployments** - Tested patterns and infrastructure
* **Easy Monitoring** - Built-in logging and metrics
* **Scalable Architecture** - Horizontal scaling ready
* **Multi-Database Support** - SQL Server, MySQL, PostgreSQL

### **For Business**

* **Faster Time-to-Market** - Reduced development cycles
* **Lower Costs** - 95% reduction in development time
* **Higher Quality** - Enterprise-grade architecture out-of-the-box
* **Future-Proof** - Easy to extend and modify

***

## 🚀 Key Capabilities

### **Auto-Generated Infrastructure**

* **Complete REST APIs** - Full CRUD operations with documentation
* **Database Integration** - Auto-migrations for multiple databases
* **Message Bus Integration** - Event-driven architecture
* **Validation Framework** - Input validation and error handling
* **Audit Trail** - Automatic change tracking

### **Developer Experience**

* **IntelliSense Support** - Full code completion
* **Refactoring Safety** - IDE refactoring works across all layers
* **Easy Testing** - Mock-friendly interfaces and clear boundaries
* **Consistent Code** - Uniform patterns across all modules

### **Enterprise Features**

* **Multi-Tenant Support** - Database per tenant
* **Security Integration** - Built-in authentication and authorization
* **Logging & Monitoring** - Structured logging with correlation IDs
* **Error Handling** - Consistent error management across all layers

***

## 📊 Performance Impact

### **Development Efficiency - Detailed Analysis**

#### **95% Reduction Calculation (Post-Requirements, Pre-Testing)**

```
Traditional Enterprise Development Cycle:
├── Requirements Analysis: 2-3 days
├── Database Design: 1-2 days
├── API Design: 1-2 days
├── Domain Model Creation: 2-3 days
├── DTOs & Validation: 1-2 days
├── Controller Implementation: 2-3 days
├── Command/Query Handlers: 3-4 days
├── Repository Integration: 1-2 days
├── Message Bus Setup: 2-3 days
├── AutoMapper Configuration: 1-2 days
├── Error Handling: 1-2 days
├── Logging & Monitoring: 1-2 days
├── API Documentation: 1-2 days
├── Code Review & Refactoring: 2-3 days
└── Total: 20-35 days (4-7 weeks)

YourApplication Generated Approach:
├── Requirements Analysis: 2-3 days (same)
├── Domain Model Definition: 0.5 days (attributes only)
├── Code Generation: 0.5 days (30 minutes)
├── Custom Business Logic: 1-2 days (validation rules)
├── Custom Mappings: 0.5 days (if needed)
├── Code Review & Refactoring: 0.5 days (minimal)
└── Total: 5-7 days (1-1.5 weeks)

Time Savings: 15-28 days saved per module
Reduction: 75-80% of total development time
```

#### **Why 95% Reduction in Core Development?**

The 95% reduction applies specifically to the **core development work** (post-requirements, pre-testing):

**Traditional Core Development (15-25 days):**

* Database schema design and migrations
* API endpoint implementation
* Domain model creation with attributes
* DTO creation and validation
* Command/Query handler implementation
* Repository pattern implementation
* Message bus integration
* AutoMapper configuration
* Error handling and logging setup

**YourApplication Core Development (1-2 days):**

* Domain model attributes definition
* Custom business validation rules
* Optional custom mappings

**Calculation: (15-25 days) → (1-2 days) = 90-95% reduction**

#### **Complete Enterprise Development Lifecycle Savings**

**Full Enterprise Development Cycle (Traditional vs YourApplication):**

```
Phase 1: Requirements & Planning (Same for both approaches)
├── Business Requirements: 3-5 days
├── Technical Architecture: 2-3 days
├── Database Design: 2-3 days
├── API Specification: 2-3 days
└── Total: 9-14 days

Phase 2: Core Development (95% reduction with YourApplication)
├── Traditional Approach: 20-35 days
├── YourApplication Approach: 5-7 days
└── Savings: 15-28 days (75-80% reduction)

Phase 3: Testing & Quality Assurance
├── Unit Testing: 3-5 days (Traditional) vs 1-2 days (YourApplication)
├── Integration Testing: 2-3 days (same for both)
├── Performance Testing: 1-2 days (same for both)
├── Security Testing: 1-2 days (same for both)
└── Total: 7-12 days (Traditional) vs 5-9 days (YourApplication)

Phase 4: Deployment & DevOps
├── Environment Setup: 1-2 days (same for both)
├── CI/CD Pipeline: 1-2 days (same for both)
├── Production Deployment: 1 day (same for both)
└── Total: 3-5 days (same for both)

Phase 5: Documentation & Training
├── Technical Documentation: 2-3 days (Traditional) vs 0.5 days (YourApplication)
├── API Documentation: 1-2 days (Traditional) vs 0 days (YourApplication)
├── User Training: 1-2 days (same for both)
└── Total: 4-7 days (Traditional) vs 2-4 days (YourApplication)

TOTAL ENTERPRISE CYCLE:
├── Traditional: 43-73 days (8.5-14.5 weeks)
├── YourApplication: 24-39 days (4.5-8 weeks)
└── Overall Savings: 19-34 days (4-7 weeks)
└── Overall Reduction: 44-47% of total development time
```

#### **How Generated Code Saves Overall Effort**

**1. Reduced Testing Effort:**

* **Consistent Patterns**: Generated code follows identical patterns, reducing test complexity
* **Pre-tested Framework**: Core functionality already tested by framework
* **Fewer Edge Cases**: Standardized error handling reduces edge case testing
* **Auto-generated Tests**: Framework can generate basic unit tests

**2. Reduced Documentation Effort:**

* **Auto-generated API Docs**: Swagger/OpenAPI documentation created automatically
* **Consistent Architecture**: Same patterns across modules reduce documentation needs
* **Self-documenting Code**: Clear separation of concerns makes code self-explanatory

**3. Reduced Maintenance Effort:**

* **Consistent Code Quality**: Generated code maintains consistent quality standards
* **Framework Updates**: Infrastructure updates handled by framework
* **Reduced Technical Debt**: Best practices built-in prevent common issues
* **Easier Debugging**: Clear patterns make issues easier to identify and fix

**4. Reduced Onboarding Effort:**

* **Familiar Patterns**: New developers quickly understand the structure
* **Reduced Learning Curve**: Less custom code to learn
* **Standard Practices**: Framework enforces enterprise best practices

**5. Reduced Integration Effort:**

* **Pre-configured Integration**: Message bus, database, and API integration ready
* **Standardized Interfaces**: Consistent API patterns across all modules
* **Built-in Security**: Authentication and authorization patterns included

#### **Real-World Enterprise Impact**

**For a 10-Module Enterprise Application:**

```
Traditional Development:
├── Total Time: 430-730 days (1.5-2.5 years)
├── Team Size: 8-12 developers
├── Cost: $2-4 million
└── Risk: High (custom code complexity)

YourApplication Development:
├── Total Time: 240-390 days (8-13 months)
├── Team Size: 4-6 developers
├── Cost: $800K-1.5 million
└── Risk: Low (proven framework patterns)

Savings:
├── Time: 190-340 days (6-11 months)
├── Cost: $1.2-2.5 million
├── Team Size: 50% reduction
└── Risk: 70% reduction
```

### **Quality Improvements**

* **Consistent Architecture** - Every module follows identical patterns
* **Best Practices** - Enterprise patterns built-in
* **Error Reduction** - Framework prevents common mistakes
* **Maintainability** - Clear separation of concerns

***

## 🎯 Bottom Line

**YourApplication generates all infrastructure and plumbing code, delivering 95% reduction in core development time and 44-47% reduction in overall enterprise development lifecycle, while maintaining enterprise-grade quality and consistency.**

**Key Benefits:**

* ⚡ **95% faster core development** - Complete infrastructure generated in 30 minutes
* 🎯 **Focus on business logic** - Developers write only attributes and validation
* 🏗️ **Enterprise architecture out-of-the-box**
* 📊 **44-47% overall time savings** - Complete enterprise development cycle
* 💰 **50-60% cost reduction** - Smaller teams, faster delivery
* 📈 **Consistent quality and patterns**
* 🚀 **Ready to scale immediately**
* 🔒 **70% risk reduction** - Proven framework patterns

***

## 📦 Generated Business Modules

### 1. **Orders Module** - Complete E-Commerce Order Management

#### **Generated Capabilities:**

* **AddOrder** - Create new orders with full validation
* **AddItemToOrder** - Add products to existing orders
* **Order Management** - Complete CRUD operations
* **Order Queries** - Retrieve order information

#### **Generated Infrastructure vs Developer Code:**

**Generated Plumbing Code (Framework):**

```csharp
// Auto-generated Command Handler - Orchestration
public partial class AddOrderHandler : IAddOrderHandler
{
    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        int records = await _repoFactory.GetRepo().SaveAsync();
        await this.Fire(EventCondition, serviceBusContext);
    }
}

// Auto-generated REST API Controller
[HttpPost]
[Route("AddOrder")]
public async Task<IActionResult> AddOrder([FromBody]AddOrderDto dto)
{
    return await RunService(201, dto, _processOrdersService.AddOrder);
}
```

**Developer Writes (Business Logic):**

```csharp
// Developer adds business attributes and validation
public partial class Order : DomainModelBridge
{
    [Required]
    [StringLength(50)]
    public string CustomerId { get; set; }

    [Range(0.01, double.MaxValue)]
    public decimal TotalAmount { get; set; }

    // Developer adds custom business logic
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // Custom validation logic
        if (cmd.Dto.TotalAmount > 10000)
        {
            throw new BusinessException("Order amount exceeds limit");
        }
        
        // Framework handles the rest
        this.Convert(cmd.Dto);
        this.SetAdded(cmd.Dto.GetGeneratedId());
        return this;
    }
}

// Developer can customize AutoMapper SelectTo when needed
public class OrderMapperConfiguration : FlexMapperProfile
{
    public OrderMapperConfiguration() : base()
    {
        CreateMap<Order, GetOrdersDto>()
            .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
            .ForMember(dest => dest.StatusDisplay, opt => opt.MapFrom(src => GetStatusDisplay(src.Status)))
            .ForMember(dest => dest.DaysSinceCreated, opt => opt.MapFrom(src => (DateTime.UtcNow - src.CreatedDate).Days));
    }
}
```

### 2. **Products Module** - Product Catalog Management

#### **Generated Capabilities:**

* **AddProduct** - Create new products
* **UpdateProduct** - Modify existing products
* **Product Management** - Full lifecycle management
* **Product Queries** - Search and retrieve products

#### **Architectural Benefits:**

* **Consistent Patterns**: Same architectural structure as Orders module
* **Reusable Components**: Shared infrastructure and framework bridges
* **Type Safety**: Strongly-typed DTOs and commands
* **Validation**: Built-in input validation and error handling

### 3. **Payments Module** - Payment Processing

#### **Generated Capabilities:**

* **MakePayment** - Process payment transactions
* **PaymentConfirmationCallBack** - Handle payment confirmations
* **Payment Management** - Complete payment lifecycle
* **Payment Queries** - Retrieve payment information

#### **Enterprise Features:**

* **Event-Driven**: Payment events for downstream processing
* **Audit Trail**: Complete transaction logging
* **Error Handling**: Robust error management
* **Integration Ready**: External payment gateway integration

### 4. **Customers Module** - Customer Management

#### **Generated Capabilities:**

* **GetCustomers** - Query customer information
* **Customer Management** - Complete customer lifecycle
* **Customer Queries** - Advanced search capabilities

***

## 📋 DTO Pattern & Clean Separation Architecture

### **DTO Structure and Clean Separation**

The YourApplication solution implements a sophisticated DTO (Data Transfer Object) pattern that provides clean separation between different architectural layers, ensuring loose coupling and maintainability.

#### **DTO Hierarchy and Organization:**

```csharp
// Input DTOs - API Layer to Application Layer
YourApplication.Application/ControlContracts/YourApplication.DTOs/
├── FeatureDtos/
│   ├── Orders/
│   │   ├── Input/
│   │   │   ├── AddOrder/AddOrderDto.cs
│   │   │   └── AddItemToOrder/AddItemToOrderDto.cs
│   │   └── Output/
│   ├── Products/
│   │   ├── Input/
│   │   │   ├── AddProduct/AddProductDto.cs
│   │   │   └── UpdateProduct/UpdateProductDto.cs
│   │   └── Output/
│   └── Payments/
│       ├── Input/
│       │   └── MakePayment/MakePaymentDto.cs
│       └── Output/
└── DomainDtos/
    ├── Order/OrderDto.cs
    ├── Product/ProductDto.cs
    ├── Payment/PaymentDto.cs
    └── OrderItem/OrderItemDto.cs
```

#### **DTO Pattern Implementation:**

```csharp
// Input DTO - Clean API Contract
public partial class AddOrderDto : DtoBridge 
{
    // Auto-generated properties for API input
    // Validation attributes
    // Type safety
}

// Domain DTO - Business Entity Representation  
public partial class OrderDto : DtoBridge 
{
    // Domain model representation
    // Business logic encapsulation
    // Database-agnostic structure
}

// Output DTO - Query Results
public partial class GetCustomersDto : DtoBridge 
{
    // Optimized for read operations
    // Projection-specific properties
    // Performance-optimized structure
}
```

#### **Clean Separation Benefits:**

1. **API Layer Isolation:**
   * Input DTOs shield domain models from API changes
   * Versioning support through DTO evolution
   * API-specific validation and formatting
2. **Domain Layer Protection:**
   * Domain DTOs represent pure business concepts
   * No API or database concerns in domain
   * Business rules encapsulation
3. **Database Layer Abstraction:**
   * Domain DTOs are database-agnostic
   * ORM mapping handled separately
   * Database schema changes don't affect domain

### **Handler-to-Domain Method Architecture**

The solution follows a sophisticated architectural pattern where handlers orchestrate domain method calls, implementing several key enterprise patterns:

#### **Command Handler Pattern:**

```csharp
public partial class AddOrderHandler : IAddOrderHandler
{
    // Dependency Injection - Clean Architecture
    protected readonly ILogger<AddOrderHandler> _logger;
    protected readonly IFlexHost _flexHost;           // Domain access
    protected readonly RepoFactory _repoFactory;      // Data access
    
    // Domain model instance
    protected Order? _model;
    protected FlexAppContextBridge? _flexAppContext;  // Context

    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // 1. Context Extraction
        _flexAppContext = cmd.Dto.GetAppContext();
        
        // 2. Repository Initialization
        _repoFactory.Init(cmd.Dto);
        
        // 3. Domain Method Invocation - CORE ARCHITECTURAL PATTERN
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        
        // 4. Persistence Layer
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        int records = await _repoFactory.GetRepo().SaveAsync();
        
        // 5. Event Publishing
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

#### **Domain Method Implementation:**

```csharp
// Domain Model with Business Logic
public partial class Order : DomainModelBridge
{
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // 1. Input Validation
        Guard.AgainstNull("Order command cannot be empty", cmd);
        
        // 2. DTO to Domain Mapping
        this.Convert(cmd.Dto);
        
        // 3. Business Logic Application
        this.CreatedBy = cmd.Dto.GetAppContext()?.UserId;
        this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;
        
        // 4. Domain State Management
        this.SetAdded(cmd.Dto.GetGeneratedId());
        
        // 5. Business Rules Enforcement
        // Custom business logic can be added here
        
        return this;
    }
}
```

#### **Architectural Patterns Demonstrated:**

1. **Command Pattern:**
   * `AddOrderCommand` encapsulates request
   * Handler executes command
   * Domain model processes business logic
2. **Repository Pattern:**
   * `RepoFactory` abstracts data access
   * Generic repository interface
   * Database-agnostic operations
3. **Domain-Driven Design:**
   * Rich domain models with behavior
   * Business logic in domain layer
   * Ubiquitous language implementation
4. **CQRS (Command Query Responsibility Segregation):**
   * Commands for write operations
   * Queries for read operations
   * Separate optimization paths
5. **Event-Driven Architecture:**
   * Domain events for side effects
   * Loose coupling between modules
   * Asynchronous processing

### **AutoMapper Integration for DTO-Domain Mapping:**

```csharp
// AutoMapper Configuration
public class CoreMapperConfiguration : FlexMapperProfile
{
    public CoreMapperConfiguration() : base()
    {
        #region Input Mapping
        // DTO to Domain Model mapping
        CreateMap<AddOrderDto, Order>();
        CreateMap<AddProductDto, Product>();
        CreateMap<MakePaymentDto, Payment>();
        #endregion

        #region Output Mapping  
        // Domain Model to DTO mapping
        CreateMap<Order, OrderDto>();
        CreateMap<Product, ProductDto>();
        CreateMap<Payment, PaymentDto>();
        #endregion
    }
}
```

#### **Mapping Benefits:**

1. **Type Safety:** Compile-time mapping validation
2. **Performance:** Optimized object transformation
3. **Maintainability:** Centralized mapping configuration
4. **Flexibility:** Custom mapping rules support

### **Update Operations Pattern:**

```csharp
// Update Handler - Different Pattern for Existing Entities
public virtual async Task Execute(UpdateProductCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    _flexAppContext = cmd.Dto.GetAppContext();
    _repoFactory.Init(cmd.Dto);
    
    // 1. Entity Retrieval
    _model = _repoFactory.GetRepo().FindAll<Product>()
        .Where(m => m.Id == cmd.Dto.Id)
        .FirstOrDefault();
    
    if (_model != null)
    {
        // 2. Domain Method Invocation
        _model.UpdateProduct(cmd);
        
        // 3. Persistence
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        int records = await _repoFactory.GetRepo().SaveAsync();
        
        // 4. Event Publishing
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

### **Data Flow Architecture:**

```mermaid
graph TB
    subgraph "API Layer"
        Controller[OrdersController]
        InputDTO[AddOrderDto]
        OutputDTO[OrderDto]
    end
    
    subgraph "Application Layer"
        Command[AddOrderCommand]
        Handler[AddOrderHandler]
        Service[ProcessOrdersService]
    end
    
    subgraph "Domain Layer"
        DomainModel[Order Domain Model]
        BusinessLogic[AddOrder Method]
        DomainDTO[OrderDto]
    end
    
    subgraph "Infrastructure Layer"
        Repository[Repository Factory]
        Database[(Database)]
        MessageBus[Event Bus]
    end
    
    Controller --> InputDTO
    InputDTO --> Command
    Command --> Handler
    Handler --> DomainModel
    DomainModel --> BusinessLogic
    BusinessLogic --> DomainDTO
    Handler --> Repository
    Repository --> Database
    Handler --> MessageBus
    DomainDTO --> OutputDTO
    OutputDTO --> Controller
```

#### **Key Architectural Benefits:**

1. **Clean Separation of Concerns:**
   * Each layer has distinct responsibilities
   * DTOs provide clear boundaries
   * Domain logic isolated from infrastructure
2. **Testability:**
   * Each layer can be tested independently
   * Mock-friendly interfaces
   * Clear dependency injection
3. **Maintainability:**
   * Changes in one layer don't affect others
   * Clear data transformation points
   * Consistent patterns across modules
4. **Scalability:**
   * Each layer can be scaled independently
   * Event-driven architecture for loose coupling
   * Database-agnostic design

***

## 🗄️ Domain Model-Driven Database Migrations

### **Revolutionary Migration Strategy**

The YourApplication solution implements a groundbreaking approach where **domain models automatically generate database schemas and migrations**, eliminating the traditional manual database design process and dramatically improving developer and DevOps efficiency.

#### **Migration Architecture Overview:**

```csharp
// Domain Model Definition
public partial class Order : DomainModelBridge
{
    // Domain properties automatically become database columns
    // Business logic drives schema design
    // Framework handles all database mapping
}

// Automatic Migration Generation
public class ApplicationEFDbContext : FlexEFDbContext
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // Framework automatically configures all domain models
        // No manual DbSet definitions required
        // Automatic relationship mapping
    }
}
```

#### **Multi-Database Migration Support:**

```csharp
// SQL Server Migration Context
public class ApplicationEFDbMigrationContext : ApplicationEFDbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connectionString = _configuration.GetSection("FlexBase")["AppDbConnection"];
        optionsBuilder.UseSqlServer(connectionString);
    }
}

// MySQL Migration Context  
public class ApplicationEFDbMigrationContext : ApplicationEFDbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connectionString = _configuration.GetSection("FlexBase")["AppDbConnection"];
        optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
    }
}

// PostgreSQL Migration Context
public class ApplicationEFDbMigrationContext : ApplicationEFDbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connectionString = _configuration.GetSection("FlexBase")["AppDbConnection"];
        optionsBuilder.UseNpgsql(connectionString);
    }
}
```

### **Developer Efficiency Benefits**

#### **1. Zero Manual Database Design:**

```csharp
// Traditional Approach (Manual):
// 1. Design database schema in SQL Management Studio
// 2. Create tables manually
// 3. Define relationships
// 4. Create indexes
// 5. Write migration scripts
// 6. Test migrations
// 7. Deploy to different environments
// Time: 2-4 hours per module

// YourApplication Approach (Automatic):
// 1. Define domain model
// 2. Run migration command
// 3. Framework generates everything
// Time: 5 minutes per module
```

#### **2. Automatic Schema Generation:**

* **Tables**: Created from domain models automatically
* **Columns**: Generated from domain properties
* **Relationships**: Inferred from domain associations
* **Indexes**: Auto-generated for performance
* **Constraints**: Applied based on domain rules
* **Audit Fields**: Automatically added (CreatedBy, LastModifiedBy, etc.)

#### **3. Multi-Database Consistency:**

```bash
# Single command generates migrations for all databases
dotnet ef migrations add InitialCreate --project YourApplication.Migrations.SqlServer
dotnet ef migrations add InitialCreate --project YourApplication.Migrations.MySql  
dotnet ef migrations add InitialCreate --project YourApplication.Migrations.PostgreSql
```

### **DevOps Efficiency Benefits**

#### **1. Automated Migration Pipeline:**

```yaml
# CI/CD Pipeline Example
stages:
  - generate_migrations:
      script:
        - dotnet ef migrations add $CI_COMMIT_SHA --project YourApplication.Migrations.SqlServer
        - dotnet ef migrations add $CI_COMMIT_SHA --project YourApplication.Migrations.MySql
        - dotnet ef migrations add $CI_COMMIT_SHA --project YourApplication.Migrations.PostgreSql
      artifacts:
        paths:
          - **/Migrations/
  
  - deploy_migrations:
      script:
        - dotnet ef database update --project YourApplication.Migrations.SqlServer
        - dotnet ef database update --project YourApplication.Migrations.MySql
        - dotnet ef database update --project YourApplication.Migrations.PostgreSql
```

#### **2. Environment Consistency:**

* **Development**: Auto-generated schema matches production
* **Staging**: Identical database structure across environments
* **Production**: Zero manual intervention required
* **Multi-Tenant**: Automatic tenant database creation

#### **3. Rollback Safety:**

```csharp
// Automatic rollback support
dotnet ef database update PreviousMigration --project YourApplication.Migrations.SqlServer
dotnet ef migrations remove --project YourApplication.Migrations.SqlServer
```

### **Time and Energy Savings**

#### **Development Time Comparison:**

| Task                   | Traditional Approach | YourApplication Approach | Time Saved |
| ---------------------- | -------------------- | ------------------------ | ---------- |
| **Database Design**    | 2-4 hours            | 5 minutes                | **95%**    |
| **Migration Creation** | 1-2 hours            | 2 minutes                | **98%**    |
| **Multi-DB Setup**     | 4-6 hours            | 10 minutes               | **97%**    |
| **Schema Updates**     | 1-3 hours            | 3 minutes                | **98%**    |
| **Testing Migrations** | 2-4 hours            | 5 minutes                | **96%**    |
| **Deployment**         | 1-2 hours            | 5 minutes                | **95%**    |
| **Total per Module**   | **11-21 hours**      | **30 minutes**           | **97%**    |

#### **DevOps Benefits:**

1. **Zero Manual Database Scripts:**
   * No SQL scripts to write or maintain
   * No manual database configuration
   * No environment-specific database setup
2. **Automatic Multi-Database Support:**
   * Single domain model generates multiple database schemas
   * Consistent structure across all database types
   * No database-specific migration scripts
3. **Version Control Integration:**
   * Migrations are code-first and version controlled
   * Easy to track schema changes
   * Rollback capabilities built-in
4. **Environment Parity:**
   * Identical database structure across all environments
   * No environment-specific database issues
   * Consistent deployment process

### **Advanced Migration Features**

#### **1. Seed Data Integration:**

```csharp
// Automatic seed data generation
public partial class Product : DomainModelBridge
{
    // Domain model includes seed data
    // Automatically populated during migration
    // Test data generation
}
```

#### **2. Multi-Tenant Migration Support:**

```csharp
// Tenant-specific migrations
public class TenantMigrationContext : ApplicationTenantEFDbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connectionString = _configuration.GetSection("FlexBase")["AppDbTenantConnection"];
        optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
    }
}
```

#### **3. Custom Migration Configuration:**

```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    
    // Custom indexes
    modelBuilder.Entity<Order>()
        .HasIndex(o => o.CreatedDate)
        .HasDatabaseName("IX_Orders_CreatedDate");
    
    // Custom constraints
    modelBuilder.Entity<Product>()
        .HasCheckConstraint("CK_Product_Price", "Price > 0");
}
```

### **Real-World Impact**

#### **For Development Teams:**

* **Focus on Business Logic**: Developers focus on domain models, not database schemas
* **Faster Iterations**: Schema changes take minutes, not hours
* **Reduced Errors**: Framework prevents common database design mistakes
* **Consistent Patterns**: All modules follow identical database patterns

#### **For DevOps Teams:**

* **Simplified Deployments**: No manual database configuration
* **Environment Consistency**: Identical databases across all environments
* **Automated Pipelines**: Database migrations integrated into CI/CD
* **Reduced Support**: Fewer database-related issues and tickets

#### **For Business:**

* **Faster Time-to-Market**: Database setup no longer a bottleneck
* **Lower Costs**: Reduced development and maintenance time
* **Higher Quality**: Consistent, tested database schemas
* **Scalability**: Easy to add new modules and features

### **Migration Command Examples:**

```bash
# Generate new migration
dotnet ef migrations add AddOrderModule --project YourApplication.Migrations.SqlServer

# Update database
dotnet ef database update --project YourApplication.Migrations.SqlServer

# Generate script for manual deployment
dotnet ef migrations script --project YourApplication.Migrations.SqlServer

# Remove last migration
dotnet ef migrations remove --project YourApplication.Migrations.SqlServer

# Generate for specific environment
dotnet ef migrations add ProductionRelease --project YourApplication.Migrations.SqlServer --environment Production
```

***

## 🏗️ Architectural Benefits Demonstrated

### 1. **Rapid Development Acceleration**

#### **Code Generation Efficiency:**

* **90% Less Boilerplate**: Framework generates complete CRUD operations
* **Consistent Patterns**: Every module follows identical architectural patterns
* **Zero Configuration**: Auto-generated dependency injection and routing
* **Instant API**: REST endpoints created automatically

#### **Development Time Comparison:**

```
Traditional Development: 2-3 days per module
YourApplication Generated: 30 minutes per module
Time Savings: 95% reduction in development time
```

### 2. **Enterprise-Grade Architecture Out-of-the-Box**

#### **Clean Architecture Implementation:**

```csharp
// Each module automatically implements:
├── Domain Layer (Business Logic)
│   ├── Domain Models with behavior
│   ├── Business rules and validation
│   └── Domain events
├── Application Layer (Use Cases)
│   ├── Command Handlers (CQRS)
│   ├── Query Handlers (CQRS)
│   └── Application Services
├── Infrastructure Layer
│   ├── Repository Pattern
│   ├── Message Bus Integration
│   └── Database Abstraction
└── Presentation Layer
    ├── REST API Controllers
    ├── DTOs and Validation
    └── Error Handling
```

#### **CQRS Pattern Implementation:**

* **Commands**: `AddOrderCommand`, `AddProductCommand`, `MakePaymentCommand`
* **Queries**: `GetCustomers`, `GetOrders`, `GetProducts`
* **Separation**: Clear distinction between read and write operations
* **Scalability**: Independent scaling of read/write workloads

### 3. **Framework Integration Benefits**

#### **Sumeru.Flex Framework Integration:**

```csharp
// Automatic Framework Bridge Implementation
public partial class OrdersController : FlexControllerBridge<OrdersController>
{
    // Auto-generated base functionality
    // Built-in error handling
    // Automatic logging
    // Request/Response transformation
}

// Domain Model Integration
public partial class Order : DomainModelBridge
{
    // Built-in audit fields
    // Automatic ID generation
    // Row state management
    // Validation framework
}
```

#### **Built-in Enterprise Features:**

* **Logging**: Structured logging with correlation IDs
* **Validation**: FluentValidation integration
* **Mapping**: AutoMapper configuration
* **Auditing**: Automatic audit trail creation
* **Security**: Built-in security patterns

### 4. **Database and Messaging Integration**

#### **Multi-Database Support:**

```csharp
// Automatic Repository Factory
_repoFactory.Init(cmd.Dto);
_repoFactory.GetRepo().InsertOrUpdate(_model);
await _repoFactory.GetRepo().SaveAsync();

// Supported Databases:
// - SQL Server
// - MySQL  
// - PostgreSQL
// - Multi-tenant configurations
```

#### **Message Bus Integration:**

```csharp
// Event-Driven Architecture
await this.Fire(EventCondition, serviceBusContext);

// Supported Message Buses:
// - RabbitMQ
// - Azure Service Bus
// - SQL Server Transport
// - Learning Transport (Development)
```

### 5. **Type Safety and Developer Experience**

#### **Strongly-Typed Contracts:**

```csharp
// Auto-generated DTOs
public partial class AddOrderDto : DtoBridge { }
public partial class OrderDto : DtoBridge { }

// Auto-generated Commands
public class AddOrderCommand : FlexCommandBridge<AddOrderDto, FlexAppContextBridge> { }

// Auto-generated Handlers
public partial class AddOrderHandler : IAddOrderHandler { }
```

#### **IntelliSense and Compile-Time Safety:**

* **Full IntelliSense**: Complete code completion
* **Compile-Time Validation**: Catch errors before runtime
* **Refactoring Safety**: IDE refactoring works across all layers
* **Type Consistency**: Same types across all layers

### 6. **Scalability and Performance**

#### **Horizontal Scaling Ready:**

* **Stateless Design**: All handlers are stateless
* **Load Balancing**: Built-in support for multiple instances
* **Database Sharding**: Multi-tenant database support
* **Message Queuing**: Asynchronous processing

#### **Performance Optimizations:**

* **Repository Pattern**: Optimized data access
* **Connection Pooling**: Automatic connection management
* **Caching Ready**: Framework prepared for caching implementation
* **Async/Await**: Full async support throughout

***

## 🎯 Business Value Demonstration

### 1. **Time-to-Market Acceleration**

#### **Module Creation Speed:**

```
Complete Business Module (Orders/Products/Payments):
├── Domain Models: Auto-generated
├── Command Handlers: Auto-generated  
├── Query Handlers: Auto-generated
├── REST Controllers: Auto-generated
├── DTOs and Validation: Auto-generated
├── Database Integration: Auto-generated
├── Message Bus Integration: Auto-generated
└── Testing Infrastructure: Auto-generated

Total Development Time: 30 minutes
Traditional Development Time: 2-3 weeks
```

### 2. **Consistency and Quality**

#### **Architectural Consistency:**

* **Identical Patterns**: Every module follows the same structure
* **Best Practices**: Enterprise patterns built-in
* **Code Quality**: Consistent, readable, maintainable code
* **Documentation**: Auto-generated XML documentation

#### **Error Reduction:**

* **Type Safety**: Compile-time error detection
* **Validation**: Built-in input validation
* **Error Handling**: Consistent error management
* **Logging**: Comprehensive logging and monitoring

### 3. **Maintainability and Extensibility**

#### **Easy Maintenance:**

* **Clear Separation**: Well-defined layer boundaries
* **Single Responsibility**: Each class has one purpose
* **Dependency Injection**: Easy to test and modify
* **Configuration**: Centralized configuration management

#### **Simple Extensions:**

```csharp
// Adding new business logic is straightforward
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // Existing generated code...
    
    // Add custom business logic
    if (cmd.Dto.TotalAmount > 1000)
    {
        this.ApplyDiscount(0.1); // 10% discount for large orders
    }
    
    return this;
}
```

### 4. **Team Productivity**

#### **Developer Onboarding:**

* **Familiar Patterns**: Standard enterprise patterns
* **Self-Documenting**: Clear code structure
* **Consistent Style**: Uniform coding standards
* **Quick Learning**: New developers productive immediately

#### **Parallel Development:**

* **Module Independence**: Teams can work on different modules
* **Clear Interfaces**: Well-defined module boundaries
* **Shared Infrastructure**: Common framework and utilities
* **Version Control**: Clean, organized code structure

***

## 🔧 Technical Implementation Highlights

### 1. **Auto-Generated Infrastructure**

#### **Complete Module Structure:**

```
OrdersModule/
├── Domain/
│   ├── Order.cs (Domain Model)
│   ├── AddOrder.cs (Business Logic)
│   └── Order_SeedData.cs (Test Data)
├── Application/
│   ├── AddOrderHandler.cs (Command Handler)
│   ├── AddItemToOrderHandler.cs (Command Handler)
│   └── ProcessOrdersService.cs (Application Service)
├── Presentation/
│   ├── OrdersController.cs (REST API)
│   ├── AddOrderDto.cs (Input DTO)
│   └── OrderDto.cs (Output DTO)
├── Infrastructure/
│   ├── OrderMapperConfiguration.cs (AutoMapper)
│   └── Repository Integration (Database)
└── Messaging/
    ├── AddOrderCommand.cs (Command)
    └── Event Integration (NServiceBus)
```

### 2. **Framework Integration Benefits**

#### **Sumeru.Flex Framework Features:**

* **FlexControllerBridge**: Automatic controller base functionality
* **FlexCommandBridge**: Command pattern implementation
* **FlexQueryBridge**: Query pattern implementation
* **DomainModelBridge**: Domain model base functionality
* **DtoBridge**: DTO base functionality

#### **Built-in Enterprise Features:**

* **Audit Trail**: Automatic CreatedBy, LastModifiedBy tracking
* **Row State Management**: Added, Modified, Deleted state tracking
* **ID Generation**: Automatic unique ID generation
* **Context Management**: Request context and user information
* **Validation Framework**: Built-in validation patterns

### 3. **Database and Messaging Integration**

#### **Repository Pattern:**

```csharp
// Automatic repository management
_repoFactory.Init(cmd.Dto);
_repoFactory.GetRepo().InsertOrUpdate(_model);
int records = await _repoFactory.GetRepo().SaveAsync();
```

#### **Message Bus Integration:**

```csharp
// Event-driven architecture
await this.Fire(EventCondition, serviceBusContext);
```

***

## 📊 Performance and Scalability Benefits

### 1. **Performance Optimizations**

#### **Built-in Performance Features:**

* **Async/Await**: Full asynchronous programming support
* **Connection Pooling**: Automatic database connection management
* **Repository Pattern**: Optimized data access patterns
* **Lazy Loading**: On-demand data loading
* **Caching Ready**: Framework prepared for caching implementation

### 2. **Scalability Features**

#### **Horizontal Scaling:**

* **Stateless Design**: All components are stateless
* **Load Balancing**: Built-in support for multiple instances
* **Database Sharding**: Multi-tenant database support
* **Message Queuing**: Asynchronous processing and decoupling

#### **Microservices Ready:**

* **Independent Modules**: Each module can be deployed separately
* **Clear Boundaries**: Well-defined module interfaces
* **Event-Driven**: Loose coupling through events
* **API Gateway Ready**: RESTful API design

***

## 🎯 Conclusion

The YourApplication solution demonstrates a powerful approach to enterprise application development that:

### **Accelerates Development:**

* **95% reduction** in development time for new modules
* **Consistent patterns** across all business modules
* **Zero configuration** for basic functionality
* **Instant API** generation

### **Ensures Quality:**

* **Enterprise-grade architecture** out-of-the-box
* **Type safety** and compile-time validation
* **Built-in best practices** and patterns
* **Comprehensive error handling** and logging

### **Enables Scalability:**

* **Horizontal scaling** ready
* **Microservices architecture** support
* **Event-driven design** for loose coupling
* **Multi-database** and messaging support

### **Improves Maintainability:**

* **Clear separation of concerns**
* **Consistent code structure**
* **Easy testing** and debugging
* **Simple extensions** and modifications

This framework provides a solid foundation for building enterprise applications that are **fast to develop**, **easy to maintain**, and **ready to scale** - enabling teams to focus on business logic rather than infrastructure concerns.

***

*This demonstration showcases the actual generated capabilities of the Application created with Flexbase and highlights how the architectural patterns and framework integration provide significant business value through accelerated development, consistent quality, and enterprise-grade scalability.*


# Domain-Driven Design

## Application created with Flexbase Domain-Driven Design Patterns & Best Practices

### 🏗️ Domain-Driven Design Implementation

The Application created with Flexbase demonstrates sophisticated Domain-Driven Design (DDD) patterns through its Handler-Domain-Domain Method architecture, showcasing enterprise-grade best practices and clean separation of concerns.

***

### 🎯 Core DDD Architecture

#### **Three-Layer Domain Pattern**

```
┌─────────────────────────────────────┐
│ Handler Layer (Application)         │ ← Orchestrates business operations
├─────────────────────────────────────┤
│ Domain Layer (Business Logic)       │ ← Contains pure business logic
├─────────────────────────────────────┤
│ Infrastructure Layer (Data)         │ ← Handles persistence and external concerns
└─────────────────────────────────────┘
```

#### **Key DDD Principles Implemented**

* **Rich Domain Models** - Business logic encapsulated in domain entities
* **Ubiquitous Language** - Domain terms used consistently across all layers
* **Domain Entities** - Business objects that manage their own state and invariants
* **Domain Events** - Business events published for side effects
* **Repository Pattern** - Clean data access abstraction

***

### 🔧 Handler Layer - Application Orchestration

#### **Handler Responsibilities**

The Handler layer acts as the **Application Service** in DDD, orchestrating business operations without containing business logic.

```csharp
// Handler Pattern - Application Service
public partial class AddOrderHandler : IAddOrderHandler
{
    // Dependencies injected - Clean Architecture
    protected readonly ILogger<AddOrderHandler> _logger;
    protected readonly IFlexHost _flexHost;           // Domain access
    protected readonly RepoFactory _repoFactory;      // Data access
    
    // Domain model instance
    protected Order? _model;
    protected FlexAppContextBridge? _flexAppContext;  // Context

    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // 1. Context Extraction - DDD Context Management
        _flexAppContext = cmd.Dto.GetAppContext();
        
        // 2. Repository Initialization - Infrastructure Setup
        _repoFactory.Init(cmd.Dto);
        
        // 3. Domain Method Invocation - CORE DDD PATTERN
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        
        // 4. Persistence Layer - Infrastructure Concern
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        int records = await _repoFactory.GetRepo().SaveAsync();
        
        // 5. Event Publishing - DDD Event-Driven Architecture
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

#### **Handler Best Practices Demonstrated**

**1. Single Responsibility Principle**

* **Only orchestrates** - No business logic in handlers
* **Manages dependencies** - Coordinates between domain and infrastructure
* **Handles transactions** - Ensures data consistency
* **Publishes events** - Triggers side effects

**2. Dependency Inversion Principle**

* **Depends on abstractions** - Uses interfaces, not concrete implementations
* **Domain-first approach** - Handler calls domain, not vice versa
* **Infrastructure abstraction** - Repository pattern for data access

**3. Command Pattern Implementation**

* **Encapsulates requests** - Commands contain all necessary data
* **Type safety** - Strongly-typed command parameters
* **Validation** - Command-level validation before domain processing

***

### 🏛️ Domain Layer - Business Logic Encapsulation

#### **Domain Model Structure**

Domain models are **rich business objects** that encapsulate business logic and maintain invariants.

```csharp
// Domain Model - Rich Business Object
public partial class Order : DomainModelBridge
{
    // Domain Properties - Business State
    public Guid Id { get; set; }
    public string CustomerId { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; }
    public DateTime CreatedDate { get; set; }
    
    // Navigation Properties - Domain Relationships
    public virtual Customer? Customer { get; set; }
    public virtual ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>();
    
    // Audit Properties - Cross-cutting Concerns
    public string? CreatedBy { get; set; }
    public string? LastModifiedBy { get; set; }
    public DateTime? LastModifiedDate { get; set; }
}
```

#### **Domain Model Best Practices**

**1. Rich Domain Models**

* **Behavior over data** - Methods contain business logic
* **Encapsulation** - Internal state protected from external modification
* **Invariants** - Business rules enforced within the domain

**2. Domain Entity Pattern**

* **Single responsibility** - Each domain entity manages its own business logic
* **Consistency boundaries** - Ensures data integrity within the domain object
* **State management** - Domain objects control their own state transitions

**3. Value Objects and Entities**

* **Entities** - Have identity (Order, Customer)
* **Value Objects** - No identity, immutable (Money, Address)
* **Clear boundaries** - Well-defined domain concepts

***

### ⚙️ Domain Methods - Business Logic Implementation

#### **Domain Method Pattern**

Domain methods contain the **core business logic** and are the heart of DDD implementation.

```csharp
// Domain Method - Business Logic Implementation
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // 1. Input Validation - Domain Invariants
    Guard.AgainstNull("Order command cannot be empty", cmd);
    
    // 2. DTO to Domain Mapping - Data Transformation
    this.Convert(cmd.Dto);
    
    // 3. Business Logic Application - Core DDD
    this.CreatedBy = cmd.Dto.GetAppContext()?.UserId;
    this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;
    
    // 4. Domain State Management - Entity State
    this.SetAdded(cmd.Dto.GetGeneratedId());
    
    // 5. Business Rules Enforcement - Domain Invariants
    this.ValidateOrderTotal();
    this.ApplyBusinessRules();
    
    // 6. Domain Event Publishing - Event-Driven DDD
    this.RaiseEvent(new OrderCreatedEvent
    {
        OrderId = this.Id,
        CustomerId = this.CustomerId,
        TotalAmount = this.TotalAmount,
        CreatedAt = DateTime.UtcNow
    });
    
    return this;
}
```

#### **Domain Method Best Practices**

**1. Business Logic Encapsulation**

* **Pure business logic** - No infrastructure concerns
* **Domain invariants** - Business rules enforced
* **Validation** - Domain-level validation
* **State management** - Domain entity state changes

**2. Command Pattern Integration**

* **Command objects** - Encapsulate all necessary data
* **Type safety** - Strongly-typed parameters
* **Context preservation** - User and request context maintained

**3. Event-Driven Architecture**

* **Domain events** - Business events published
* **Side effects** - Triggered by domain events
* **Loose coupling** - Modules communicate through events

***

### 🔄 Complete DDD Flow Example

#### **AddOrder Operation - DDD in Action**

```mermaid
graph TB
    subgraph "Handler Layer (Application)"
        Handler[AddOrderHandler.Execute]
        Context[Extract Context]
        Repo[Initialize Repository]
        Persist[Persist Changes]
        Event[Publish Events]
    end
    
    subgraph "Domain Layer (Business Logic)"
        Domain[Order Domain Model]
        Method[AddOrder Method]
        Rules[Business Rules]
        Validation[Domain Validation]
        State[State Management]
    end
    
    subgraph "Infrastructure Layer (Data)"
        Repository[Repository Factory]
        Database[(Database)]
        MessageBus[Event Bus]
    end
    
    Handler --> Context
    Context --> Repo
    Repo --> Domain
    Domain --> Method
    Method --> Rules
    Method --> Validation
    Method --> State
    Method --> Event
    Handler --> Persist
    Persist --> Repository
    Repository --> Database
    Event --> MessageBus
```

#### **Step-by-Step DDD Implementation**

**Step 1: Handler Orchestration**

```csharp
// Handler coordinates the operation
public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    // Extract application context
    _flexAppContext = cmd.Dto.GetAppContext();
    
    // Initialize infrastructure
    _repoFactory.Init(cmd.Dto);
    
    // Delegate to domain - CORE DDD PRINCIPLE
    _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
    
    // Handle infrastructure concerns
    _repoFactory.GetRepo().InsertOrUpdate(_model);
    await _repoFactory.GetRepo().SaveAsync();
    
    // Publish domain events
    await this.Fire(EventCondition, serviceBusContext);
}
```

**Step 2: Domain Business Logic**

```csharp
// Domain contains the business logic
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // Business validation
    Guard.AgainstNull("Order command cannot be empty", cmd);
    
    // Data transformation
    this.Convert(cmd.Dto);
    
    // Business rules application
    this.CreatedBy = cmd.Dto.GetAppContext()?.UserId;
    this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;
    this.SetAdded(cmd.Dto.GetGeneratedId());
    
    // Domain event publishing
    this.RaiseEvent(new OrderCreatedEvent { ... });
    
    return this;
}
```

**Step 3: Infrastructure Handling**

```csharp
// Infrastructure handles data persistence
_repoFactory.GetRepo().InsertOrUpdate(_model);
int records = await _repoFactory.GetRepo().SaveAsync();

// Event publishing for side effects
await this.Fire(EventCondition, serviceBusContext);
```

***

### 🎯 DDD Best Practices Demonstrated

#### **1. Separation of Concerns**

* **Handler Layer**: Orchestration, transaction management, event publishing
* **Domain Layer**: Business logic, rules, invariants, domain events
* **Infrastructure Layer**: Data persistence, external service integration

#### **2. Dependency Inversion**

* **High-level modules** (Handlers) don't depend on low-level modules (Database)
* **Domain layer** is independent of infrastructure
* **Abstractions** define contracts between layers

#### **3. Single Responsibility Principle**

* **Handlers**: Only orchestrate operations
* **Domain Models**: Only contain business logic
* **Repositories**: Only handle data access

#### **4. Open/Closed Principle**

* **Open for extension**: New domain methods, handlers, events
* **Closed for modification**: Existing domain logic doesn't change
* **Plugin architecture**: Easy to add new business capabilities

#### **5. Interface Segregation**

* **Focused interfaces**: Each interface serves specific purpose
* **Client-specific contracts**: Handlers only depend on what they need
* **Loose coupling**: Changes in one interface don't affect others

***

### 🚀 Advanced DDD Patterns

#### **1. Rich Domain Entity Pattern**

```csharp
// Order is a Rich Domain Entity
public partial class Order : DomainModelBridge
{
    // Manages related entities as part of the domain object
    public virtual ICollection<OrderItem> OrderItems { get; set; }
    
    // Business method that maintains domain consistency
    public virtual Order AddItemToOrder(AddItemToOrderCommand cmd)
    {
        // Business logic to add item
        // Maintains domain invariants
        // Publishes domain events
        return this;
    }
}
```

#### **2. Domain Events Pattern**

```csharp
// Domain events for side effects
public class OrderCreatedEvent : IFlexEvent
{
    public Guid OrderId { get; set; }
    public string CustomerId { get; set; }
    public decimal TotalAmount { get; set; }
    public DateTime CreatedAt { get; set; }
}

// Event publishing in domain method
this.RaiseEvent(new OrderCreatedEvent
{
    OrderId = this.Id,
    CustomerId = this.CustomerId,
    TotalAmount = this.TotalAmount,
    CreatedAt = DateTime.UtcNow
});
```

#### **3. Repository Pattern**

```csharp
// Repository abstraction for data access
_repoFactory.GetRepo().InsertOrUpdate(_model);
int records = await _repoFactory.GetRepo().SaveAsync();

// Domain doesn't know about database specifics
// Infrastructure handles the implementation details
```

#### **4. Command Pattern**

```csharp
// Commands encapsulate business operations
public class AddOrderCommand : FlexCommandBridge<AddOrderDto, FlexAppContextBridge>
{
    public AddOrderDto Dto { get; set; }
    public FlexAppContextBridge Context { get; set; }
    public string CorrelationId { get; set; }
    public DateTime Timestamp { get; set; }
}
```

***

### 📊 DDD Benefits Achieved

#### **1. Maintainability**

* **Clear boundaries** - Each layer has distinct responsibilities
* **Business logic isolation** - Domain logic is separate from infrastructure
* **Easy testing** - Each layer can be tested independently
* **Consistent patterns** - Same structure across all modules

#### **2. Scalability**

* **Horizontal scaling** - Stateless handlers can be scaled independently
* **Event-driven** - Loose coupling through domain events
* **Microservices ready** - Clear boundaries enable service extraction

#### **3. Business Alignment**

* **Ubiquitous language** - Domain terms used consistently
* **Business logic centralization** - All business rules in one place
* **Domain expert collaboration** - Clear domain model for business discussions

#### **4. Quality Assurance**

* **Type safety** - Compile-time validation throughout
* **Invariant enforcement** - Business rules enforced at domain level
* **Error prevention** - Framework prevents common mistakes
* **Consistent behavior** - Same patterns across all operations

***

### 🎯 Key Takeaways

#### **DDD Implementation Success**

The YourApplication solution demonstrates **enterprise-grade DDD implementation** with:

1. **Clean Architecture** - Clear separation between layers
2. **Rich Domain Models** - Business logic properly encapsulated in domain entities
3. **Event-Driven Design** - Loose coupling through domain events
4. **Repository Pattern** - Clean data access abstraction
5. **Command Pattern** - Encapsulated business operations

#### **Business Value Delivered**

* **Maintainable Code** - Clear structure and separation of concerns
* **Testable Architecture** - Each layer can be tested independently
* **Scalable Design** - Ready for horizontal scaling and microservices
* **Business Alignment** - Domain model reflects business concepts
* **Quality Assurance** - Consistent patterns and error prevention

***

*This document showcases how the YourApplication solution implements Domain-Driven Design principles through its Handler-Domain-Domain Method architecture, delivering enterprise-grade maintainability, scalability, and business alignment.*


# Post Production Impact

## 🚀 Post-Production Value Proposition

The Applications Built With Flexbase framework delivers **exceptional post-production value** through consistent patterns, generated infrastructure, and enterprise-grade architecture that significantly reduces maintenance overhead, accelerates feature delivery, and minimizes operational risks.

***

## 📊 Post-Production Impact Analysis

### **Traditional vs Applications Built With Flexbase Post-Production Comparison**

```
Post-Production Phase (12-24 months):
├── Maintenance & Bug Fixes
├── Feature Extensions
├── Performance Optimizations
├── Security Updates
├── Infrastructure Changes
├── Team Scaling
└── Knowledge Transfer
```

***

## 🔧 Maintenance & Bug Fixes

### **Traditional Application Maintenance Challenges**

#### **Code Complexity Issues:**

* **Inconsistent Patterns**: Each module implemented differently
* **Custom Error Handling**: Unique error handling per module
* **Manual Database Changes**: Custom migration scripts
* **API Versioning**: Manual versioning and backward compatibility
* **Logging Inconsistencies**: Different logging approaches across modules

#### **Maintenance Effort (Traditional):**

```
Monthly Maintenance Tasks:
├── Bug Investigation: 2-3 days
├── Code Analysis: 1-2 days
├── Fix Implementation: 2-4 days
├── Testing: 1-2 days
├── Documentation Update: 0.5-1 day
├── Deployment: 0.5-1 day
└── Total: 7-13 days per month
```

### **Applications Built With Flexbase Maintenance Benefits**

#### **Consistent Architecture Advantages:**

* **Predictable Patterns**: Same structure across all modules
* **Standardized Error Handling**: Framework-managed error responses
* **Auto-Generated Migrations**: Database changes handled automatically
* **Consistent API Patterns**: Uniform API behavior and versioning
* **Centralized Logging**: Structured logging with correlation IDs

#### **Maintenance Effort (Applications Built With Flexbase):**

```
Monthly Maintenance Tasks:
├── Bug Investigation: 0.5-1 day (consistent patterns)
├── Code Analysis: 0.5 day (familiar structure)
├── Fix Implementation: 1-2 days (framework handles complexity)
├── Testing: 0.5-1 day (pre-tested patterns)
├── Documentation Update: 0 days (auto-generated)
├── Deployment: 0.5 day (standardized process)
└── Total: 3-5 days per month

Time Savings: 60-70% reduction in maintenance effort
```

***

## 🚀 Feature Extensions & New Development

### **Traditional Extension Challenges**

#### **Integration Complexity:**

* **Custom Integration**: Each new feature requires custom integration
* **API Compatibility**: Manual API versioning and backward compatibility
* **Database Schema Changes**: Custom migration scripts and rollback plans
* **Message Bus Integration**: Manual event handling and routing
* **Security Integration**: Custom authentication and authorization

#### **Extension Effort (Traditional):**

```
New Feature Development (Post-Production):
├── Requirements Analysis: 1-2 days
├── Architecture Design: 1-2 days
├── Database Schema Changes: 1-2 days
├── API Development: 2-3 days
├── Integration with Existing Modules: 2-4 days
├── Message Bus Integration: 1-2 days
├── Security Implementation: 1-2 days
├── Testing: 2-3 days
├── Documentation: 1-2 days
├── Deployment: 1-2 days
└── Total: 13-24 days per feature
```

### **Applications Built With Flexbase Extension Benefits**

#### **Framework Integration Advantages:**

* **Consistent Integration**: New features follow same patterns
* **Auto-Generated APIs**: New endpoints created automatically
* **Automatic Schema Management**: Database changes handled by framework
* **Built-in Message Bus**: Event handling integrated automatically
* **Security by Default**: Authentication and authorization built-in

#### **Extension Effort (Applications Built With Flexbase):**

```
New Feature Development (Post-Production):
├── Requirements Analysis: 1-2 days (same)
├── Domain Model Definition: 0.5 day (attributes only)
├── Code Generation: 0.5 day (30 minutes)
├── Custom Business Logic: 1-2 days (validation rules)
├── Integration Testing: 1-2 days (framework handles integration)
├── Documentation: 0 days (auto-generated)
├── Deployment: 0.5 day (standardized)
└── Total: 4.5-7 days per feature

Time Savings: 65-70% reduction in extension effort
```

***

## ⚡ Performance Optimizations

### **Traditional Performance Challenges**

#### **Performance Issues:**

* **Inconsistent Query Patterns**: Different query approaches per module
* **Manual Caching**: Custom caching implementation per feature
* **Database Optimization**: Manual query optimization and indexing
* **API Performance**: Custom performance tuning per endpoint
* **Memory Management**: Custom memory optimization per module

#### **Performance Optimization Effort (Traditional):**

```
Performance Optimization Cycle:
├── Performance Analysis: 2-3 days
├── Query Optimization: 2-4 days
├── Caching Implementation: 2-3 days
├── Database Tuning: 1-2 days
├── API Optimization: 1-2 days
├── Testing & Validation: 2-3 days
└── Total: 10-17 days per optimization cycle
```

### **Applications Built With Flexbase Performance Benefits**

#### **Framework Performance Advantages:**

* **Optimized Query Patterns**: AutoMapper SelectTo with database-level projections
* **Built-in Caching**: Framework-managed caching strategies
* **Database Optimization**: Automatic indexing and query optimization
* **Consistent API Performance**: Standardized performance patterns
* **Memory Management**: Framework-managed resource allocation

#### **Performance Optimization Effort (Applications Built With Flexbase):**

```
Performance Optimization Cycle:
├── Performance Analysis: 1 day (framework metrics)
├── Configuration Tuning: 1-2 days (framework settings)
├── Custom Optimization: 1-2 days (business-specific)
├── Testing & Validation: 1-2 days (framework testing)
└── Total: 4-7 days per optimization cycle

Time Savings: 60-65% reduction in optimization effort
```

***

## 🔒 Security Updates & Compliance

### **Traditional Security Challenges**

#### **Security Maintenance Issues:**

* **Manual Security Updates**: Custom security implementation per module
* **Vulnerability Patching**: Manual patching across different implementations
* **Compliance Auditing**: Custom audit trails per module
* **Access Control**: Manual role-based access control implementation
* **Data Encryption**: Custom encryption per module

#### **Security Update Effort (Traditional):**

```
Security Update Cycle:
├── Vulnerability Assessment: 1-2 days
├── Security Patch Implementation: 2-4 days
├── Access Control Updates: 1-2 days
├── Audit Trail Updates: 1-2 days
├── Compliance Validation: 1-2 days
├── Security Testing: 2-3 days
└── Total: 8-15 days per security cycle
```

### **Applications Built With Flexbase Security Benefits**

#### **Framework Security Advantages:**

* **Centralized Security**: Framework-managed security policies
* **Automatic Updates**: Security patches applied framework-wide
* **Built-in Audit Trails**: Automatic audit logging
* **Role-Based Access Control**: Integrated security patterns
* **Data Protection**: Framework-managed encryption

#### **Security Update Effort (Applications Built With Flexbase):**

```
Security Update Cycle:
├── Framework Security Update: 0.5 day (automatic)
├── Configuration Update: 0.5-1 day (framework settings)
├── Custom Security Rules: 1-2 days (business-specific)
├── Compliance Validation: 0.5-1 day (framework compliance)
└── Total: 2.5-4.5 days per security cycle

Time Savings: 70-75% reduction in security effort
```

***

## 🚀 Deployment & DevOps

### **Traditional Deployment Challenges**

#### **Deployment Complexity:**

* **Custom Deployment Scripts**: Unique deployment per module
* **Environment Configuration**: Manual configuration per environment
* **Database Migration**: Custom migration scripts and rollback plans
* **Service Dependencies**: Manual dependency management
* **Rollback Procedures**: Custom rollback implementation

#### **Deployment Effort (Traditional):**

```
Deployment Cycle:
├── Pre-deployment Testing: 1-2 days
├── Environment Preparation: 1-2 days
├── Database Migration: 1-2 days
├── Application Deployment: 1-2 days
├── Integration Testing: 1-2 days
├── Rollback Preparation: 1 day
└── Total: 6-11 days per deployment
```

### **Applications Built With Flexbase Deployment Benefits**

#### **Framework Deployment Advantages:**

* **Standardized Deployment**: Consistent deployment process
* **Auto-Generated Migrations**: Database changes handled automatically
* **Environment Configuration**: Framework-managed configuration
* **Built-in Rollback**: Automatic rollback capabilities
* **Health Checks**: Framework-managed health monitoring

#### **Deployment Effort (Applications Built With Flexbase):**

```
Deployment Cycle:
├── Pre-deployment Testing: 0.5 day (framework testing)
├── Environment Preparation: 0.5 day (standardized)
├── Database Migration: 0.5 day (automatic)
├── Application Deployment: 0.5 day (standardized)
├── Integration Testing: 0.5 day (framework validation)
└── Total: 2.5 days per deployment

Time Savings: 75-80% reduction in deployment effort
```

***

## 👥 Team Scaling & Knowledge Transfer

### **Traditional Team Scaling Challenges**

#### **Knowledge Transfer Issues:**

* **Custom Code Learning**: Each module requires unique learning
* **Inconsistent Patterns**: Different approaches across modules
* **Documentation Gaps**: Manual documentation maintenance
* **Onboarding Time**: 2-4 weeks per new developer
* **Knowledge Silos**: Module-specific expertise required

#### **Team Scaling Effort (Traditional):**

```
New Developer Onboarding:
├── Code Review: 1-2 days
├── Architecture Understanding: 3-5 days
├── Module-Specific Learning: 5-10 days
├── Integration Understanding: 2-3 days
├── Testing Procedures: 1-2 days
└── Total: 12-22 days per developer
```

### **Applications Built With Flexbase Team Scaling Benefits**

#### **Framework Learning Advantages:**

* **Consistent Patterns**: Same structure across all modules
* **Auto-Generated Documentation**: Up-to-date documentation
* **Standardized Testing**: Framework-managed testing procedures
* **Reduced Learning Curve**: Familiar patterns across modules
* **Centralized Knowledge**: Framework documentation and examples

#### **Team Scaling Effort (Applications Built With Flexbase):**

```
New Developer Onboarding:
├── Framework Learning: 2-3 days
├── Pattern Understanding: 1-2 days
├── Business Logic Focus: 2-3 days
├── Testing Procedures: 0.5 day (standardized)
└── Total: 5.5-8.5 days per developer

Time Savings: 55-65% reduction in onboarding effort
```

***

## 📈 Post-Production ROI Analysis

### **12-Month Post-Production Impact**

```
Traditional Application (12 months):
├── Maintenance: 84-156 days
├── Feature Extensions: 130-240 days (5-10 features)
├── Performance Optimization: 20-34 days (2 cycles)
├── Security Updates: 32-60 days (4 cycles)
├── Deployments: 36-66 days (6 deployments)
├── Team Scaling: 24-44 days (2 new developers)
└── Total: 326-600 days

Applications Built With Flexbase Application (12 months):
├── Maintenance: 36-60 days
├── Feature Extensions: 45-70 days (5-10 features)
├── Performance Optimization: 8-14 days (2 cycles)
├── Security Updates: 10-18 days (4 cycles)
├── Deployments: 15 days (6 deployments)
├── Team Scaling: 11-17 days (2 new developers)
└── Total: 125-194 days

Total Savings: 201-406 days (6-13 months)
Cost Savings: 60-70% reduction in post-production costs
```

### **24-Month Post-Production Impact**

```
Traditional Application (24 months):
├── Total Effort: 652-1200 days
├── Team Size: 8-12 developers
├── Maintenance Cost: $1.5-3 million
├── Feature Development Cost: $2-4 million
└── Total Cost: $3.5-7 million

Applications Built With Flexbase Application (24 months):
├── Total Effort: 250-388 days
├── Team Size: 4-6 developers
├── Maintenance Cost: $600K-1.2 million
├── Feature Development Cost: $800K-1.5 million
└── Total Cost: $1.4-2.7 million

Total Savings: 402-812 days (13-27 months)
Cost Savings: $2.1-4.3 million (60-70% reduction)
```

***

## 🎯 Key Post-Production Benefits

### **1. Operational Excellence**

* **60-70% Reduction** in maintenance effort
* **65-70% Reduction** in feature extension time
* **75-80% Reduction** in deployment effort
* **70-75% Reduction** in security update time

### **2. Team Productivity**

* **55-65% Reduction** in developer onboarding time
* **50% Smaller Teams** required for same output
* **Consistent Knowledge** across all team members
* **Reduced Knowledge Silos** and dependencies

### **3. Quality & Reliability**

* **Consistent Architecture** reduces bugs and issues
* **Pre-tested Framework** components reduce testing time
* **Standardized Patterns** improve code quality
* **Built-in Monitoring** and health checks

### **4. Business Agility**

* **Faster Feature Delivery** (65-70% faster)
* **Rapid Team Scaling** (55-65% faster onboarding)
* **Quick Deployments** (75-80% faster)
* **Reduced Risk** in changes and updates

### **5. Cost Optimization**

* **60-70% Reduction** in post-production costs
* **50% Smaller Teams** for same output
* **Reduced Infrastructure** complexity
* **Lower Maintenance** overhead

***

## 🚀 Strategic Post-Production Advantages

### **1. Competitive Advantage**

* **Faster Time-to-Market** for new features
* **Lower Operational Costs** than competitors
* **Higher Team Productivity** and satisfaction
* **Reduced Technical Debt** accumulation

### **2. Risk Mitigation**

* **Consistent Patterns** reduce implementation risks
* **Framework Updates** handle security and performance
* **Standardized Processes** reduce human error
* **Built-in Monitoring** provides early warning

### **3. Scalability**

* **Easy Team Scaling** with consistent patterns
* **Rapid Feature Addition** with framework support
* **Horizontal Scaling** with stateless design
* **Multi-tenant Support** built-in

### **4. Future-Proofing**

* **Framework Evolution** handles technology changes
* **Consistent Architecture** supports new technologies
* **Modular Design** enables easy refactoring
* **Enterprise Patterns** ensure long-term viability

***

## 🎯 Bottom Line

**Applications Built With Flexbase delivers exceptional post-production value through consistent patterns, generated infrastructure, and enterprise-grade architecture, resulting in 60-70% reduction in operational costs, 65-70% faster feature delivery, and 55-65% faster team scaling while maintaining enterprise-grade quality and reliability.**

**Key Post-Production Benefits:**

* 🔧 **60-70% maintenance reduction** - Consistent patterns and framework support
* 🚀 **65-70% faster features** - Auto-generated infrastructure and integration
* ⚡ **75-80% faster deployments** - Standardized processes and automation
* 🔒 **70-75% security efficiency** - Centralized security and automatic updates
* 👥 **55-65% faster onboarding** - Consistent patterns and documentation
* 💰 **60-70% cost reduction** - Smaller teams and higher productivity
* 📈 **Higher quality** - Pre-tested framework and standardized patterns
* 🎯 **Business agility** - Faster delivery and reduced risk

***

*This document demonstrates how the Applications Built With Flexbase framework provides exceptional post-production value through consistent architecture, generated infrastructure, and enterprise patterns that significantly reduce operational overhead while accelerating feature delivery and team productivity.*


# Flexbase and Gen AI

## 🚀 The Ultimate Development Combination

This analysis compares **Traditional Development + Coding Agents** versus **Flexbase Framework + Coding Agents**, demonstrating how the combination of Flexbase with AI coding agents creates an exponentially more powerful development environment.

***

## 📊 Development Approach Comparison

### **Scenario 1: Traditional Development + Coding Agents**

#### **What Coding Agents Can Do:**

* **Code Generation**: Generate boilerplate code, CRUD operations
* **Bug Fixing**: Identify and fix common bugs
* **Code Refactoring**: Improve code structure and patterns
* **Documentation**: Generate code comments and documentation
* **Testing**: Create unit tests and integration tests

#### **What Coding Agents Cannot Do:**

* **Architecture Decisions**: Cannot make architectural choices
* **Framework Integration**: Cannot integrate with enterprise frameworks
* **Database Design**: Cannot design optimal database schemas
* **Message Bus Setup**: Cannot configure complex messaging
* **Security Implementation**: Cannot implement enterprise security patterns
* **Performance Optimization**: Cannot optimize at framework level

#### **Traditional + Coding Agents Effort:**

```
Complete Business Module Development:
├── Requirements Analysis: 2-3 days (human)
├── Architecture Design: 2-3 days (human)
├── Database Design: 1-2 days (human)
├── Coding Agent Code Generation: 3-4 days (AI + human review)
├── Framework Integration: 2-3 days (human)
├── Message Bus Setup: 1-2 days (human)
├── Security Implementation: 1-2 days (human)
├── Testing & Debugging: 2-3 days (AI + human)
├── Documentation: 1 day (AI + human review)
├── Code Review & Refactoring: 1-2 days (human)
└── Total: 16-25 days (3-5 weeks)

Coding Agent Contribution: 30-40% of total effort
Human Effort: 60-70% of total effort
```

### **Scenario 2: Applications Built With Flexbase Framework + Coding Agents**

#### **What Applications Built With Flexbase Framework Provides:**

* **Complete Architecture**: Enterprise patterns built-in
* **Database Integration**: Auto-migrations and schema management
* **Message Bus Integration**: Event-driven architecture ready
* **Security Framework**: Authentication and authorization built-in
* **API Generation**: REST endpoints with documentation
* **Testing Infrastructure**: Pre-configured testing patterns

#### **What Coding Agents Can Focus On:**

* **Business Logic**: Custom validation rules and business processes
* **Domain Models**: Attributes and business-specific properties
* **Custom Mappings**: Special projection requirements
* **State Machine Logic**: Business workflow transitions
* **Integration Code**: External service integrations
* **Performance Tuning**: Business-specific optimizations

#### **Applications Built With Flexbase + Coding Agents Effort:**

```
Complete Business Module Development:
├── Requirements Analysis: 2-3 days (human)
├── Domain Model Definition: 0.5 days (human + AI)
├── Code Generation: 0.5 days (framework)
├── AI Business Logic Generation: 1-2 days (AI + human review)
├── AI Custom Mappings: 0.5 days (AI + human review)
├── AI State Machine Logic: 0.5-1 day (AI + human review)
├── AI Integration Code: 1-2 days (AI + human review)
├── AI Testing Enhancement: 0.5-1 day (AI + human review)
├── AI Documentation: 0.5 day (AI + human review)
└── Total: 7-12 days (1.5-2.5 weeks)

Coding Agent Contribution: 50-60% of total effort
Human Effort: 40-50% of total effort
Framework Contribution: 30-40% of total effort
```

***

## 🎯 Detailed Comparison Analysis

### **1. Code Generation Efficiency**

#### **Traditional + Coding Agents:**

```csharp
// AI generates boilerplate code
public class OrderController : ControllerBase
{
    private readonly IOrderService _orderService;
    
    public OrderController(IOrderService orderService)
    {
        _orderService = orderService;
    }
    
    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
    {
        // AI generates basic CRUD logic
        var order = await _orderService.CreateOrderAsync(request);
        return Ok(order);
    }
}

// Human still needs to implement:
// - Service layer
// - Repository pattern
// - Database context
// - Message bus integration
// - Security attributes
// - Error handling
// - Validation
// - Logging
```

#### **Applications Built With Flexbase + Coding Agents:**

```csharp
// Framework generates complete infrastructure
[HttpPost]
[Route("AddOrder")]
[ProducesResponseType(typeof(OrderDto), 201)]
[SwaggerOperation(Summary = "Create a new order")]
public async Task<IActionResult> AddOrder([FromBody] AddOrderDto dto)
{
    return await RunService(201, dto, _processOrdersService.AddOrder);
}

// AI focuses on business logic
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // AI generates custom business logic
    if (cmd.Dto.TotalAmount > 10000)
    {
        throw new BusinessException("Order amount exceeds limit");
    }
    
    // AI generates custom validation
    if (cmd.Dto.CustomerId == null || !IsValidCustomer(cmd.Dto.CustomerId))
    {
        throw new ValidationException("Invalid customer");
    }
    
    // AI generates custom business rules
    ApplyDiscountIfEligible(cmd.Dto);
    CalculateTaxes(cmd.Dto);
    
    // Framework handles the rest
    this.Convert(cmd.Dto);
    this.SetAdded(cmd.Dto.GetGeneratedId());
    return this;
}
```

### **2. Testing Efficiency**

#### **Traditional + Coding Agents:**

```csharp
// AI generates basic tests
[Test]
public async Task CreateOrder_ShouldReturnOrder_WhenValidRequest()
{
    // AI generates test setup
    var mockService = new Mock<IOrderService>();
    var controller = new OrderController(mockService.Object);
    
    // AI generates test execution
    var result = await controller.CreateOrder(validRequest);
    
    // AI generates assertions
    Assert.IsInstanceOf<OkObjectResult>(result);
}

// Human still needs to implement:
// - Integration tests
// - Database tests
// - Message bus tests
// - Security tests
// - Performance tests
// - Mock configurations
```

#### **Applications Built With Flexbase + Coding Agents:**

```csharp
// Framework provides testing infrastructure
[Test]
public async Task AddOrder_ShouldCreateOrder_WhenValidData()
{
    // AI generates business logic tests
    var order = new Order();
    var command = new AddOrderCommand(validDto, context);
    
    // AI generates business rule tests
    var result = order.AddOrder(command);
    
    // AI generates custom assertions
    Assert.IsNotNull(result);
    Assert.AreEqual(validDto.TotalAmount, result.TotalAmount);
    Assert.IsTrue(result.OrderItems.Any());
}

// Framework handles:
// - Integration test setup
// - Database test configuration
// - Message bus test mocking
// - Security test patterns
// - Performance test infrastructure
```

### **3. Documentation Efficiency**

#### **Traditional + Coding Agents:**

```csharp
// AI generates basic documentation
/// <summary>
/// Creates a new order
/// </summary>
/// <param name="request">Order creation request</param>
/// <returns>Created order</returns>
[HttpPost]
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)

// Human still needs to create:
// - API documentation
// - Architecture documentation
// - Database schema documentation
// - Integration documentation
// - Deployment documentation
// - Security documentation
```

#### **Applications Built With Flexbase + Coding Agents:**

```csharp
// Framework generates complete documentation
[HttpPost]
[Route("AddOrder")]
[ProducesResponseType(typeof(OrderDto), 201)]
[ProducesResponseType(typeof(ValidationProblemDetails), 400)]
[SwaggerOperation(
    Summary = "Create a new order",
    Description = "Creates a new order with the provided details",
    OperationId = "AddOrder",
    Tags = new[] { "Orders" }
)]
[SwaggerResponse(201, "Order created successfully", typeof(OrderDto))]
[SwaggerResponse(400, "Invalid input data", typeof(ValidationProblemDetails))]
public async Task<IActionResult> AddOrder([FromBody] AddOrderDto dto)

// AI enhances business logic documentation
/// <summary>
/// Adds a new order with business validation and rules
/// </summary>
/// <param name="cmd">Order command with validation context</param>
/// <returns>Created order with applied business rules</returns>
/// <remarks>
/// Business Rules:
/// - Order amount must not exceed $10,000
/// - Customer must be valid and active
/// - Automatic discount applied for orders over $500
/// - Tax calculation based on customer location
/// </remarks>
public virtual Order AddOrder(AddOrderCommand cmd)
```

***

## 🚀 Synergistic Benefits

### **1. AI Agent Efficiency Multiplier**

#### **Traditional + Coding Agents:**

* **AI Focus**: 30-40% on boilerplate code
* **Human Focus**: 60-70% on architecture and integration
* **AI Limitations**: Cannot handle complex framework integration
* **Human Overhead**: High due to architectural decisions

#### **Applications Built With Flexbase + Coding Agents:**

* **AI Focus**: 50-60% on business logic and custom code
* **Human Focus**: 40-50% on business requirements and validation
* **AI Strengths**: Excels at business logic and custom implementations
* **Human Efficiency**: Higher due to framework handling complexity

### **2. Code Quality Enhancement**

#### **Traditional + Coding Agents:**

```csharp
// AI generates inconsistent patterns
public class OrderService : IOrderService
{
    public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
    {
        // AI generates basic logic
        var order = new Order();
        // ... basic implementation
        return order;
    }
}

// Human needs to add:
// - Error handling
// - Logging
// - Validation
// - Security
// - Performance optimization
```

#### **Applications Built With Flexbase + Coding Agents:**

```csharp
// Framework provides consistent patterns
// AI enhances business logic
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // AI generates sophisticated business logic
    if (cmd.Dto.TotalAmount > 10000)
    {
        throw new BusinessException("Order amount exceeds limit");
    }
    
    // AI generates complex validation
    ValidateCustomerEligibility(cmd.Dto.CustomerId);
    ValidateProductAvailability(cmd.Dto.OrderItems);
    ValidatePaymentMethod(cmd.Dto.PaymentInfo);
    
    // AI generates business rules
    ApplyLoyaltyDiscount(cmd.Dto);
    CalculateShippingCost(cmd.Dto);
    ApplyTaxRules(cmd.Dto);
    
    // Framework handles infrastructure
    this.Convert(cmd.Dto);
    this.SetAdded(cmd.Dto.GetGeneratedId());
    return this;
}
```

### **3. Testing and Quality Assurance**

#### **Traditional + Coding Agents:**

* **AI Generates**: Basic unit tests
* **Human Implements**: Integration tests, security tests, performance tests
* **Testing Effort**: 40-50% of development time
* **Quality Issues**: Inconsistent patterns lead to testing complexity

#### **Applications Built With Flexbase + Coding Agents:**

* **AI Generates**: Business logic tests, custom validation tests
* **Framework Provides**: Integration test infrastructure, security test patterns
* **Testing Effort**: 20-30% of development time
* **Quality Benefits**: Consistent patterns enable comprehensive testing

***

## 📊 Efficiency Comparison

### **Development Time Analysis**

```
Traditional + Coding Agents:
├── Core Development: 16-25 days
├── AI Contribution: 5-8 days (30-40%)
├── Human Effort: 11-17 days (60-70%)
├── Quality Issues: 2-3 days (additional)
└── Total: 18-28 days

Applications Built With Flexbase + Coding Agents:
├── Core Development: 7-12 days
├── AI Contribution: 3.5-6 days (50-60%)
├── Human Effort: 3.5-6 days (40-50%)
├── Framework Contribution: 2-3 days (30-40%)
├── Quality Benefits: 0 days (built-in)
└── Total: 7-12 days

Time Savings: 60-70% reduction
AI Efficiency: 2x improvement
Human Efficiency: 3x improvement
```

### **Code Quality Analysis**

```
Traditional + Coding Agents:
├── Consistency: 60-70% (AI helps but patterns vary)
├── Maintainability: 50-60% (inconsistent architecture)
├── Testability: 60-70% (AI helps but complex setup)
├── Security: 40-50% (manual implementation)
└── Performance: 50-60% (manual optimization)

Applications Built With Flexbase + Coding Agents:
├── Consistency: 90-95% (framework enforces patterns)
├── Maintainability: 85-90% (consistent architecture)
├── Testability: 85-90% (framework testing infrastructure)
├── Security: 90-95% (framework security patterns)
└── Performance: 80-85% (framework optimization)
```

***

## 🎯 Value Proposition Analysis

### **1. AI Agent Value Maximization**

#### **Traditional + Coding Agents:**

* **AI Utilization**: 30-40% (limited by architectural complexity)
* **AI Limitations**: Cannot handle framework integration
* **Human Overhead**: High due to architectural decisions
* **ROI**: Moderate (AI helps but human effort still high)

#### **Applications Built With Flexbase + Coding Agents:**

* **AI Utilization**: 50-60% (focused on business logic)
* **AI Strengths**: Excels at business logic and custom code
* **Human Efficiency**: High due to framework handling complexity
* **ROI**: High (AI and framework work synergistically)

### **2. Development Velocity**

#### **Traditional + Coding Agents:**

* **Initial Development**: 3-5 weeks per module
* **Maintenance**: 60-70% of development time
* **Feature Extensions**: 2-3 weeks per feature
* **Team Scaling**: 2-4 weeks per developer

#### **Applications Built With Flexbase + Coding Agents:**

* **Initial Development**: 1.5-2.5 weeks per module
* **Maintenance**: 20-30% of development time
* **Feature Extensions**: 1-2 weeks per feature
* **Team Scaling**: 1-2 weeks per developer

### **3. Long-term Sustainability**

#### **Traditional + Coding Agents:**

* **Technical Debt**: High (inconsistent patterns)
* **Maintenance Cost**: High (complex architecture)
* **Team Knowledge**: Fragmented (different patterns per module)
* **Scalability**: Limited (custom integration complexity)

#### **Applications Built With Flexbase + Coding Agents:**

* **Technical Debt**: Low (consistent patterns)
* **Maintenance Cost**: Low (framework-managed infrastructure)
* **Team Knowledge**: Unified (consistent patterns across modules)
* **Scalability**: High (framework handles complexity)

***

## 🚀 Strategic Advantages

### **1. Competitive Edge**

* **Faster Time-to-Market**: 60-70% faster development
* **Higher Quality**: Consistent patterns and AI-enhanced business logic
* **Lower Costs**: 50-60% reduction in development and maintenance costs
* **Better Scalability**: Framework handles infrastructure complexity

### **2. Team Productivity**

* **AI Efficiency**: 2x improvement in AI utilization
* **Human Focus**: 3x improvement in human efficiency
* **Knowledge Transfer**: 50% faster onboarding
* **Reduced Burnout**: Less repetitive work, more creative problem-solving

### **3. Business Value**

* **Faster Feature Delivery**: 60-70% faster feature development
* **Higher Quality**: 90-95% consistency and reliability
* **Lower Risk**: Framework patterns reduce implementation risks
* **Future-Proof**: Easy to adopt new technologies and patterns

***

## 🎯 Bottom Line

**The combination of Applications Built With Flexbase Framework + Coding Agents creates an exponentially more powerful development environment than Traditional Development + Coding Agents, delivering 60-70% faster development, 2x AI efficiency, 3x human efficiency, and 90-95% code quality consistency.**

**Key Synergistic Benefits:**

* 🤖 **2x AI Efficiency** - AI focuses on business logic, not boilerplate
* 🏗️ **3x Human Efficiency** - Framework handles architecture complexity
* ⚡ **60-70% Faster Development** - AI + Framework work synergistically
* 📈 **90-95% Code Quality** - Consistent patterns + AI enhancement
* 🔧 **50-60% Lower Maintenance** - Framework-managed infrastructure
* 👥 **50% Faster Team Scaling** - Consistent patterns + AI assistance
* 💰 **50-60% Cost Reduction** - Higher efficiency + lower maintenance
* 🚀 **Future-Proof Architecture** - Framework evolution + AI adaptation

***

*This analysis demonstrates that Applications Built With Flexbase Framework + Coding Agents is not just an incremental improvement over Traditional Development + Coding Agents, but a fundamental paradigm shift that maximizes the value of both AI capabilities and human expertise while delivering enterprise-grade quality and consistency.*


# Separate Command And Query

## Overview

FlexBase implements **Command Query Responsibility Segregation (CQRS)** as a core architectural pattern, providing clear separation between data modification operations (Commands) and data retrieval operations (Queries). This separation enables independent scaling, optimization, and maintenance of read and write operations.

## Architecture Pattern

### **Command-Query Separation**

```
┌─────────────────┐    ┌─────────────────┐
│   COMMANDS      │    │    QUERIES      │
│   (Write Ops)   │    │   (Read Ops)    │
├─────────────────┤    ├─────────────────┤
│ • Insert        │    │ • GetById       │
│ • Update        │    │ • GetSingle     │
│ • Delete        │    │ • GetList       │
│ • SoftDelete    │    │ • GetPagedList  │
└─────────────────┘    └─────────────────┘
         │                       │
         ▼                       ▼
┌─────────────────┐    ┌─────────────────┐
│ Write Repository│    │ Read Repository │
│ (Write DB)      │    │ (Read DB)       │
└─────────────────┘    └─────────────────┘
```

## Command Operations

### **Purpose**

Commands handle **data modification** operations that change the state of the system.

### **Characteristics**

* **Write Operations**: Create, Update, Delete, SoftDelete
* **State Changes**: Modify data in the system
* **Event Publishing**: Trigger events after successful operations
* **Transaction Support**: Full ACID compliance
* **Audit Trail**: Track who made changes and when

### **Command Flow**

```
Controller → Service → Command Handler → Domain Model → Write Repository → Write Database → Event Publishing
```

### **Command Examples**

* **Insert**: `AddOrder`, `CreateProduct`, `RegisterUser`
* **Update**: `UpdateOrder`, `EditProduct`, `ModifyUser`
* **Delete**: `DeleteOrder`, `RemoveProduct`, `DeactivateUser`
* **SoftDelete**: `SoftDeleteOrder`, `ArchiveProduct`, `DeactivateUser`

### **Command Implementation**

```csharp
// Command Handler
public class AddOrderHandler : IAddOrderHandler
{
    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _repoFactory.Init(cmd.Dto);
        
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        int records = await _repoFactory.GetRepo().SaveAsync();
        
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

## Query Operations

### **Purpose**

Queries handle **data retrieval** operations that read data without modifying the system state.

### **Characteristics**

* **Read Operations**: GetById, GetSingle, GetList, GetPagedList
* **No State Changes**: Read-only operations
* **No Events**: No side effects or event publishing
* **Optimized for Performance**: Tuned for fast data retrieval
* **Caching Friendly**: Can be easily cached

### **Query Flow**

```
Controller → Service → Query Handler → Read Repository → Read Database → Response
```

### **Query Examples**

* **GetById**: `GetOrderById`, `GetProductById`, `GetUserById`
* **GetSingle**: `GetOrderByNumber`, `GetProductBySku`, `GetUserByEmail`
* **GetList**: `GetOrders`, `GetProducts`, `GetUsers`
* **GetPagedList**: `GetOrdersPaged`, `GetProductsPaged`, `GetUsersPaged`

### **Query Implementation**

```csharp
// Query Handler
public class GetOrderById : FlexiQueryBridge<Order, GetOrderByIdDto>
{
    public override GetOrderByIdDto Fetch()
    {
        var result = Build<Order>().SelectTo<GetOrderByIdDto>().FirstOrDefault();
        return result;
    }

    protected override IQueryable<T> Build<T>()
    {
        _repoFactory.Init(_params);
        IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>().Where(t => t.Id == _params.Id);
        return query;
    }
}
```

## Repository Separation

### **Write Repository (Commands)**

* **Purpose**: Handles all data modification operations
* **Database**: Connected to the primary/write database
* **Operations**: Insert, Update, Delete, SoftDelete
* **Transaction Support**: Full ACID compliance
* **Audit Trail**: Tracks all changes

### **Read Repository (Queries)**

* **Purpose**: Handles all data retrieval operations
* **Database**: Can be connected to read-only replica or separate read database
* **Operations**: Select, Filter, Search, Pagination
* **Performance Optimized**: Tuned for fast queries
* **Caching Support**: Can be easily cached

### **Repository Configuration**

```csharp
// Write Repository Registration
services.AddTransient<IWriteDbConnectionProviderBridge, AppSettingsWriteDbConnectionProvider>();

// Read Repository Registration
services.AddTransient<IReadDbConnectionProviderBridge, AppSettingsReadDbConnectionProvider>();
```

## Production Scalability Benefits

### **1. Independent Database Scaling**

#### **Write Database Scaling**

* **Vertical Scaling**: Increase CPU, memory, and storage for write operations
* **Optimized for Writes**: Tuned for insert, update, delete operations
* **Transaction Performance**: Optimized for ACID compliance
* **Backup Strategy**: Full backup and point-in-time recovery

#### **Read Database Scaling**

* **Horizontal Scaling**: Multiple read replicas for high availability
* **Read-Only Optimizations**: Indexes optimized for query patterns
* **Caching Layer**: Redis or in-memory caching for frequently accessed data
* **Geographic Distribution**: Read replicas in different regions

### **2. Performance Optimization**

#### **Write Database Optimizations**

```sql
-- Write-optimized indexes
CREATE INDEX IX_Orders_CreatedDate ON Orders (CreatedDate);
CREATE INDEX IX_Orders_LastModified ON Orders (LastModifiedDate);

-- Partitioning for large tables
CREATE PARTITION FUNCTION PF_OrdersByDate (datetime)
AS RANGE RIGHT FOR VALUES ('2024-01-01', '2024-02-01', '2024-03-01');
```

#### **Read Database Optimizations**

```sql
-- Read-optimized indexes
CREATE INDEX IX_Orders_CustomerId_OrderDate ON Orders (CustomerId, OrderDate);
CREATE INDEX IX_Orders_Status_CreatedDate ON Orders (Status, CreatedDate);

-- Covering indexes for common queries
CREATE INDEX IX_Orders_Covering ON Orders (CustomerId) 
INCLUDE (OrderDate, TotalAmount, Status);
```

### **3. High Availability Architecture**

#### **Write Database**

* **Primary Database**: Single source of truth for all writes
* **Synchronous Replication**: Real-time data consistency
* **Failover Support**: Automatic failover to secondary
* **Data Integrity**: ACID compliance and consistency

#### **Read Database**

* **Multiple Replicas**: Several read-only replicas
* **Asynchronous Replication**: Near real-time data availability
* **Load Balancing**: Distribute read load across replicas
* **Geographic Distribution**: Replicas in different regions

### **4. Cost Optimization**

#### **Write Database Costs**

* **High-Performance Hardware**: SSD storage, high CPU/memory
* **Backup Storage**: Full and incremental backups
* **Monitoring**: Comprehensive monitoring and alerting
* **Security**: Advanced security and compliance features

#### **Read Database Costs**

* **Standard Hardware**: Cost-effective hardware for read operations
* **Reduced Backup Requirements**: Less frequent backups
* **Basic Monitoring**: Essential monitoring for read operations
* **Standard Security**: Standard security measures

## Configuration Examples

### **Single Database Configuration**

```csharp
// Both commands and queries use the same database
services.AddTransient<IWriteDbConnectionProviderBridge, AppSettingsWriteDbConnectionProvider>();
services.AddTransient<IReadDbConnectionProviderBridge, AppSettingsReadDbConnectionProvider>();
```

### **Separate Database Configuration**

```csharp
// Commands use write database
services.AddTransient<IWriteDbConnectionProviderBridge, AppSettingsWriteDbConnectionProvider>();

// Queries use read database
services.AddTransient<IReadDbConnectionProviderBridge, AppSettingsReadDbConnectionProvider>();
```

### **Connection String Configuration**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=WriteServer;Initial Catalog=YourDatabase;...",
    "AppReadDbConnection": "Data Source=ReadServer;Initial Catalog=YourReadDatabase;..."
  }
}
```

## Real-World Scaling Scenarios

### **Scenario 1: High-Volume E-Commerce**

* **Write Database**: Handles order creation, updates, and inventory changes
* **Read Database**: Serves product catalogs, search results, and analytics
* **Scaling**: Read replicas in multiple regions for global customers

### **Scenario 2: Financial Services**

* **Write Database**: Processes transactions, account updates, and payments
* **Read Database**: Serves account balances, transaction history, and reports
* **Scaling**: Read replicas for compliance reporting and analytics

### **Scenario 3: Social Media Platform**

* **Write Database**: Handles posts, comments, and user interactions
* **Read Database**: Serves feeds, timelines, and search results
* **Scaling**: Multiple read replicas for content delivery

## Monitoring and Metrics

### **Write Database Metrics**

* **Transaction Rate**: Commands per second
* **Response Time**: Average command execution time
* **Error Rate**: Failed command percentage
* **Resource Utilization**: CPU, memory, disk usage

### **Read Database Metrics**

* **Query Rate**: Queries per second
* **Response Time**: Average query execution time
* **Cache Hit Rate**: Percentage of cached queries
* **Replica Lag**: Data freshness across replicas

## Best Practices

### **1. Database Design**

* **Write Database**: Normalized for consistency and integrity
* **Read Database**: Denormalized for query performance
* **Indexing Strategy**: Different indexes for write vs read patterns

### **2. Caching Strategy**

* **Write Operations**: No caching (always fresh data)
* **Read Operations**: Aggressive caching for frequently accessed data
* **Cache Invalidation**: Smart invalidation on data changes

### **3. Monitoring**

* **Separate Monitoring**: Different monitoring for write and read operations
* **Performance Metrics**: Track performance independently
* **Alerting**: Different alerting thresholds for each database

### **4. Backup and Recovery**

* **Write Database**: Full backup and point-in-time recovery
* **Read Database**: Less frequent backups, can be rebuilt from write database

## Key Benefits

* **Independent Scaling**: Scale read and write operations separately
* **Performance Optimization**: Optimize each database for its specific workload
* **High Availability**: Multiple read replicas for better availability
* **Cost Optimization**: Use appropriate hardware for each workload
* **Maintenance**: Perform maintenance on read replicas without affecting writes
* **Geographic Distribution**: Place read replicas closer to users
* **Disaster Recovery**: Better disaster recovery options
* **Load Distribution**: Distribute read load across multiple replicas

***

**This Command-Query separation in FlexBase provides a robust foundation for building scalable, high-performance applications that can handle both high-volume writes and complex read operations efficiently!** 🚀


# Build Applications that Scale

## The Scaling Challenge

Imagine starting with a simple e-commerce application serving 100 users, then watching it grow to serve millions. Traditional approaches often require complete rewrites, architectural overhauls, and months of refactoring. **FlexBase changes this reality.**

With FlexBase, you can start small and scale to enterprise levels **without rewriting a single line of business code**. The secret lies in its **endpoint-based architecture** and **configuration-driven scaling**.

## The FlexBase Scaling Philosophy

### **Start Simple, Scale Seamlessly**

```
Phase 1: 100 Users    →  Single Server, Single Database
Phase 2: 1,000 Users  →  Load Balancer, Read Replicas  
Phase 3: 10,000 Users →  Microservices, Message Queues
Phase 4: 1M+ Users    →  Cloud-Native, Global Distribution
```

**Your business code remains unchanged throughout this journey.**

## Endpoint Architecture: The Scaling Foundation

### **Modular Endpoint Design**

FlexBase applications are built as **independent, scalable endpoints** that can be deployed and scaled separately:

```
┌─────────────────────┐    ┌─────────────────────┐    ┌─────────────────────┐
│   WebAPI Endpoint   │    │  Handlers Endpoint  │    │ Subscribers Endpoint│
│   (User Interface)  │    │  (Command Processing)│    │ (Event Processing)  │
│                     │    │                     │    │                     │
│ • REST Controllers  │    │ • Command Handlers  │    │ • Event Subscribers │
│ • API Gateway       │    │ • Business Logic    │    │ • Background Tasks  │
│ • Authentication    │    │ • Data Validation   │    │ • Notifications     │
│ • Rate Limiting     │    │ • Database Writes   │    │ • Analytics         │
└─────────────────────┘    └─────────────────────┘    └─────────────────────┘
         │                           │                           │
         └───────────────────────────┼───────────────────────────┘
                                     │
                            ┌─────────────────────┐
                            │   Message Queue     │
                            │   (NServiceBus)     │
                            │                     │
                            │ • Reliable Messaging│
                            │ • Event Sourcing    │
                            │ • Saga Orchestration│
                            │ • Dead Letter Queue │
                            └─────────────────────┘
```

### **Why This Architecture Scales**

1. **Independent Scaling**: Each endpoint scales based on its specific workload
2. **Fault Isolation**: Failure in one endpoint doesn't affect others
3. **Technology Flexibility**: Use different technologies for different endpoints
4. **Deployment Independence**: Deploy updates without affecting other endpoints

## Scaling Journey: From 100 to Millions

### **Phase 1: Startup (100 Users)**

**Infrastructure**: Single server, single database **Configuration**: All endpoints on one machine

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=localhost;Initial Catalog=YourApp;...",
    "AppReadDbConnection": "Data Source=localhost;Initial Catalog=YourApp;...",
    "RabbitMqConnectionString": "amqp://guest:guest@localhost:5672"
  }
}
```

**Deployment**:

* WebAPI + Handlers + Subscribers on single server
* Single SQL Server database
* Local RabbitMQ for messaging

**Cost**: \~$50-100/month\*

\*Note: All costs mentioned in this document are illustrative examples for comparison purposes. Actual costs may vary significantly based on specific requirements, cloud provider pricing, geographic location, usage patterns, and other factors.

### **Phase 2: Growth (1,000 Users)**

**Infrastructure**: Load balancer, read replicas, separate servers **Configuration**: Split endpoints across servers

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=WriteServer;Initial Catalog=YourApp;...",
    "AppReadDbConnection": "Data Source=ReadServer;Initial Catalog=YourApp;...",
    "RabbitMqConnectionString": "amqp://guest:guest@rabbitmq-server:5672"
  }
}
```

**Deployment**:

* WebAPI on 2 servers behind load balancer
* Handlers on dedicated server
* Subscribers on dedicated server
* Write database + Read replica
* Centralized RabbitMQ cluster

**Cost**: \~$500-1,000/month\*

### **Phase 3: Scale (10,000 Users)**

**Infrastructure**: Microservices, message queues, caching **Configuration**: Cloud-native deployment

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=WriteCluster;Initial Catalog=YourApp;...",
    "AppReadDbConnection": "Data Source=ReadCluster;Initial Catalog=YourApp;...",
    "AzureServiceBusConnectionString": "Endpoint=sb://yournamespace.servicebus.windows.net/;...",
    "AzureStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=yourstorage;..."
  }
}
```

**Deployment**:

* WebAPI: 5+ instances in Azure App Service
* Handlers: Azure Functions or Container Instances
* Subscribers: Azure Functions or Container Instances
* Database: Azure SQL with read replicas
* Messaging: Azure Service Bus
* Caching: Redis Cache

**Cost**: \~$2,000-5,000/month\*

### **Phase 4: Enterprise (1M+ Users)**

**Infrastructure**: Global distribution, multi-region, advanced caching **Configuration**: Multi-cloud, global deployment

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=WriteCluster-WestUS;Initial Catalog=YourApp;...",
    "AppReadDbConnection": "Data Source=ReadCluster-EastUS;Initial Catalog=YourApp;...",
    "AzureServiceBusConnectionString": "Endpoint=sb://yournamespace.servicebus.windows.net/;...",
    "AmazonSQSTransportBucketName": "your-sqs-bucket",
    "TenantMasterDbConnection": "Data Source=TenantMaster;Initial Catalog=TenantMaster;..."
  }
}
```

**Deployment**:

* WebAPI: Global CDN + multiple regions
* Handlers: Kubernetes clusters across regions
* Subscribers: Event-driven serverless functions
* Database: Multi-region SQL with geo-replication
* Messaging: Multi-cloud message buses
* Caching: Distributed Redis clusters

**Cost**: \~$10,000-50,000/month\*

## CQRS: The Scaling Multiplier

### **Command-Query Separation Benefits**

```
┌─────────────────┐    ┌─────────────────┐
│   COMMANDS      │    │    QUERIES      │
│   (Write Ops)   │    │   (Read Ops)    │
├─────────────────┤    ├─────────────────┤
│ • High Volume   │    │ • High Frequency│
│ • ACID Required │    │ • Performance   │
│ • Event Sourcing│    │ • Caching       │
│ • Audit Trail   │    │ • Aggregation   │
└─────────────────┘    └─────────────────┘
         │                       │
         ▼                       ▼
┌─────────────────┐    ┌─────────────────┐
│ Write Database  │    │ Read Database   │
│ (Normalized)    │    │ (Denormalized)  │
│ • Consistency   │    │ • Performance   │
│ • Integrity     │    │ • Scalability   │
└─────────────────┘    └─────────────────┘
```

### **Independent Scaling Advantages**

1. **Write Database**: Optimized for transactions and consistency
2. **Read Database**: Optimized for queries and performance
3. **Separate Scaling**: Scale read and write operations independently
4. **Cost Optimization**: Use appropriate hardware for each workload

## Message Queue: The Scaling Enabler

### **Asynchronous Processing Benefits**

```
User Request → WebAPI → Message Queue → Handler → Database
     ↓              ↓           ↓          ↓         ↓
  Immediate      Fast        Reliable   Process   Update
  Response      Response    Delivery   Business   Data
```

### **Why Message Queues Scale**

1. **Decoupling**: WebAPI responds immediately, processing happens asynchronously
2. **Reliability**: Messages are persisted and retried on failure
3. **Load Distribution**: Multiple handlers can process messages in parallel
4. **Fault Tolerance**: Failed messages go to dead letter queue for investigation

### **Message Queue Options**

| Phase | Users  | Queue Technology   | Benefits                        |
| ----- | ------ | ------------------ | ------------------------------- |
| 1     | 100    | RabbitMQ (Local)   | Simple setup, low cost          |
| 2     | 1,000  | RabbitMQ (Cluster) | High availability, clustering   |
| 3     | 10,000 | Azure Service Bus  | Managed service, auto-scaling   |
| 4     | 1M+    | Multi-Cloud        | Global distribution, redundancy |

## Configuration-Driven Scaling

### **The Magic of Configuration**

**Same Code, Different Scale** - Your business logic never changes, only the configuration:

```csharp
// This code works for 100 users AND 1 million users
public class AddOrderHandler : IAddOrderHandler
{
    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _repoFactory.Init(cmd.Dto);
        
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        int records = await _repoFactory.GetRepo().SaveAsync();
        
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

### **Scaling Through Configuration Changes**

#### **Database Scaling**

```json
// Phase 1: Single Database
"AppDbConnection": "Data Source=localhost;Initial Catalog=YourApp;..."

// Phase 2: Read Replicas
"AppDbConnection": "Data Source=WriteServer;Initial Catalog=YourApp;..."
"AppReadDbConnection": "Data Source=ReadServer;Initial Catalog=YourApp;..."

// Phase 3: Cloud Databases
"AppDbConnection": "Data Source=WriteCluster.database.windows.net;..."
"AppReadDbConnection": "Data Source=ReadCluster.database.windows.net;..."

// Phase 4: Multi-Region
"AppDbConnection": "Data Source=WriteCluster-WestUS.database.windows.net;..."
"AppReadDbConnection": "Data Source=ReadCluster-EastUS.database.windows.net;..."
```

#### **Message Queue Scaling**

```json
// Phase 1: Local RabbitMQ
"RabbitMqConnectionString": "amqp://guest:guest@localhost:5672"

// Phase 2: RabbitMQ Cluster
"RabbitMqConnectionString": "amqp://guest:guest@rabbitmq-cluster:5672"

// Phase 3: Azure Service Bus
"AzureServiceBusConnectionString": "Endpoint=sb://yournamespace.servicebus.windows.net/;..."

// Phase 4: Multi-Cloud
"AzureServiceBusConnectionString": "Endpoint=sb://yournamespace.servicebus.windows.net/;..."
"AmazonSQSTransportBucketName": "your-sqs-bucket"
```

## Real-World Scaling Scenarios

### **E-Commerce Platform Scaling**

#### **Phase 1: Local Business (100 users)**

* **Setup**: Single server, local database
* **Features**: Basic order processing, inventory management
* **Performance**: 10 orders/minute, 100 concurrent users
* **Cost**: $100/month

#### **Phase 2: Regional Business (1,000 users)**

* **Setup**: Load balancer, read replicas, message queues
* **Features**: Advanced inventory, customer management
* **Performance**: 100 orders/minute, 1,000 concurrent users
* **Cost**: $1,000/month

#### **Phase 3: National Business (10,000 users)**

* **Setup**: Cloud deployment, microservices, caching
* **Features**: Real-time inventory, advanced analytics
* **Performance**: 1,000 orders/minute, 10,000 concurrent users
* **Cost**: $5,000/month

#### **Phase 4: Global Business (1M+ users)**

* **Setup**: Multi-region, global CDN, advanced caching
* **Features**: Global inventory, AI recommendations, real-time analytics
* **Performance**: 10,000+ orders/minute, 100,000+ concurrent users
* **Cost**: $25,000/month

### **Financial Services Scaling**

#### **Phase 1: Local Bank (100 users)**

* **Setup**: Single server, local database
* **Features**: Basic transactions, account management
* **Performance**: 50 transactions/minute, 100 concurrent users
* **Cost**: $200/month

#### **Phase 2: Regional Bank (1,000 users)**

* **Setup**: High-availability setup, read replicas
* **Features**: Advanced transactions, compliance reporting
* **Performance**: 500 transactions/minute, 1,000 concurrent users
* **Cost**: $2,000/month

#### **Phase 3: National Bank (10,000 users)**

* **Setup**: Cloud deployment, microservices, event sourcing
* **Features**: Real-time processing, advanced analytics
* **Performance**: 5,000 transactions/minute, 10,000 concurrent users
* **Cost**: $10,000/month

#### **Phase 4: Global Bank (1M+ users)**

* **Setup**: Multi-region, global distribution, advanced security
* **Features**: Global transactions, AI fraud detection, real-time compliance
* **Performance**: 50,000+ transactions/minute, 100,000+ concurrent users
* **Cost**: $50,000/month

## Load Balancer Integration: The Traffic Distribution Engine

### **How Load Balancers Work with FlexBase**

Load balancers are the **traffic distribution engine** that enables FlexBase applications to scale horizontally. They intelligently route requests across multiple instances of your endpoints, ensuring optimal performance and high availability.

#### **Load Balancer Types and Their Role**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Load Balancer │    │   Load Balancer │    │   Load Balancer │
│   (Layer 4)     │    │   (Layer 7)     │    │   (Global)      │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ • TCP/UDP       │    │ • HTTP/HTTPS    │    │ • DNS-based     │
│ • Fast Routing  │    │ • Content-aware │    │ • Geographic    │
│ • Low Latency   │    │ • SSL Termination│    │ • Multi-region │
│ • High Throughput│    │ • Path Routing  │    │ • Failover     │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ WebAPI Instances│    │ WebAPI Instances│    │ WebAPI Instances│
│ (Multiple)      │    │ (Multiple)      │    │ (Multiple)      │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

### **Load Balancing Strategies by Scaling Phase**

#### **Phase 1: Simple Load Balancing (1,000 Users)**

```yaml
# Basic Round-Robin Load Balancer
apiVersion: v1
kind: Service
metadata:
  name: webapi-service
spec:
  selector:
    app: webapi-endpoint
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapi-endpoint
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapi-endpoint
  template:
    spec:
      containers:
      - name: webapi
        image: your-app:latest
        ports:
        - containerPort: 8080
```

**Benefits:**

* **Simple Setup**: Easy to configure and maintain
* **Equal Distribution**: Requests distributed evenly across instances
* **Basic Health Checks**: Automatic removal of unhealthy instances
* **Cost Effective**: Minimal infrastructure overhead

#### **Phase 2: Advanced Load Balancing (10,000 Users)**

```yaml
# Advanced Load Balancer with Health Checks
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapi-ingress
  annotations:
    nginx.ingress.kubernetes.io/load-balance: "round_robin"
    nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"
    nginx.ingress.kubernetes.io/health-check-path: "/health"
    nginx.ingress.kubernetes.io/health-check-interval: "10s"
spec:
  rules:
  - host: api.yourcompany.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapi-service
            port:
              number: 80
```

**Benefits:**

* **Health Monitoring**: Continuous health checks and automatic failover
* **Session Affinity**: Maintain user sessions across requests
* **Path-Based Routing**: Route different API endpoints to different services
* **SSL Termination**: Handle SSL certificates at the load balancer level

#### **Phase 3: Intelligent Load Balancing (100,000 Users)**

```yaml
# Intelligent Load Balancer with Auto-Scaling
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: webapi-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: webapi-endpoint
  minReplicas: 5
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: "100"
```

**Benefits:**

* **Auto-Scaling**: Automatically scale based on CPU, memory, and custom metrics
* **Predictive Scaling**: Scale up before traffic spikes
* **Cost Optimization**: Scale down during low-traffic periods
* **Performance Optimization**: Maintain optimal response times

#### **Phase 4: Global Load Balancing (1M+ Users)**

```yaml
# Global Load Balancer with Multi-Region
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: global-webapi-ingress
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: "global-ip"
    kubernetes.io/ingress.allow-http: "false"
    kubernetes.io/ingress.ssl-cert: "your-ssl-cert"
spec:
  rules:
  - host: api.yourcompany.com
    http:
      paths:
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: webapi-service
            port:
              number: 80
```

**Benefits:**

* **Global Distribution**: Route traffic to the nearest region
* **Geographic Load Balancing**: Optimize for user location
* **Disaster Recovery**: Automatic failover to backup regions
* **CDN Integration**: Cache static content globally

### **Load Balancer Configuration for FlexBase Endpoints**

#### **WebAPI Endpoint Load Balancing**

```csharp
// FlexBase WebAPI automatically handles load balancer integration
public class OrdersController : ControllerBase
{
    [HttpGet]
    [Route("GetOrders")]
    public async Task<IActionResult> GetOrders()
    {
        // This endpoint can handle requests from any load balancer
        // FlexBase automatically manages session state and context
        return await RunService(200, new GetOrdersDto(), _processOrdersService.GetOrders);
    }
}
```

**Load Balancer Benefits:**

* **Stateless Design**: Each request is independent
* **Session Management**: FlexBase handles user context automatically
* **Health Checks**: Built-in health check endpoints
* **Graceful Shutdown**: Proper handling of rolling updates

#### **Handler Endpoint Load Balancing**

```csharp
// Handlers automatically scale based on message queue depth
public class OrderProcessingHandler : IOrderProcessingHandler
{
    public virtual async Task Execute(ProcessOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Load balancer distributes messages across handler instances
        // Each handler processes messages independently
        await ProcessOrder(cmd);
    }
}
```

**Load Balancer Benefits:**

* **Message Distribution**: Even distribution of messages across handlers
* **Fault Tolerance**: Failed handlers don't affect message processing
* **Auto-Scaling**: Scale handlers based on queue depth
* **Dead Letter Handling**: Automatic retry and dead letter queue management

## FlexBase vs Serverless: The Scalability Showdown

### **The Serverless Promise vs Reality**

#### **What Serverless Promises**

* **Infinite Scalability**: Scale from 0 to millions of requests
* **Pay-per-Use**: Only pay for what you use
* **Zero Infrastructure Management**: No servers to manage
* **Automatic Scaling**: Scale automatically based on demand

#### **What Serverless Reality Delivers**

* **Cold Start Penalties**: 1-5 second delays on first request
* **Vendor Lock-in**: Difficult to migrate between cloud providers
* **Limited Execution Time**: 15-minute maximum execution time
* **Complex Debugging**: Difficult to debug distributed functions
* **Cost Surprises**: Can be expensive at scale
* **Limited Control**: No control over underlying infrastructure

### **FlexBase: Serverless Benefits Without the Drawbacks**

#### **FlexBase Achieves Serverless-Like Scalability**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Serverless    │    │    FlexBase     │    │   Traditional   │
│   Functions     │    │   Endpoints     │    │   Monoliths     │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ ❌ Cold Starts  │    │ ✅ Warm Starts  │    │ ❌ Always On    │
│ ❌ Vendor Lock  │    │ ✅ Cloud Agnostic│    │ ❌ Fixed Scale  │
│ ❌ Time Limits  │    │ ✅ No Limits    │    │ ❌ Manual Scale │
│ ❌ Debug Issues │    │ ✅ Easy Debug   │    │ ❌ Complex Deploy│
│ ❌ Cost Surprises│    │ ✅ Predictable  │    │ ❌ High Costs   │
│ ❌ Limited Control│    │ ✅ Full Control│    │ ❌ No Control   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

### **Detailed Comparison: FlexBase vs Serverless**

#### **1. Scalability Performance**

| Aspect               | Serverless     | FlexBase      | Winner      |
| -------------------- | -------------- | ------------- | ----------- |
| **Cold Start**       | 1-5 seconds    | <100ms        | 🏆 FlexBase |
| **Warm Performance** | 50-200ms       | 10-50ms       | 🏆 FlexBase |
| **Scaling Speed**    | 30-60 seconds  | 10-30 seconds | 🏆 FlexBase |
| **Max Concurrent**   | 1000+          | 10,000+       | 🏆 FlexBase |
| **Execution Time**   | 15 minutes max | Unlimited     | 🏆 FlexBase |

#### **2. Cost Analysis**

**Serverless Costs (AWS Lambda Example):**

```
100M requests/month:
- Compute: $20,000/month
- API Gateway: $3,500/month
- Data Transfer: $1,000/month
- Total: $24,500/month
```

**FlexBase Costs (Same Scale):**

```
100M requests/month:
- EC2 Instances: $8,000/month
- Load Balancer: $500/month
- Database: $2,000/month
- Total: $10,500/month
```

**Cost Savings: 57% with FlexBase**\*

\*Note: All costs mentioned in this document are illustrative examples for comparison purposes. Actual costs may vary significantly based on specific requirements, cloud provider pricing, geographic location, usage patterns, and other factors.

#### **3. Development Experience**

**Serverless Development:**

```javascript
// AWS Lambda Function
exports.handler = async (event) => {
    // Limited to 15 minutes
    // Cold start penalty
    // Difficult to debug
    // Vendor-specific code
    return {
        statusCode: 200,
        body: JSON.stringify({message: 'Hello from Lambda'})
    };
};
```

**FlexBase Development:**

```csharp
// FlexBase Handler
public class ProcessOrderHandler : IProcessOrderHandler
{
    public virtual async Task Execute(ProcessOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // No time limits
        // Warm start
        // Easy debugging
        // Cloud-agnostic code
        await ProcessOrder(cmd);
    }
}
```

#### **4. Monitoring and Observability**

**Serverless Monitoring:**

* **Limited Metrics**: Basic CloudWatch metrics
* **Complex Debugging**: Distributed tracing across functions
* **Vendor Lock-in**: Tied to specific cloud provider
* **Limited Customization**: Restricted to provider's monitoring tools

**FlexBase Monitoring:**

* **Rich Metrics**: Custom metrics, business KPIs
* **Easy Debugging**: Centralized logging and tracing
* **Cloud Agnostic**: Works with any monitoring solution
* **Full Customization**: Complete control over monitoring stack

### **FlexBase: The Best of Both Worlds**

#### **Serverless-Like Benefits with FlexBase**

1. **Automatic Scaling**

   ```yaml
   # FlexBase Auto-Scaling
   apiVersion: autoscaling/v2
   kind: HorizontalPodAutoscaler
   metadata:
     name: flexbase-hpa
   spec:
     minReplicas: 0  # Scale to zero like serverless
     maxReplicas: 1000
     metrics:
     - type: Resource
       resource:
         name: cpu
         target:
           type: Utilization
           averageUtilization: 70
   ```
2. **Pay-per-Use Economics**
   * **Scale to Zero**: No requests = no costs
   * **Resource Optimization**: Use only what you need
   * **Predictable Pricing**: No surprise bills
   * **Cost Transparency**: Clear understanding of costs
3. **Zero Infrastructure Management**
   * **Managed Kubernetes**: Use cloud-managed Kubernetes
   * **Auto-Updates**: Automatic security and feature updates
   * **Managed Databases**: Use cloud-managed databases
   * **Managed Message Queues**: Use cloud-managed message queues
4. **Infinite Scalability**
   * **Horizontal Scaling**: Scale to thousands of instances
   * **Global Distribution**: Deploy across multiple regions
   * **Load Balancing**: Intelligent traffic distribution
   * **Auto-Scaling**: Scale based on demand

#### **FlexBase Advantages Over Serverless**

1. **No Cold Starts**
   * **Warm Instances**: Always ready to handle requests
   * **Predictable Performance**: Consistent response times
   * **Better User Experience**: No waiting for cold starts
2. **No Vendor Lock-in**
   * **Cloud Agnostic**: Run on any cloud provider
   * **Portable Code**: Move between clouds easily
   * **Open Source**: No proprietary dependencies
3. **No Execution Time Limits**
   * **Long-Running Processes**: Handle complex business logic
   * **Batch Processing**: Process large datasets
   * **Real-time Processing**: Handle streaming data
4. **Better Debugging**
   * **Centralized Logging**: All logs in one place
   * **Distributed Tracing**: Track requests across services
   * **Local Development**: Run entire stack locally
5. **Full Control**
   * **Custom Configurations**: Tune for your specific needs
   * **Custom Monitoring**: Implement your own metrics
   * **Custom Scaling**: Implement custom scaling logic

### **Real-World Performance Comparison**

#### **E-Commerce Platform (1M Users)**

**Serverless Implementation:**

* **Cold Start Penalty**: 2-3 seconds for first request
* **Cost**: $25,000/month
* **Debugging**: Complex distributed tracing
* **Vendor Lock-in**: Difficult to migrate

**FlexBase Implementation:**

* **Warm Start**: <100ms response time
* **Cost**: $12,000/month
* **Debugging**: Simple centralized logging
* **Cloud Agnostic**: Easy to migrate

**Result: 52% cost savings + better performance**\*

#### **Financial Services (500K Users)**

**Serverless Implementation:**

* **Execution Time Limit**: 15 minutes max
* **Cold Start Issues**: Poor user experience
* **Vendor Lock-in**: High switching costs
* **Limited Control**: Restricted customization

**FlexBase Implementation:**

* **No Time Limits**: Handle complex transactions
* **Warm Starts**: Consistent performance
* **Cloud Agnostic**: Easy to switch providers
* **Full Control**: Complete customization

**Result: Better performance + lower costs + more flexibility**\*

### **Migration Strategy: From Serverless to FlexBase**

#### **Phase 1: Assessment**

```bash
# Analyze current serverless costs and performance
aws lambda get-function --function-name your-function
aws cloudwatch get-metric-statistics --namespace AWS/Lambda
```

#### **Phase 2: FlexBase Setup**

```yaml
# Deploy FlexBase endpoints
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flexbase-endpoint
spec:
  replicas: 3
  selector:
    matchLabels:
      app: flexbase-endpoint
  template:
    spec:
      containers:
      - name: flexbase
        image: your-flexbase-app:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
```

#### **Phase 3: Gradual Migration**

```yaml
# Use canary deployment for gradual migration
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: flexbase-rollout
spec:
  replicas: 5
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {duration: 10m}
      - setWeight: 40
      - pause: {duration: 10m}
      - setWeight: 60
      - pause: {duration: 10m}
      - setWeight: 80
      - pause: {duration: 10m}
```

#### **Phase 4: Full Migration**

```yaml
# Complete migration to FlexBase
apiVersion: v1
kind: Service
metadata:
  name: flexbase-service
spec:
  selector:
    app: flexbase-endpoint
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer
```

### **The FlexBase Advantage: Why Choose FlexBase Over Serverless**

#### **1. Performance**

* **No Cold Starts**: Always warm and ready
* **Consistent Performance**: Predictable response times
* **Better Throughput**: Handle more concurrent requests
* **Lower Latency**: Faster response times

#### **2. Cost**

* **Predictable Pricing**: No surprise bills
* **Lower Costs**: 40-60% cost savings at scale
* **Resource Optimization**: Use only what you need
* **Transparent Pricing**: Clear understanding of costs

#### **3. Flexibility**

* **No Vendor Lock-in**: Run anywhere
* **Full Control**: Customize everything
* **No Time Limits**: Handle complex processes
* **Easy Debugging**: Simple troubleshooting

#### **4. Scalability**

* **Infinite Scale**: Scale to millions of users
* **Auto-Scaling**: Scale based on demand
* **Global Distribution**: Deploy worldwide
* **Load Balancing**: Intelligent traffic distribution

## Scaling Strategies by Component

#### **Horizontal Scaling**

```yaml
# Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapi-endpoint
spec:
  replicas: 10  # Scale from 1 to 10+ instances
  selector:
    matchLabels:
      app: webapi-endpoint
  template:
    spec:
      containers:
      - name: webapi
        image: your-app:latest
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
```

#### **Auto-Scaling Configuration**

```yaml
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: webapi-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: webapi-endpoint
  minReplicas: 2
  maxReplicas: 50
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
```

### **Handler Endpoint Scaling**

#### **Message-Driven Scaling**

```csharp
// Handlers automatically scale based on message queue depth
public class OrderProcessingHandler : IOrderProcessingHandler
{
    public virtual async Task Execute(ProcessOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // This handler can run on 1 instance or 100 instances
        // Scaling is automatic based on message queue depth
        await ProcessOrder(cmd);
    }
}
```

#### **Serverless Scaling**

```csharp
// Azure Functions - Automatic scaling based on message count
[FunctionName("ProcessOrder")]
public static async Task Run(
    [ServiceBusTrigger("order-queue", Connection = "ServiceBusConnection")] 
    ProcessOrderCommand command,
    ILogger log)
{
    // Automatically scales from 0 to 1000+ instances
    await ProcessOrder(command);
}
```

### **Database Scaling**

#### **Read Replica Scaling**

```sql
-- Read replicas automatically handle read queries
-- Write queries go to primary database
-- Read queries are distributed across replicas

-- Primary Database (Writes)
INSERT INTO Orders (CustomerId, TotalAmount) VALUES (@CustomerId, @TotalAmount);

-- Read Replica (Queries)
SELECT * FROM Orders WHERE CustomerId = @CustomerId;
```

#### **Sharding Strategy**

```csharp
// Sharding based on customer ID
public class OrderRepository
{
    public async Task<Order> GetOrderById(string orderId, string customerId)
    {
        var shardKey = GetShardKey(customerId);
        var connectionString = GetConnectionString(shardKey);
        
        // Route to appropriate database shard
        return await QueryOrder(connectionString, orderId);
    }
}
```

## Monitoring and Observability

### **Scaling Metrics**

#### **Performance Metrics**

* **Response Time**: API response times across all endpoints
* **Throughput**: Requests per second, messages per second
* **Error Rate**: Failed requests, dead letter queue depth
* **Resource Utilization**: CPU, memory, disk usage

#### **Business Metrics**

* **User Activity**: Active users, session duration
* **Transaction Volume**: Orders per minute, revenue per hour
* **System Health**: Database connections, queue depths

### **Scaling Alerts**

```yaml
# Prometheus Alert Rules
groups:
- name: scaling
  rules:
  - alert: HighCPUUsage
    expr: cpu_usage_percent > 80
    for: 5m
    annotations:
      summary: "High CPU usage detected"
      description: "CPU usage is above 80% for 5 minutes"
      
  - alert: HighQueueDepth
    expr: message_queue_depth > 1000
    for: 2m
    annotations:
      summary: "High message queue depth"
      description: "Message queue has more than 1000 pending messages"
```

## Cost Optimization Strategies

### **Right-Sizing Resources**

#### **Development Environment**

* **WebAPI**: 1 instance, 1 CPU, 1GB RAM
* **Handlers**: 1 instance, 1 CPU, 512MB RAM
* **Database**: Single instance, 2 CPU, 4GB RAM
* **Message Queue**: Single instance, 1 CPU, 1GB RAM
* **Total Cost**: \~$100/month\*

#### **Production Environment**

* **WebAPI**: 5 instances, 2 CPU, 4GB RAM each
* **Handlers**: 3 instances, 2 CPU, 2GB RAM each
* **Database**: Primary + 2 replicas, 4 CPU, 16GB RAM each
* **Message Queue**: Cluster, 3 instances, 2 CPU, 4GB RAM each
* **Total Cost**: \~$2,000/month\*

#### **Enterprise Environment**

* **WebAPI**: 20 instances, 4 CPU, 8GB RAM each
* **Handlers**: 10 instances, 4 CPU, 4GB RAM each
* **Database**: Multi-region, 8 CPU, 32GB RAM each
* **Message Queue**: Multi-cloud, 5 instances, 4 CPU, 8GB RAM each
* **Total Cost**: \~$10,000/month\*

### **Auto-Scaling Benefits**

1. **Cost Efficiency**: Scale up during peak hours, scale down during off-peak
2. **Performance**: Maintain consistent performance during traffic spikes
3. **Reliability**: Handle unexpected load without manual intervention
4. **Resource Optimization**: Use only the resources you need

## Migration Strategies

### **Zero-Downtime Scaling**

#### **Blue-Green Deployment**

```
Phase 1: Deploy new version alongside old version
Phase 2: Route traffic to new version gradually
Phase 3: Monitor performance and rollback if needed
Phase 4: Decommission old version
```

#### **Canary Deployment**

```
Phase 1: Deploy new version to 5% of traffic
Phase 2: Monitor metrics and gradually increase to 25%
Phase 3: Continue monitoring and increase to 50%
Phase 4: Full deployment to 100% of traffic
```

### **Database Migration**

#### **Read Replica Migration**

```
Phase 1: Create read replica
Phase 2: Update read queries to use replica
Phase 3: Monitor performance
Phase 4: Scale read replicas as needed
```

#### **Database Sharding**

```
Phase 1: Implement sharding logic
Phase 2: Migrate data to sharded databases
Phase 3: Update connection strings
Phase 4: Monitor and optimize shard distribution
```

## Best Practices for Scaling

### **1. Start Simple, Scale Gradually**

* Begin with single-server deployment
* Add complexity only when needed
* Monitor performance at each phase
* Plan for future scaling requirements

### **2. Configuration-Driven Architecture**

* Use configuration files for all scaling parameters
* Implement feature flags for gradual rollouts
* Use environment-specific configurations
* Document all configuration changes

### **3. Monitor Everything**

* Implement comprehensive logging
* Set up performance monitoring
* Create alerting for critical metrics
* Regular performance reviews

### **4. Test Scaling Scenarios**

* Load test at each scaling phase
* Test failure scenarios and recovery
* Validate backup and restore procedures
* Document scaling procedures

### **5. Plan for Failure**

* Implement circuit breakers
* Design for graceful degradation
* Plan for disaster recovery
* Regular backup testing

## FlexBase + Cloud Platforms: The Ultimate Scaling Combination

### **Why Clouds Alone Aren't Enough**

While cloud platforms provide the infrastructure for scalability, they don't solve the **application architecture challenges** that prevent true scalability. Most applications fail to scale not because of infrastructure limitations, but because of **architectural bottlenecks** in the code itself.

#### **Common Cloud Scaling Failures**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Cloud Scale   │    │  App Bottleneck │    │   Real Scale    │
│   (Available)   │    │   (Limitation)  │    │   (Achieved)    │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ ✅ Auto-Scale   │    │ ❌ Monolithic   │    │ ✅ Microservices│
│ ✅ Load Balance │    │ ❌ Shared State │    │ ✅ Stateless    │
│ ✅ Multi-Region │    │ ❌ Tight Coupling│    │ ✅ Loose Coupling│
│ ✅ Managed DB   │    │ ❌ Single DB    │    │ ✅ CQRS        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

**The Problem**: Cloud infrastructure scales, but your application doesn't.

### **How FlexBase Maximizes Cloud Potential**

#### **1. Cloud-Native Architecture from Day One**

**Traditional Approach:**

```csharp
// Monolithic controller - doesn't scale well
public class OrdersController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    private readonly IEmailService _emailService;
    private readonly IInventoryService _inventoryService;
    
    [HttpPost]
    public async Task<IActionResult> CreateOrder(OrderDto order)
    {
        // Everything in one place - scaling bottleneck
        using var transaction = _context.Database.BeginTransaction();
        try
        {
            var orderEntity = new Order(order);
            _context.Orders.Add(orderEntity);
            await _inventoryService.ReserveInventory(order.Items);
            await _emailService.SendConfirmation(order.CustomerEmail);
            await _context.SaveChangesAsync();
            await transaction.CommitAsync();
            return Ok(orderEntity.Id);
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}
```

**FlexBase Approach:**

```csharp
// Scalable endpoint architecture
public class OrdersController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> CreateOrder(OrderDto order)
    {
        // Immediate response, processing happens asynchronously
        return await RunService(201, order, _processOrdersService.CreateOrder);
    }
}

// Separate handler for processing
public class CreateOrderHandler : ICreateOrderHandler
{
    public async Task Execute(CreateOrderCommand cmd, IFlexServiceBusContext context)
    {
        // Scalable, independent processing
        await ProcessOrder(cmd);
        await this.Fire(EventCondition, context); // Trigger other services
    }
}
```

**Cloud Benefits Maximized:**

* **Auto-Scaling**: Each endpoint scales independently
* **Load Balancing**: Stateless design works perfectly with load balancers
* **Multi-Region**: Endpoints can be deployed across regions
* **Fault Tolerance**: Failure in one endpoint doesn't affect others

#### **2. Cloud Database Optimization**

**Traditional Approach:**

```csharp
// Single database for everything
public class OrderService
{
    public async Task<Order> GetOrderWithDetails(int orderId)
    {
        // Complex query joining multiple tables
        return await _context.Orders
            .Include(o => o.Customer)
            .Include(o => o.Items)
            .ThenInclude(i => i.Product)
            .Include(o => o.Payment)
            .FirstOrDefaultAsync(o => o.Id == orderId);
    }
}
```

**FlexBase CQRS Approach:**

```csharp
// Optimized read database
public class GetOrderByIdQuery : FlexiQueryBridge<Order, GetOrderByIdDto>
{
    public override GetOrderByIdDto Fetch()
    {
        // Denormalized, optimized for reads
        return Build<Order>().SelectTo<GetOrderByIdDto>().FirstOrDefault();
    }
}

// Separate write database
public class CreateOrderHandler : ICreateOrderHandler
{
    public async Task Execute(CreateOrderCommand cmd, IFlexServiceBusContext context)
    {
        // Optimized for writes
        _model = _flexHost.GetDomainModel<Order>().CreateOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        await _repoFactory.GetRepo().SaveAsync();
    }
}
```

**Cloud Database Benefits:**

* **Read Replicas**: Automatic scaling of read operations
* **Write Optimization**: Primary database optimized for transactions
* **Cost Optimization**: Use appropriate database types for each workload
* **Global Distribution**: Read replicas in multiple regions

#### **3. Cloud Message Queue Integration**

**Traditional Approach:**

```csharp
// Synchronous processing - blocks scaling
public class OrderController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> ProcessOrder(OrderDto order)
    {
        // Synchronous processing blocks the request
        await _inventoryService.ReserveInventory(order.Items);
        await _paymentService.ProcessPayment(order.Payment);
        await _shippingService.CalculateShipping(order);
        await _emailService.SendConfirmation(order);
        
        return Ok();
    }
}
```

**FlexBase Message Queue Approach:**

```csharp
// Asynchronous processing - enables scaling
public class OrderController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> ProcessOrder(OrderDto order)
    {
        // Immediate response, processing happens asynchronously
        var command = new ProcessOrderCommand { Order = order };
        await _messageBus.Send(command);
        return Accepted();
    }
}

// Separate handlers for each concern
public class ReserveInventoryHandler : IReserveInventoryHandler
{
    public async Task Execute(ReserveInventoryCommand cmd, IFlexServiceBusContext context)
    {
        await _inventoryService.ReserveInventory(cmd.Items);
        await this.Fire(EventCondition, context);
    }
}
```

**Cloud Message Queue Benefits:**

* **Reliability**: Messages persisted and retried on failure
* **Scalability**: Multiple handlers process messages in parallel
* **Decoupling**: Services can scale independently
* **Event Sourcing**: Complete audit trail of all changes

### **Cloud Platform-Specific Optimizations**

#### **AWS Optimization with FlexBase**

**Amazon EKS + FlexBase:**

```yaml
# EKS Cluster with FlexBase
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flexbase-webapi
spec:
  replicas: 10
  selector:
    matchLabels:
      app: flexbase-webapi
  template:
    spec:
      containers:
      - name: flexbase
        image: your-flexbase-app:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        env:
        - name: AWS_REGION
          value: "us-west-2"
        - name: RDS_ENDPOINT
          valueFrom:
            secretKeyRef:
              name: rds-secret
              key: endpoint
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: flexbase-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: flexbase-webapi
  minReplicas: 5
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
```

**AWS Benefits Maximized:**

* **EKS Auto-Scaling**: Automatic scaling based on demand
* **RDS Read Replicas**: Automatic read scaling
* **SQS/SNS**: Reliable message processing
* **CloudWatch**: Comprehensive monitoring
* **ALB**: Intelligent load balancing

#### **Azure Optimization with FlexBase**

**Azure AKS + FlexBase:**

```yaml
# AKS Cluster with FlexBase
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flexbase-webapi
spec:
  replicas: 10
  selector:
    matchLabels:
      app: flexbase-webapi
  template:
    spec:
      containers:
      - name: flexbase
        image: your-flexbase-app:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        env:
        - name: AZURE_REGION
          value: "West US 2"
        - name: SQL_SERVER_ENDPOINT
          valueFrom:
            secretKeyRef:
              name: sql-secret
              key: endpoint
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: flexbase-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: flexbase-webapi
  minReplicas: 5
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
```

**Azure Benefits Maximized:**

* **AKS Auto-Scaling**: Automatic scaling based on demand
* **Azure SQL Read Replicas**: Automatic read scaling
* **Service Bus**: Reliable message processing
* **Application Insights**: Comprehensive monitoring
* **Application Gateway**: Intelligent load balancing

#### **Google Cloud Optimization with FlexBase**

**GKE + FlexBase:**

```yaml
# GKE Cluster with FlexBase
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flexbase-webapi
spec:
  replicas: 10
  selector:
    matchLabels:
      app: flexbase-webapi
  template:
    spec:
      containers:
      - name: flexbase
        image: your-flexbase-app:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        env:
        - name: GCP_REGION
          value: "us-central1"
        - name: CLOUD_SQL_INSTANCE
          valueFrom:
            secretKeyRef:
              name: cloudsql-secret
              key: instance
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: flexbase-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: flexbase-webapi
  minReplicas: 5
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
```

**Google Cloud Benefits Maximized:**

* **GKE Auto-Scaling**: Automatic scaling based on demand
* **Cloud SQL Read Replicas**: Automatic read scaling
* **Pub/Sub**: Reliable message processing
* **Cloud Monitoring**: Comprehensive monitoring
* **Cloud Load Balancing**: Intelligent load balancing

### **Why Choose FlexBase Over Other Solutions**

#### **1. FlexBase vs Traditional Microservices**

| Aspect               | Traditional Microservices                   | FlexBase                           | Winner      |
| -------------------- | ------------------------------------------- | ---------------------------------- | ----------- |
| **Setup Complexity** | High (service discovery, config management) | Low (built-in)                     | 🏆 FlexBase |
| **Communication**    | HTTP calls, complex error handling          | Message queues, automatic retry    | 🏆 FlexBase |
| **Data Consistency** | Complex distributed transactions            | Event-driven, eventual consistency | 🏆 FlexBase |
| **Monitoring**       | Multiple tools, complex setup               | Built-in, centralized              | 🏆 FlexBase |
| **Scaling**          | Manual configuration                        | Automatic, configuration-driven    | 🏆 FlexBase |

#### **2. FlexBase vs Serverless Functions**

| Aspect             | Serverless Functions | FlexBase  | Winner      |
| ------------------ | -------------------- | --------- | ----------- |
| **Cold Starts**    | 1-5 seconds          | <100ms    | 🏆 FlexBase |
| **Execution Time** | 15 minutes max       | Unlimited | 🏆 FlexBase |
| **Vendor Lock-in** | High                 | None      | 🏆 FlexBase |
| **Debugging**      | Complex              | Simple    | 🏆 FlexBase |
| **Cost at Scale**  | High                 | Low       | 🏆 FlexBase |

#### **3. FlexBase vs Container Orchestration**

| Aspect                | Raw Kubernetes       | FlexBase          | Winner      |
| --------------------- | -------------------- | ----------------- | ----------- |
| **Application Logic** | You build everything | Built-in patterns | 🏆 FlexBase |
| **Message Handling**  | You implement        | Built-in          | 🏆 FlexBase |
| **Database Patterns** | You design           | CQRS built-in     | 🏆 FlexBase |
| **Event Sourcing**    | You implement        | Built-in          | 🏆 FlexBase |
| **Monitoring**        | You configure        | Built-in          | 🏆 FlexBase |

### **Real-World Cloud Scaling Examples**

#### **E-Commerce Platform on AWS**

**Without FlexBase:**

* **Setup Time**: 6 months
* **Infrastructure Cost**: $15,000/month
* **Scaling Issues**: Database bottlenecks, synchronous processing
* **Maintenance**: High (custom microservices)

**With FlexBase:**

* **Setup Time**: 2 months
* **Infrastructure Cost**: $8,000/month
* **Scaling**: Automatic, no bottlenecks
* **Maintenance**: Low (managed patterns)

**Result: 47% cost savings + 3x faster setup**\*

#### **Financial Services on Azure**

**Without FlexBase:**

* **Compliance**: Complex audit trails
* **Scalability**: Limited by monolithic design
* **Cost**: $25,000/month
* **Reliability**: Single points of failure

**With FlexBase:**

* **Compliance**: Built-in event sourcing
* **Scalability**: Unlimited horizontal scaling
* **Cost**: $12,000/month
* **Reliability**: Fault-tolerant design

**Result: 52% cost savings + better compliance**\*

#### **SaaS Platform on Google Cloud**

**Without FlexBase:**

* **Multi-tenancy**: Complex tenant isolation
* **Scaling**: Manual configuration
* **Cost**: $30,000/month
* **Development**: 12 months

**With FlexBase:**

* **Multi-tenancy**: Built-in tenant support
* **Scaling**: Automatic configuration
* **Cost**: $18,000/month
* **Development**: 4 months

**Result: 40% cost savings + 3x faster development**\*

### **The FlexBase Cloud Advantage**

#### **1. Cloud-Native by Design**

* **Container-Ready**: Built for Kubernetes from the ground up
* **Auto-Scaling**: Leverages cloud auto-scaling capabilities
* **Load Balancing**: Works seamlessly with cloud load balancers
* **Multi-Region**: Designed for global deployment

#### **2. Cloud Service Integration**

* **Managed Databases**: Optimized for cloud database services
* **Message Queues**: Integrates with cloud messaging services
* **Monitoring**: Works with cloud monitoring solutions
* **Security**: Leverages cloud security services

#### **3. Cost Optimization**

* **Resource Efficiency**: Uses cloud resources optimally
* **Auto-Scaling**: Scales down during low usage
* **Right-Sizing**: Uses appropriate instance types
* **Reserved Instances**: Can leverage cloud cost optimizations

#### **4. Operational Excellence**

* **Zero-Downtime Deployments**: Rolling updates without interruption
* **Health Checks**: Built-in health monitoring
* **Graceful Shutdown**: Proper handling of scaling events
* **Disaster Recovery**: Built-in backup and recovery patterns

### **Migration Benefits: From Any Platform to FlexBase**

#### **From Monoliths**

* **Gradual Migration**: Move endpoints one by one
* **Risk Reduction**: Test each endpoint independently
* **Immediate Benefits**: Start seeing benefits immediately
* **Cost Savings**: Reduce infrastructure costs gradually

#### **From Microservices**

* **Simplification**: Reduce complexity of service communication
* **Standardization**: Use consistent patterns across services
* **Monitoring**: Centralized monitoring and logging
* **Maintenance**: Reduce operational overhead

#### **From Serverless**

* **Performance**: Eliminate cold start penalties
* **Cost**: Reduce costs at scale
* **Flexibility**: Remove execution time limits
* **Control**: Gain full control over infrastructure

## The FlexBase Advantage

### **Why FlexBase Scales Better**

1. **Endpoint Architecture**: Natural microservices boundaries
2. **CQRS Pattern**: Independent scaling of read and write operations
3. **Message Queues**: Reliable, scalable asynchronous processing
4. **Configuration-Driven**: Scale without code changes
5. **Cloud-Native**: Built for modern cloud environments
6. **Event-Driven**: Loose coupling enables independent scaling
7. **Cloud Optimization**: Maximizes cloud platform potential
8. **Cost Efficiency**: 40-60% cost savings compared to alternatives\*

\*Note: All costs mentioned in this document are illustrative examples for comparison purposes. Actual costs may vary significantly based on specific requirements, cloud provider pricing, geographic location, usage patterns, and other factors.

### **Real-World Success Stories**

#### **E-Commerce Platform**

* **Started**: 100 users, $100/month\*
* **Scaled**: 1M+ users, $25,000/month\*
* **Time**: 18 months
* **Code Changes**: Zero business logic changes

#### **Financial Services**

* **Started**: 100 users, $200/month\*
* **Scaled**: 500K+ users, $15,000/month\*
* **Time**: 12 months
* **Code Changes**: Zero business logic changes

#### **SaaS Platform**

* **Started**: 50 users, $50/month\*
* **Scaled**: 2M+ users, $50,000/month\*
* **Time**: 24 months
* **Code Changes**: Zero business logic changes

## Conclusion

FlexBase transforms the scaling challenge from a **code problem** into a **configuration problem**. You can start with 100 users and scale to millions without rewriting business logic, without architectural overhauls, and without months of refactoring.

**The secret**: Endpoint architecture + CQRS + Message queues + Configuration-driven scaling = **Infinite scalability without code changes**.

Start small, scale big, and let FlexBase handle the complexity while you focus on your business.

***

**Ready to build applications that scale? Start with FlexBase and watch your application grow from 100 users to millions without breaking a sweat!** 🚀


# Modular Monolith / Microservices

## Overview

FlexBase provides a unique approach to application architecture that starts with a **modular monolith** by default and can seamlessly evolve into **true microservices** when needed. This evolutionary architecture pattern allows you to start simple and scale to enterprise levels without the complexity of microservices from day one.

## The Evolution Path

```
Phase 1: Modular Monolith    →    Phase 2: Distributed Monolith    →    Phase 3: True Microservices
     (Single Application)              (Shared Database)                    (Independent Services)
```

**FlexBase Philosophy**: Start with a modular monolith, evolve to microservices when business requirements demand it.

## Modular Monolith: The FlexBase Default

### **What is a Modular Monolith?**

A modular monolith is a single application that is internally organized into **loosely coupled modules**. Each module has clear boundaries and can be developed, tested, and deployed independently, but they all run within the same process.

#### **FlexBase Modular Monolith Structure**

```
┌─────────────────────────────────────────────────────────────────┐
│                    FlexBase Modular Monolith                    │
├─────────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────┐ │
│  │   ECommerce │  │   Payment   │  │   Shipping  │  │  User   │ │
│  │   Module    │  │   Module    │  │   Module    │  │ Module  │ │
│  ├─────────────┤  ├─────────────┤  ├─────────────┤  ├─────────┤ │
│  │ • Orders    │  │ • Payments  │  │ • Shipments │  │ • Users │ │
│  │ • Products  │  │ • Refunds   │  │ • Tracking  │  │ • Auth  │ │
│  │ • Inventory │  │ • Billing   │  │ • Logistics │  │ • Roles │ │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────┘ │
├─────────────────────────────────────────────────────────────────┤
│                    Shared Database Layer                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────┐ │
│  │   Orders    │  │  Payments   │  │  Shipments  │  │  Users  │ │
│  │   Tables    │  │   Tables    │  │   Tables    │  │ Tables  │ │
│  └─────────────┘  └─────────────┘  └─────────────┘  └─────────┘ │
└─────────────────────────────────────────────────────────────────┘
```

### **FlexBase Modular Monolith Benefits**

#### **1. Clear Module Boundaries**

```csharp
// ECommerce Module
namespace EBusiness.Modules.ECommerce
{
    public class OrdersController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> CreateOrder(OrderDto order)
        {
            return await RunService(201, order, _processOrdersService.CreateOrder);
        }
    }
}

// Payment Module
namespace EBusiness.Modules.Payment
{
    public class PaymentsController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> ProcessPayment(PaymentDto payment)
        {
            return await RunService(200, payment, _processPaymentsService.ProcessPayment);
        }
    }
}
```

#### **2. Independent Module Development**

* **Separate Teams**: Each module can be developed by different teams
* **Independent Testing**: Test each module in isolation
* **Module-Specific Dependencies**: Each module manages its own dependencies
* **Clear Interfaces**: Well-defined contracts between modules

#### **3. Shared Infrastructure**

* **Single Database**: All modules share the same database
* **Shared Message Bus**: Common message queue for inter-module communication
* **Unified Monitoring**: Single monitoring and logging system
* **Common Configuration**: Shared configuration management

### **FlexBase Module Communication Patterns**

#### **1. Synchronous Communication (Within Monolith)**

```csharp
// Direct service calls within the same application
public class OrderService
{
    private readonly IPaymentService _paymentService;
    private readonly IInventoryService _inventoryService;

    public async Task<Order> CreateOrder(OrderDto order)
    {
        // Synchronous calls within the same process
        await _inventoryService.ReserveInventory(order.Items);
        var payment = await _paymentService.ProcessPayment(order.Payment);
        
        return await SaveOrder(order, payment);
    }
}
```

#### **2. Asynchronous Communication (Event-Driven)**

```csharp
// Event-driven communication between modules
public class OrderCreatedHandler : IOrderCreatedHandler
{
    public async Task Execute(OrderCreatedEvent @event, IFlexServiceBusContext context)
    {
        // Fire events to other modules
        await this.Fire<InventoryReservationCommand>(EventCondition, context);
        await this.Fire<PaymentProcessingCommand>(EventCondition, context);
        await this.Fire<ShippingNotificationCommand>(EventCondition, context);
    }
}
```

### **Modular Monolith Advantages**

#### **1. Development Simplicity**

* **Single Deployment**: Deploy one application
* **Shared Dependencies**: Common libraries and frameworks
* **Unified Testing**: Test the entire application together
* **Simple Debugging**: Single process to debug

#### **2. Performance Benefits**

* **No Network Overhead**: Direct method calls
* **Shared Memory**: Efficient data sharing
* **Single Database Connection**: Reduced connection overhead
* **Fast Communication**: In-process communication

#### **3. Operational Simplicity**

* **Single Monitoring**: One application to monitor
* **Unified Logging**: All logs in one place
* **Simple Deployment**: One deployment pipeline
* **Easy Rollback**: Single application rollback

## True Microservices: The Next Evolution

### **When to Evolve to Microservices**

#### **Business Triggers**

* **Team Growth**: Multiple teams need independent deployment
* **Technology Diversity**: Different modules need different technologies
* **Scaling Requirements**: Different modules have different scaling needs
* **Geographic Distribution**: Modules need to be deployed in different regions

#### **Technical Triggers**

* **Database Bottlenecks**: Single database becomes a bottleneck
* **Deployment Conflicts**: Teams block each other during deployments
* **Technology Constraints**: Different modules need different tech stacks
* **Performance Isolation**: Need to isolate performance issues

### **FlexBase Microservices Architecture**

#### **True Microservices Structure**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  ECommerce      │    │  Payment        │    │  Shipping       │    │  User           │
│  Microservice   │    │  Microservice   │    │  Microservice   │    │  Microservice   │
├─────────────────┤    ├─────────────────┤    ├─────────────────┤    ├─────────────────┤
│ • Orders API    │    │ • Payments API  │    │ • Shipping API  │    │ • Users API     │
│ • Products API  │    │ • Billing API   │    │ • Tracking API  │    │ • Auth API      │
│ • Inventory API │    │ • Refunds API   │    │ • Logistics API │    │ • Roles API     │
└─────────────────┘    └─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │                       │
         ▼                       ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  ECommerce DB   │    │  Payment DB     │    │  Shipping DB    │    │  User DB        │
│  (Independent)  │    │  (Independent)  │    │  (Independent)  │    │  (Independent)  │
└─────────────────┘    └─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │                       │
         └───────────────────────┼───────────────────────┼───────────────────────┘
                                 │                       │
                                 ▼                       ▼
                    ┌─────────────────┐    ┌─────────────────┐
                    │  Message Bus    │    │  API Gateway    │
                    │  (Events)       │    │  (Routing)      │
                    └─────────────────┘    └─────────────────┘
```

### **FlexBase Microservices Implementation**

Each microservice is a **completely independent FlexBase application** with its own:

* **Database**: Independent database schema and data
* **Message Bus**: Own message queue configuration
* **Endpoints**: Separate WebAPI, Handlers, and Subscribers
* **Configuration**: Independent appsettings and environment configs
* **Deployment**: Independent deployment pipeline
* **Scaling**: Independent scaling configuration

#### **1. ECommerce Microservice - Independent FlexBase Application**

**Project Structure:**

```
ECommerce.Service/
├── ECommerce.EndPoint.WebAPI/          # WebAPI Endpoint
├── ECommerce.EndPoint.Handlers/        # Command Handlers
├── ECommerce.EndPoint.Subscribers/     # Event Subscribers
├── ECommerce.Domain/                   # Domain Models
├── ECommerce.Application/              # Application Services
└── ECommerce.Infrastructure/           # Database & Message Bus
```

**WebAPI Endpoint:**

```csharp
// ECommerce Microservice - Independent FlexBase Application
namespace ECommerce.Service.EndPoint.WebAPI
{
    public class OrdersController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> CreateOrder(OrderDto order)
        {
            // Process order using FlexBase patterns
            return await RunService(201, order, _processOrdersService.CreateOrder);
        }
        
        [HttpGet]
        public async Task<IActionResult> GetOrder(string orderId)
        {
            return await RunService(200, new GetOrderDto { Id = orderId }, _queryOrdersService.GetOrderById);
        }
    }
}
```

**Command Handler:**

```csharp
// ECommerce Command Handler - Independent Processing
public class CreateOrderHandler : ICreateOrderHandler
{
    public async Task Execute(CreateOrderCommand cmd, IFlexServiceBusContext context)
    {
        // Process order in ECommerce service
        _model = _flexHost.GetDomainModel<Order>().CreateOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        await _repoFactory.GetRepo().SaveAsync();
        
        // Publish event to other microservices
        await this.Fire<OrderCreatedEvent>(EventCondition, context);
    }
}
```

**Configuration:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=localhost;Initial Catalog=ECommerceDb;...",
    "AppReadDbConnection": "Data Source=localhost;Initial Catalog=ECommerceReadDb;...",
    "RabbitMqConnectionString": "amqp://localhost:5672/ecommerce"
  }
}
```

#### **2. Payment Microservice - Independent FlexBase Application**

**Project Structure:**

```
Payment.Service/
├── Payment.EndPoint.WebAPI/            # WebAPI Endpoint
├── Payment.EndPoint.Handlers/          # Command Handlers
├── Payment.EndPoint.Subscribers/       # Event Subscribers
├── Payment.Domain/                     # Domain Models
├── Payment.Application/                # Application Services
└── Payment.Infrastructure/             # Database & Message Bus
```

**WebAPI Endpoint:**

```csharp
// Payment Microservice - Independent FlexBase Application
namespace Payment.Service.EndPoint.WebAPI
{
    public class PaymentsController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> ProcessPayment(PaymentDto payment)
        {
            // Process payment using FlexBase patterns
            return await RunService(200, payment, _processPaymentsService.ProcessPayment);
        }
        
        [HttpGet]
        public async Task<IActionResult> GetPayment(string paymentId)
        {
            return await RunService(200, new GetPaymentDto { Id = paymentId }, _queryPaymentsService.GetPaymentById);
        }
    }
}
```

**Event Subscriber:**

```csharp
// Payment Event Subscriber - Reacts to ECommerce Events
public class OrderCreatedHandler : IOrderCreatedHandler
{
    public async Task Execute(OrderCreatedEvent @event, IFlexServiceBusContext context)
    {
        // Process payment for the order
        var paymentCommand = new ProcessPaymentCommand
        {
            OrderId = @event.OrderId,
            Amount = @event.TotalAmount,
            CustomerId = @event.CustomerId
        };
        
        await _processPaymentsService.ProcessPayment(paymentCommand);
    }
}
```

**Configuration:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=localhost;Initial Catalog=PaymentDb;...",
    "AppReadDbConnection": "Data Source=localhost;Initial Catalog=PaymentReadDb;...",
    "RabbitMqConnectionString": "amqp://localhost:5672/payment"
  }
}
```

#### **3. Shipping Microservice - Independent FlexBase Application**

**Project Structure:**

```
Shipping.Service/
├── Shipping.EndPoint.WebAPI/           # WebAPI Endpoint
├── Shipping.EndPoint.Handlers/         # Command Handlers
├── Shipping.EndPoint.Subscribers/      # Event Subscribers
├── Shipping.Domain/                    # Domain Models
├── Shipping.Application/               # Application Services
└── Shipping.Infrastructure/            # Database & Message Bus
```

**WebAPI Endpoint:**

```csharp
// Shipping Microservice - Independent FlexBase Application
namespace Shipping.Service.EndPoint.WebAPI
{
    public class ShipmentsController : ControllerBase
    {
        [HttpPost]
        public async Task<IActionResult> CreateShipment(ShipmentDto shipment)
        {
            // Process shipment using FlexBase patterns
            return await RunService(201, shipment, _processShipmentsService.CreateShipment);
        }
        
        [HttpGet]
        public async Task<IActionResult> TrackShipment(string trackingNumber)
        {
            return await RunService(200, new TrackShipmentDto { TrackingNumber = trackingNumber }, _queryShipmentsService.TrackShipment);
        }
    }
}
```

**Event Subscriber:**

```csharp
// Shipping Event Subscriber - Reacts to Payment Events
public class PaymentProcessedHandler : IPaymentProcessedHandler
{
    public async Task Execute(PaymentProcessedEvent @event, IFlexServiceBusContext context)
    {
        if (@event.Status == PaymentStatus.Success)
        {
            // Create shipment for paid order
            var shipmentCommand = new CreateShipmentCommand
            {
                OrderId = @event.OrderId,
                CustomerId = @event.CustomerId,
                Items = @event.Items
            };
            
            await _processShipmentsService.CreateShipment(shipmentCommand);
        }
    }
}
```

**Configuration:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=localhost;Initial Catalog=ShippingDb;...",
    "AppReadDbConnection": "Data Source=localhost;Initial Catalog=ShippingReadDb;...",
    "RabbitMqConnectionString": "amqp://localhost:5672/shipping"
  }
}
```

#### **3. Event-Driven Communication**

```csharp
// ECommerce Microservice - Event Handler
public class PaymentProcessedHandler : IPaymentProcessedHandler
{
    public async Task Execute(PaymentProcessedEvent @event, IFlexServiceBusContext context)
    {
        // Update order status based on payment
        if (@event.Status == PaymentStatus.Success)
        {
            await _orderService.UpdateOrderStatus(@event.OrderId, OrderStatus.Paid);
            await this.Fire<OrderPaidEvent>(EventCondition, context);
        }
        else
        {
            await _orderService.UpdateOrderStatus(@event.OrderId, OrderStatus.PaymentFailed);
            await this.Fire<OrderPaymentFailedEvent>(EventCondition, context);
        }
    }
}
```

## Microservices Aggregator: Consolidating Services for Clients

### **The Aggregator Pattern**

When you have multiple independent FlexBase microservices, you need an **Aggregator Service** to consolidate data and provide a unified API for client applications. The aggregator acts as a **composite service** that orchestrates calls to multiple microservices and combines their responses.

#### **Aggregator Architecture**

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Client App    │    │   Mobile App    │    │   Web App       │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         └───────────────────────┼───────────────────────┘
                                 │
                    ┌─────────────────┐
                    │   Aggregator    │
                    │   Service       │
                    │  (FlexBase)     │
                    └─────────────────┘
                                 │
         ┌───────────────────────┼───────────────────────┐
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  ECommerce      │    │  Payment        │    │  Shipping       │
│  Microservice   │    │  Microservice   │    │  Microservice   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

### **FlexBase Aggregator Service Implementation**

#### **Aggregator Project Structure**

```
Aggregator.Service/
├── Aggregator.EndPoint.WebAPI/         # WebAPI Endpoint
├── Aggregator.EndPoint.Handlers/       # Command Handlers
├── Aggregator.EndPoint.Subscribers/    # Event Subscribers
├── Aggregator.Application/             # Aggregation Services
├── Aggregator.Infrastructure/          # HTTP Clients & Configuration
└── Aggregator.Shared/                  # Shared DTOs & Models
```

#### **Aggregator Controller - Unified API**

```csharp
// Aggregator Service - Consolidates Multiple Microservices
namespace Aggregator.Service.EndPoint.WebAPI
{
    [ApiController]
    [Route("api/[controller]")]
    public class OrdersController : ControllerBase
    {
        private readonly IOrderAggregationService _orderAggregationService;

        [HttpPost]
        public async Task<IActionResult> CreateOrder(CreateOrderRequest request)
        {
            // Orchestrate order creation across multiple services
            var result = await _orderAggregationService.CreateOrderAsync(request);
            return Ok(result);
        }

        [HttpGet("{orderId}")]
        public async Task<IActionResult> GetOrderDetails(string orderId)
        {
            // Aggregate data from multiple services
            var orderDetails = await _orderAggregationService.GetOrderDetailsAsync(orderId);
            return Ok(orderDetails);
        }

        [HttpGet("{orderId}/status")]
        public async Task<IActionResult> GetOrderStatus(string orderId)
        {
            // Get comprehensive order status
            var status = await _orderAggregationService.GetOrderStatusAsync(orderId);
            return Ok(status);
        }
    }
}
```

#### **Order Aggregation Service**

```csharp
// Order Aggregation Service - Orchestrates Multiple Microservices
public class OrderAggregationService : IOrderAggregationService
{
    private readonly IECommerceServiceClient _ecommerceClient;
    private readonly IPaymentServiceClient _paymentClient;
    private readonly IShippingServiceClient _shippingClient;

    public async Task<OrderDetailsResponse> GetOrderDetailsAsync(string orderId)
    {
        // Parallel calls to multiple microservices
        var orderTask = _ecommerceClient.GetOrderAsync(orderId);
        var paymentTask = _paymentClient.GetPaymentByOrderIdAsync(orderId);
        var shipmentTask = _shippingClient.GetShipmentByOrderIdAsync(orderId);

        await Task.WhenAll(orderTask, paymentTask, shipmentTask);

        // Aggregate responses
        return new OrderDetailsResponse
        {
            Order = await orderTask,
            Payment = await paymentTask,
            Shipment = await shipmentTask,
            Status = DetermineOverallStatus(await orderTask, await paymentTask, await shipmentTask)
        };
    }

    public async Task<CreateOrderResponse> CreateOrderAsync(CreateOrderRequest request)
    {
        // Step 1: Create order in ECommerce service
        var orderResult = await _ecommerceClient.CreateOrderAsync(new CreateOrderDto
        {
            CustomerId = request.CustomerId,
            Items = request.Items,
            TotalAmount = request.TotalAmount
        });

        // Step 2: Process payment
        var paymentResult = await _paymentClient.ProcessPaymentAsync(new ProcessPaymentDto
        {
            OrderId = orderResult.OrderId,
            Amount = orderResult.TotalAmount,
            PaymentMethod = request.PaymentMethod
        });

        // Step 3: Create shipment if payment successful
        ShipmentDto shipmentResult = null;
        if (paymentResult.Status == PaymentStatus.Success)
        {
            shipmentResult = await _shippingClient.CreateShipmentAsync(new CreateShipmentDto
            {
                OrderId = orderResult.OrderId,
                CustomerId = request.CustomerId,
                Items = request.Items
            });
        }

        return new CreateOrderResponse
        {
            OrderId = orderResult.OrderId,
            PaymentId = paymentResult.PaymentId,
            ShipmentId = shipmentResult?.ShipmentId,
            Status = DetermineOrderStatus(orderResult, paymentResult, shipmentResult)
        };
    }
}
```

#### **HTTP Client Services**

```csharp
// ECommerce Service Client
public class ECommerceServiceClient : IECommerceServiceClient
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<ECommerceServiceClient> _logger;

    public async Task<OrderDto> GetOrderAsync(string orderId)
    {
        var response = await _httpClient.GetAsync($"/api/orders/{orderId}");
        response.EnsureSuccessStatusCode();
        
        var content = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<OrderDto>(content);
    }

    public async Task<CreateOrderResponse> CreateOrderAsync(CreateOrderDto order)
    {
        var json = JsonSerializer.Serialize(order);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        
        var response = await _httpClient.PostAsync("/api/orders", content);
        response.EnsureSuccessStatusCode();
        
        var responseContent = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<CreateOrderResponse>(responseContent);
    }
}

// Payment Service Client
public class PaymentServiceClient : IPaymentServiceClient
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<PaymentServiceClient> _logger;

    public async Task<PaymentDto> GetPaymentByOrderIdAsync(string orderId)
    {
        var response = await _httpClient.GetAsync($"/api/payments/order/{orderId}");
        response.EnsureSuccessStatusCode();
        
        var content = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<PaymentDto>(content);
    }

    public async Task<ProcessPaymentResponse> ProcessPaymentAsync(ProcessPaymentDto payment)
    {
        var json = JsonSerializer.Serialize(payment);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        
        var response = await _httpClient.PostAsync("/api/payments", content);
        response.EnsureSuccessStatusCode();
        
        var responseContent = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<ProcessPaymentResponse>(responseContent);
    }
}
```

#### **Aggregator Configuration**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=localhost;Initial Catalog=AggregatorDb;...",
    "AppReadDbConnection": "Data Source=localhost;Initial Catalog=AggregatorReadDb;...",
    "RabbitMqConnectionString": "amqp://localhost:5672/aggregator"
  },
  "Microservices": {
    "ECommerce": {
      "BaseUrl": "https://ecommerce-service.yourcompany.com",
      "ApiKey": "your-ecommerce-api-key",
      "Timeout": "00:00:30"
    },
    "Payment": {
      "BaseUrl": "https://payment-service.yourcompany.com",
      "ApiKey": "your-payment-api-key",
      "Timeout": "00:00:30"
    },
    "Shipping": {
      "BaseUrl": "https://shipping-service.yourcompany.com",
      "ApiKey": "your-shipping-api-key",
      "Timeout": "00:00:30"
    }
  }
}
```

#### **HTTP Client Registration**

```csharp
// Program.cs - Register HTTP Clients
public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // Register HTTP clients for microservices
        builder.Services.AddHttpClient<IECommerceServiceClient, ECommerceServiceClient>(client =>
        {
            var config = builder.Configuration.GetSection("Microservices:ECommerce");
            client.BaseAddress = new Uri(config["BaseUrl"]);
            client.DefaultRequestHeaders.Add("X-API-Key", config["ApiKey"]);
            client.Timeout = TimeSpan.Parse(config["Timeout"]);
        });

        builder.Services.AddHttpClient<IPaymentServiceClient, PaymentServiceClient>(client =>
        {
            var config = builder.Configuration.GetSection("Microservices:Payment");
            client.BaseAddress = new Uri(config["BaseUrl"]);
            client.DefaultRequestHeaders.Add("X-API-Key", config["ApiKey"]);
            client.Timeout = TimeSpan.Parse(config["Timeout"]);
        });

        builder.Services.AddHttpClient<IShippingServiceClient, ShippingServiceClient>(client =>
        {
            var config = builder.Configuration.GetSection("Microservices:Shipping");
            client.BaseAddress = new Uri(config["BaseUrl"]);
            client.DefaultRequestHeaders.Add("X-API-Key", config["ApiKey"]);
            client.Timeout = TimeSpan.Parse(config["Timeout"]);
        });

        // Register aggregation services
        builder.Services.AddScoped<IOrderAggregationService, OrderAggregationService>();

        var app = builder.Build();
        app.Run();
    }
}
```

### **Aggregator Benefits**

#### **1. Unified API for Clients**

* **Single Endpoint**: Clients call one API instead of multiple microservices
* **Consistent Interface**: Standardized request/response format
* **Simplified Integration**: Easier for client applications to integrate

#### **2. Data Aggregation**

* **Combined Responses**: Merge data from multiple services
* **Business Logic**: Implement cross-service business rules
* **Data Transformation**: Convert service-specific data to client-friendly format

#### **3. Error Handling & Resilience**

* **Circuit Breaker**: Handle service failures gracefully
* **Retry Logic**: Retry failed calls with exponential backoff
* **Fallback Data**: Provide partial data when some services are unavailable

#### **4. Performance Optimization**

* **Parallel Calls**: Make concurrent calls to multiple services
* **Caching**: Cache frequently accessed data
* **Response Compression**: Compress responses for better performance

### **Microservices Communication Patterns**

#### **1. API Gateway Pattern**

```yaml
# API Gateway Configuration
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway
spec:
  rules:
  - host: api.yourcompany.com
    http:
      paths:
      - path: /api/orders
        pathType: Prefix
        backend:
          service:
            name: aggregator-service
            port:
              number: 80
      - path: /ecommerce
        pathType: Prefix
        backend:
          service:
            name: ecommerce-service
            port:
              number: 80
      - path: /payment
        pathType: Prefix
        backend:
          service:
            name: payment-service
            port:
              number: 80
      - path: /shipping
        pathType: Prefix
        backend:
          service:
            name: shipping-service
            port:
              number: 80
```

#### **2. Event-Driven Communication**

```csharp
// Event Bus Configuration
public class EventBusConfiguration
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddNServiceBus(cfg =>
        {
            cfg.Transport(transport =>
            {
                transport.UseRabbitMQ(connectionString: "amqp://localhost:5672");
            });
            
            cfg.Routing(routing =>
            {
                routing.RouteToEndpoint(typeof(OrderCreatedEvent), "ECommerce.Service");
                routing.RouteToEndpoint(typeof(PaymentProcessedEvent), "Payment.Service");
                routing.RouteToEndpoint(typeof(ShippingCreatedEvent), "Shipping.Service");
            });
        });
    }
}
```

#### **3. Database per Service**

```csharp
// Each microservice has its own database
public class ECommerceDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Inventory> Inventory { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(Configuration.GetConnectionString("ECommerceDb"));
    }
}

public class PaymentDbContext : DbContext
{
    public DbSet<Payment> Payments { get; set; }
    public DbSet<Refund> Refunds { get; set; }
    public DbSet<Billing> Billing { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(Configuration.GetConnectionString("PaymentDb"));
    }
}
```

### **Microservices Advantages**

#### **1. Independent Deployment**

* **Team Autonomy**: Each team can deploy independently
* **Technology Freedom**: Use different technologies per service
* **Scaling Independence**: Scale each service based on its needs
* **Fault Isolation**: Failure in one service doesn't affect others

#### **2. Technology Diversity**

```csharp
// ECommerce Service - .NET Core
public class OrdersController : ControllerBase { }

// Payment Service - Node.js
app.post('/api/payments', (req, res) => { });

// Shipping Service - Python
@app.route('/api/shipping', methods=['POST'])
def create_shipment(): pass
```

#### **3. Data Independence**

* **Database per Service**: Each service owns its data
* **Data Consistency**: Eventual consistency through events
* **Technology Choice**: Different databases per service
* **Independent Schema**: Evolve schemas independently

## Migration Strategy: From Modular Monolith to Microservices

### **Phase 1: Identify Service Boundaries**

#### **Domain Analysis**

```csharp
// Analyze existing modules for service boundaries
public class ServiceBoundaryAnalysis
{
    public List<ServiceCandidate> AnalyzeModules()
    {
        return new List<ServiceCandidate>
        {
            new ServiceCandidate
            {
                Name = "ECommerce",
                Modules = new[] { "Orders", "Products", "Inventory" },
                Dependencies = new[] { "Payment", "Shipping" },
                DataVolume = "High",
                ChangeFrequency = "High"
            },
            new ServiceCandidate
            {
                Name = "Payment",
                Modules = new[] { "Payments", "Refunds", "Billing" },
                Dependencies = new[] { "ECommerce" },
                DataVolume = "Medium",
                ChangeFrequency = "Low"
            }
        };
    }
}
```

### **Phase 2: Extract Services Gradually**

#### **Strangler Fig Pattern**

```csharp
// Gradually replace monolith functionality with microservices
public class OrderService
{
    private readonly IOrderService _legacyOrderService;
    private readonly IOrderService _newOrderService;
    private readonly bool _useNewService;

    public async Task<Order> CreateOrder(OrderDto order)
    {
        if (_useNewService)
        {
            return await _newOrderService.CreateOrder(order);
        }
        else
        {
            return await _legacyOrderService.CreateOrder(order);
        }
    }
}
```

### **Phase 3: Implement Event-Driven Communication**

#### **Event Sourcing Pattern**

```csharp
// Implement event sourcing for data consistency
public class OrderAggregate
{
    private readonly List<IDomainEvent> _events = new();
    
    public void CreateOrder(OrderDto order)
    {
        // Apply business logic
        var orderCreated = new OrderCreatedEvent
        {
            OrderId = Guid.NewGuid(),
            CustomerId = order.CustomerId,
            Items = order.Items
        };
        
        // Store event
        _events.Add(orderCreated);
    }
    
    public IEnumerable<IDomainEvent> GetUncommittedEvents()
    {
        return _events;
    }
}
```

## FlexBase: The Best of Both Worlds

### **Why FlexBase is Perfect for This Evolution**

#### **1. Built-in Modularity**

* **Endpoint Architecture**: Natural service boundaries
* **Event-Driven**: Ready for microservices communication
* **CQRS Pattern**: Independent read/write operations
* **Message Queues**: Built-in asynchronous communication

#### **2. Seamless Migration**

* **Same Code**: Business logic remains unchanged
* **Configuration-Driven**: Switch between monolith and microservices
* **Gradual Evolution**: Move modules to microservices one by one
* **Risk Mitigation**: Test each migration step independently

#### **3. Operational Excellence**

* **Unified Monitoring**: Same monitoring for both architectures
* **Consistent Patterns**: Same development patterns
* **Shared Infrastructure**: Leverage existing infrastructure
* **Team Training**: Minimal learning curve for teams

### **FlexBase Configuration for Architecture Evolution**

#### **Modular Monolith Configuration**

```json
{
  "FlexBase": {
    "Architecture": "ModularMonolith",
    "Database": {
      "Type": "Single",
      "ConnectionString": "Data Source=localhost;Initial Catalog=YourApp;..."
    },
    "MessageBus": {
      "Type": "InProcess",
      "Configuration": "Local"
    }
  }
}
```

#### **Microservices Configuration**

```json
{
  "FlexBase": {
    "Architecture": "Microservices",
    "Services": {
      "ECommerce": {
        "Database": "Data Source=localhost;Initial Catalog=ECommerceDb;...",
        "MessageBus": "amqp://localhost:5672"
      },
      "Payment": {
        "Database": "Data Source=localhost;Initial Catalog=PaymentDb;...",
        "MessageBus": "amqp://localhost:5672"
      }
    }
  }
}
```

## Real-World Examples

### **E-Commerce Platform Evolution**

#### **Phase 1: Modular Monolith (Startup)**

* **Team Size**: 5 developers
* **Deployment**: Single application
* **Database**: Single SQL Server
* **Communication**: Direct method calls
* **Cost**: $500/month

#### **Phase 2: Distributed Monolith (Growth)**

* **Team Size**: 15 developers
* **Deployment**: Single application with load balancing
* **Database**: Single database with read replicas
* **Communication**: Events + direct calls
* **Cost**: $2,000/month

#### **Phase 3: Microservices (Scale)**

* **Team Size**: 50+ developers
* **Deployment**: Independent services
* **Database**: Database per service
* **Communication**: Event-driven only
* **Cost**: $10,000/month

### **Financial Services Evolution**

#### **Modular Monolith Benefits**

* **Compliance**: Single audit trail
* **Security**: Unified security model
* **Development**: Fast feature development
* **Testing**: Comprehensive integration testing

#### **Microservices Benefits**

* **Regulatory**: Independent compliance per service
* **Security**: Isolated security per service
* **Scalability**: Scale payment processing independently
* **Technology**: Use specialized financial technologies

## Best Practices

### **1. Start with Modular Monolith**

* **Clear Boundaries**: Define module boundaries early
* **Event-Driven**: Use events from the beginning
* **Database Design**: Design for future service extraction
* **API Design**: Design APIs as if they were separate services

### **2. Plan for Microservices Evolution**

* **Service Identification**: Identify potential services early
* **Data Ownership**: Plan data ownership per service
* **Communication Patterns**: Use event-driven communication
* **Technology Choices**: Choose technologies that support both architectures

### **3. Migration Strategy**

* **Gradual Migration**: Move one module at a time
* **Feature Flags**: Use feature flags for gradual rollout
* **Testing**: Test each migration step thoroughly
* **Rollback Plan**: Always have a rollback strategy

### **4. Operational Considerations**

* **Monitoring**: Implement comprehensive monitoring
* **Logging**: Centralized logging across all services
* **Security**: Consistent security model
* **Deployment**: Automated deployment pipelines

## Conclusion

FlexBase provides the perfect foundation for both **modular monoliths** and **true microservices**. By starting with a modular monolith, you get the benefits of simplicity and performance while maintaining the flexibility to evolve to microservices when business requirements demand it.

**The FlexBase Advantage:**

* **Start Simple**: Begin with modular monolith
* **Evolve Naturally**: Move to microservices when needed
* **Same Code**: Business logic remains unchanged
* **Risk Mitigation**: Gradual, tested evolution
* **Best of Both Worlds**: Simplicity when you need it, scalability when you want it

***

**Ready to build applications that can evolve with your business? Start with FlexBase and let your architecture grow with your needs!** 🚀


# How Much Abstraction

## The Abstraction Dilemma: Finding the Sweet Spot

In enterprise application development, **abstraction is a double-edged sword**. Too little abstraction leads to tight coupling and technology lock-in. Too much abstraction creates unnecessary complexity and performance overhead. **FlexBase strikes the perfect balance** by abstracting only what matters while preserving full provider capabilities.

## 🎯 The FlexBase Philosophy: Strategic Abstraction

### **What We Abstract: Infrastructure Concerns Only**

FlexBase follows a **"Infrastructure Abstraction, Domain Preservation"** approach:

* ✅ **Abstract**: Database connections, message bus implementations, configuration management
* ❌ **Don't Abstract**: Domain logic, business rules, data models, query capabilities

### **What We Preserve: Full Provider Capabilities**

Unlike over-abstracted frameworks, FlexBase ensures developers retain **100% of the underlying technology's power**:

* **Entity Framework Core**: Full LINQ, raw SQL, migrations, change tracking
* **NServiceBus**: Complete messaging patterns, saga support, advanced routing
* **Database Providers**: Native features, performance optimizations, specific capabilities

## 🏗️ The Architecture: Minimal, Strategic Interfaces

### **Core Infrastructure Interfaces**

FlexBase uses **thin, focused interfaces** that abstract only infrastructure concerns:

```csharp
// Database Connection Abstraction
public interface IWriteDbConnectionProviderBridge : IWriteDbConnectionProvider<FlexAppContextBridge>
{
    // No business logic - just connection management
}

// Message Bus Abstraction  
public interface IFlexServiceBusBridge : IFlexServiceBus
{
    // No business logic - just messaging infrastructure
}

// Repository Abstraction
public interface IFlexRepositoryBridge : IFlexRepository
{
    // No business logic - just data access patterns
}
```

### **Implementation: Provider-Specific Bridges**

Each technology provider gets a **minimal bridge implementation**:

```csharp
// SQL Server Implementation
public class FlexWriteDbRepositoryEFSQLServer : FlexEFRepositoryBridge
{
    public override void InitializeConnection<TFlexHostContextInfo>(IConnectionProvider<TFlexHostContextInfo> connectionProvider)
    {
        var optionsBuilder = new DbContextOptionsBuilder<ApplicationEFSqlServerDbContext>();
        optionsBuilder.UseSqlServer(connectionProvider.ConnectionString);
        
        ApplicationEFSqlServerDbContext context = new ApplicationEFSqlServerDbContext(optionsBuilder.Options);
        InitializeDbContext(context);
    }
}

// MySQL Implementation
public class FlexWriteDbRepositoryEFMySql : FlexEFRepositoryBridge
{
    public override void InitializeConnection<TFlexHostContextInfo>(IConnectionProvider<TFlexHostContextInfo> connectionProvider)
    {
        var optionsBuilder = new DbContextOptionsBuilder<ApplicationEFMySqlDbContext>();
        optionsBuilder.UseMySql(connectionProvider.ConnectionString, ServerVersion.AutoDetect(connectionProvider.ConnectionString));
        
        ApplicationEFMySqlDbContext context = new ApplicationEFMySqlDbContext(optionsBuilder.Options);
        InitializeDbContext(context);
    }
}
```

## 💡 The Benefits: Best of Both Worlds

### **1. Technology Independence Without Capability Loss**

**Traditional Over-Abstraction Problem:**

```csharp
// Domain-centric generic repository - loses EF Core power
public interface IDomainEntityRepository<T>
{
    Task<T> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    // Missing: LINQ, raw SQL, complex queries, migrations
}
```

**FlexBase Approach:**

```csharp
// Strategic abstraction - keeps all EF Core and NServiceBus capabilities
public class OrderHandler
{
    public async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _repoFactory.Init(cmd.Dto);
        
        // Full EF Core power available
        var orders = _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.CustomerId == cmd.Dto.CustomerId)
            .FlexInclude("OrderItems")
            .OrderByDescending(o => o.OrderDate)
            .ToList();
            
                    
        // Full NServiceBus power available
        await serviceBusContext.ServiceBus.Publish(new OrderCreatedEvent
        {
            OrderId = cmd.Dto.Id,
            CustomerId = cmd.Dto.CustomerId
        });
        
        // Advanced messaging patterns
        await serviceBusContext.ServiceBus.Send(new ProcessPaymentCommand
        {
            OrderId = cmd.Dto.Id,
            Amount = orders.Sum(o => o.TotalAmount)
        }, new SendOptions
        {
            DelayDeliveryWith = TimeSpan.FromMinutes(5),
            SetMessageId(Guid.NewGuid().ToString())
        });
    }
}
```

### **2. Message Bus: Full NServiceBus Capabilities**

**Traditional Over-Abstraction Problem:**

```csharp
// Generic message bus - loses NServiceBus power
public interface IMessageBus
{
    Task PublishAsync<T>(T message);
    Task SendAsync<T>(T message);
    // Missing: Saga support, advanced routing, retry policies, monitoring
}
```

**FlexBase Strategic Abstraction:**

```csharp
// Infrastructure abstraction only - keeps all NServiceBus capabilities
public interface IFlexServiceBusBridge : IFlexServiceBus
{
    // Inherits all NServiceBus capabilities
}

// Business code uses full NServiceBus power
public class OrderHandler
{
    public async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Full NServiceBus capabilities available
        await serviceBusContext.ServiceBus.Publish(new OrderCreatedEvent
        {
            OrderId = cmd.Dto.Id,
            CustomerId = cmd.Dto.CustomerId
        });
        
        // Advanced messaging patterns
        await serviceBusContext.ServiceBus.Send(new ProcessPaymentCommand
        {
            OrderId = cmd.Dto.Id,
            Amount = cmd.Dto.TotalAmount
        }, new SendOptions
        {
            DelayDeliveryWith = TimeSpan.FromMinutes(5),
            SetMessageId(Guid.NewGuid().ToString()),
            SetHeader("Priority", "High")
        });
        
        // Saga support
        await serviceBusContext.ServiceBus.Send(new StartOrderSagaCommand
        {
            OrderId = cmd.Dto.Id
        }, new SendOptions
        {
            RouteToThisEndpoint()
        });
    }
}
```

### **3. Easy Technology Migration**

**Switching from SQL Server to MySQL:**

**Before (Over-Abstracted):**

* Change 50+ repository interfaces
* Rewrite all query logic
* Modify business rules
* Update domain models

**With FlexBase:**

```csharp
// 1. Change one line in Program.cs
services.AddScoped<IFlexRepositoryBridge, FlexWriteDbRepositoryEFMySql>();

// 2. That's it! All business code remains unchanged
```

**Switching from NServiceBus to RabbitMQ:**

**Before (Over-Abstracted):**

* Change 20+ message bus interfaces
* Rewrite all messaging logic
* Modify saga implementations
* Update routing configurations

**With FlexBase:**

```csharp
// 1. Change one line in Program.cs
services.AddScoped<IFlexServiceBusBridge, RabbitMqServiceBusBridge>();

// 2. That's it! All business code remains unchanged
```

### **3. Future-Proof Technology Evolution**

**When Entity Framework Core 9.0 releases:**

**Traditional Approach:**

* Rewrite all data access code
* Update business logic
* Modify domain models
* Extensive testing required

**FlexBase Approach:**

```csharp
// 1. Update the bridge implementation
public class FlexWriteDbRepositoryEFSQLServer : FlexEFRepositoryBridge
{
    public override void InitializeConnection<TFlexHostContextInfo>(IConnectionProvider<TFlexHostContextInfo> connectionProvider)
    {
        var optionsBuilder = new DbContextOptionsBuilder<ApplicationEFSqlServerDbContext>();
        optionsBuilder.UseSqlServer(connectionProvider.ConnectionString, 
            sqlOptions => sqlOptions.UseNewEF9Features()); // New features available immediately
        
        ApplicationEFSqlServerDbContext context = new ApplicationEFSqlServerDbContext(optionsBuilder.Options);
        InitializeDbContext(context);
    }
}

// 2. All business code automatically gets new capabilities
```

## 🔧 Real-World Example: Multi-Database Support

### **The Challenge: Supporting Multiple Databases**

**Traditional Over-Abstraction:**

```csharp
// Generic repository - loses database-specific features
public interface IOrderRepository
{
    Task<Order> GetByIdAsync(int id);
    Task SaveAsync(Order order);
    // Missing: SQL Server specific features, MySQL optimizations, PostgreSQL extensions
}
```

**FlexBase Strategic Abstraction:**

```csharp
// Infrastructure abstraction only
public interface IFlexRepositoryBridge : IFlexRepository
{
    // Inherits all EF Core capabilities
}

// Business code uses full EF Core power
public class OrderHandler
{
    public async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _repoFactory.Init(cmd.Dto);
        
        // Full database capabilities available
        var order = _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.Id == cmd.Dto.Id)
            .FlexInclude("OrderItems.Product")
            .FirstOrDefault();
            
    }
}
```

## 📊 The Impact: Measurable Benefits

### **Development Velocity**

| Aspect                  | Over-Abstracted          | FlexBase Strategic  |
| ----------------------- | ------------------------ | ------------------- |
| **Learning Curve**      | 6-12 months              | 2-4 weeks           |
| **Feature Development** | 2-3x slower              | Native speed        |
| **Debugging**           | Complex, multiple layers | Direct, transparent |
| **Performance**         | 20-40% overhead          | Native performance  |

### **Maintenance Overhead**

| Task                     | Over-Abstracted          | FlexBase Strategic    |
| ------------------------ | ------------------------ | --------------------- |
| **Technology Migration** | 3-6 months               | 1-2 days              |
| **Feature Addition**     | Rewrite abstractions     | Direct implementation |
| **Bug Fixes**            | Multiple layers to check | Single layer          |
| **Performance Tuning**   | Limited by abstractions  | Full provider control |

### **Technical Debt Reduction**

**Over-Abstracted Systems:**

* **Abstraction Layers**: 5-8 layers
* **Interface Count**: 50-100+ interfaces
* **Maintenance Cost**: 40-60% of development time
* **Technology Lock-in**: High (hard to change)

**FlexBase Systems:**

* **Abstraction Layers**: 2-3 layers
* **Interface Count**: 5-10 interfaces
* **Maintenance Cost**: 10-15% of development time
* **Technology Flexibility**: High (easy to change)

## 🚀 The FlexBase Advantage: Strategic Abstraction

### **1. Infrastructure Abstraction Only**

```csharp
// What we abstract - infrastructure concerns
public interface IWriteDbConnectionProviderBridge : IWriteDbConnectionProvider<FlexAppContextBridge>
{
    // Connection management only
}

// What we don't abstract - business capabilities
public class OrderHandler
{
    // Direct access to full EF Core power
    public async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _repoFactory.Init(cmd.Dto);
        
        // Full LINQ capabilities
        var orders = _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.CustomerId == cmd.Dto.CustomerId)
            .Include(o => o.OrderItems)
            .OrderByDescending(o => o.OrderDate)
            .ToList();
            
        // Raw SQL when needed
        var result = _repoFactory.GetRepo()
            .ExecuteRawSql("SELECT * FROM Orders WHERE CustomerId = @customerId", 
                          new SqlParameter("@customerId", cmd.Dto.CustomerId));
    }
}
```

### **2. Technology Evolution Without Business Code Changes**

```csharp
// When EF Core 9.0 releases with new features
public class FlexWriteDbRepositoryEFSQLServer : FlexEFRepositoryBridge
{
    public override void InitializeConnection<TFlexHostContextInfo>(IConnectionProvider<TFlexHostContextInfo> connectionProvider)
    {
        var optionsBuilder = new DbContextOptionsBuilder<ApplicationEFSqlServerDbContext>();
        optionsBuilder.UseSqlServer(connectionProvider.ConnectionString, 
            sqlOptions => sqlOptions.UseNewEF9Features()); // New features immediately available
        
        ApplicationEFSqlServerDbContext context = new ApplicationEFSqlServerDbContext(optionsBuilder.Options);
        InitializeDbContext(context);
    }
}

// All business code automatically gets new capabilities - no changes needed!
```

### **3. Easy Technology Migration**

```csharp
// Switching from SQL Server to MySQL
// Step 1: Change one line in Program.cs
services.AddScoped<IFlexRepositoryBridge, FlexWriteDbRepositoryEFMySql>();

// Step 2: That's it! All business code works unchanged
// Full MySQL capabilities available immediately
```

## 🎯 The Result: Perfect Balance

### **What You Get:**

✅ **Technology Independence**: Switch databases/message buses easily\
✅ **Full Provider Capabilities**: No feature loss from over-abstraction\
✅ **Future-Proof**: New technology versions work automatically\
✅ **Performance**: Native speed, no abstraction overhead\
✅ **Maintainability**: Minimal interfaces, clear responsibilities\
✅ **Developer Productivity**: Direct access to provider features

### **What You Avoid:**

❌ **Over-Abstraction**: Complex interfaces that hide capabilities\
❌ **Technology Lock-in**: Hard to migrate or upgrade\
❌ **Performance Overhead**: Multiple abstraction layers\
❌ **Maintenance Nightmare**: Too many interfaces to maintain\
❌ **Feature Limitations**: Generic abstractions that limit power

## 💡 The Key Insight: Abstract Infrastructure, Preserve Capabilities

**FlexBase's approach is simple but powerful:**

1. **Abstract only infrastructure concerns** (connections, configuration, messaging)
2. **Preserve full provider capabilities** (EF Core power, NServiceBus features)
3. **Enable easy technology migration** (change one line, not entire codebase)
4. **Future-proof your applications** (new technology versions work automatically)

**The result?** You get the benefits of abstraction without the costs. Your applications are flexible, maintainable, and performant - with full access to the underlying technology's power.

***

**Ready to experience the perfect balance of abstraction and capability?** Start building with FlexBase and see how strategic abstraction can transform your development experience! 🚀


# Flexbase and Azure Logic Apps Integration

### 🚀 Overview

FlexBase provides seamless integration with **Azure Logic Apps** through its REST client architecture, enabling enterprise applications to leverage Azure's powerful workflow automation capabilities. This integration allows developers to orchestrate complex business processes, integrate with external systems, and implement sophisticated workflows without writing complex integration code.

### 🏗️ Architecture Overview

#### **FlexBase REST Client Pattern**

FlexBase implements a clean, maintainable pattern for Azure Logic Apps integration:

```
┌─────────────────────────────────────┐
│ Controller Layer (API Endpoint)     │ ← REST API entry point
├─────────────────────────────────────┤
│ Handler Layer (Business Logic)      │ ← Command processing
├─────────────────────────────────────┤
│ REST Client Layer (Integration)     │ ← Azure Logic Apps communication
├─────────────────────────────────────┤
│ Azure Logic Apps (Workflow)         │ ← External workflow processing
└─────────────────────────────────────┘
```

#### **Key Components**

1. **Controller** - REST API endpoint for external access
2. **Handler** - Business logic orchestration and command processing
3. **REST Client** - Azure Logic Apps communication layer
4. **Azure Logic Apps** - External workflow processing and automation

### 🔧 Implementation Example: Logic App Basic Call

#### **1. Controller Layer - API Endpoint**

```csharp
// MiscsController_DemonstrateLogicAppCallBasic.cs
public partial class MiscsController : FlexControllerBridge<MiscsController>
{
    [HttpPost]
    [Route("DemonstrateLogicAppCallBasic")]
    [ProducesResponseType(typeof(BadRequestResult), 400)]
    [ProducesResponseType(typeof(string), 201)]
    public async Task<IActionResult> DemonstrateLogicAppCallBasic([FromBody]DemonstrateLogicAppCallBasicDto dto)
    {
        return await RunService(201, dto, _processMiscsService.DemonstrateLogicAppCallBasic);
    }
}
```

**Key Features:**

* **RESTful API** - Standard HTTP POST endpoint
* **Type Safety** - Strongly-typed DTO parameters
* **Error Handling** - Built-in HTTP status code management
* **FlexBase Integration** - Uses FlexControllerBridge for consistent behavior

#### **2. Handler Layer - Business Logic**

```csharp
// DemonstrateLogicAppCallBasicHandler.cs
public partial class DemonstrateLogicAppCallBasicHandler : IDemonstrateLogicAppCallBasicHandler
{
    protected readonly ILogger<DemonstrateLogicAppCallBasicHandler> _logger;
    protected readonly IFlexHost _flexHost;
    protected MiscsRESTClient _restClient;

    public virtual async Task Execute(DemonstrateLogicAppCallBasicCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Convert command to request parameters
        DemonstrateLogicAppCallBasicRequestDto requestParams = new DemonstrateLogicAppCallBasicRequestDto
        {
            // Map command data to request DTO
        };

        // Call Azure Logic App
        var response = await _restClient.DemonstrateLogicAppCallBasic(requestParams);

        // Process response
        var jsonContent = await response.Content.ReadAsStringAsync();
        _logger.LogInformation(jsonContent);

        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Key Features:**

* **Command Pattern** - Encapsulates business operations
* **Dependency Injection** - Clean dependency management
* **Error Handling** - Comprehensive logging and error management
* **Event Publishing** - Domain event integration

#### **3. REST Client Layer - Azure Integration**

```csharp
// MiscsRESTClient.cs
public partial class MiscsRESTClient : LogicAppDemonstrationRESTClientBase, IFlexRESTClientService
{
    public async Task<HttpResponseMessage> DemonstrateLogicAppCallBasic(DemonstrateLogicAppCallBasicRequestDto model)
    {
        var httpClient = _httpClientFactory.CreateClient(LogicAppDemonstrationRESTClientMaster.Name);

        var serializedModel = JsonConvert.SerializeObject(model);

        var request = new HttpRequestMessage(
            HttpMethod.Post,
            $"workflows/{workflowId}/triggers/When_a_HTTP_request_is_received/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2FWhen_a_HTTP_request_is_received%2Frun&sv=1.0&sig={signature}");
        
        request.Content = new StringContent(serializedModel, Encoding.UTF8, "application/json");
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

        return await response.HandleHttpResponse();
    }
}
```

**Key Features:**

* **HTTP Client Factory** - Managed HTTP client lifecycle
* **JSON Serialization** - Automatic object serialization
* **Authentication** - Built-in Azure Logic Apps authentication
* **Error Handling** - FlexBase HTTP response handling

### 🎯 Azure Logic Apps Integration Scenarios

#### **1. HTTP Request Trigger (Basic)**

**Use Case**: Simple workflow initiation via REST API call

```csharp
// Basic HTTP trigger scenario
public async Task<HttpResponseMessage> TriggerBasicWorkflow(WorkflowRequestDto request)
{
    var httpClient = _httpClientFactory.CreateClient("LogicAppClient");
    
    var request = new HttpRequestMessage(
        HttpMethod.Post,
        $"workflows/{workflowId}/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig={signature}");
    
    request.Content = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
    
    return await httpClient.SendAsync(request);
}
```

**Business Scenarios:**

* **Order Processing** - Trigger order fulfillment workflow
* **Document Generation** - Generate reports and documents
* **Notification Sending** - Send emails, SMS, or push notifications
* **Data Validation** - Validate and process incoming data

#### **2. Azure Storage Queue Trigger**

**Use Case**: Process messages from Azure Storage Queues

```csharp
// FlexBase Handler for Azure Storage Queue
public class StorageQueueHandler : IStorageQueueHandler
{
    private readonly QueueClient _queueClient;
    private readonly ILogger<StorageQueueHandler> _logger;
    
    public StorageQueueHandler(IConfiguration configuration, ILogger<StorageQueueHandler> logger)
    {
        var connectionString = configuration.GetConnectionString("StorageAccount");
        var queueName = configuration["StorageQueue:QueueName"];
        _queueClient = new QueueClient(connectionString, queueName);
        _logger = logger;
    }
    
    public async Task Execute(ProcessQueueMessageCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Send message to Azure Storage Queue
        // Logic App will automatically trigger when message arrives
        var message = new QueueMessageDto
        {
            MessageId = cmd.MessageId,
            Data = cmd.Data,
            Priority = cmd.Priority,
            Timestamp = DateTime.UtcNow
        };
        
        await _queueClient.SendMessageAsync(JsonConvert.SerializeObject(message));
        
        _logger.LogInformation($"Message sent to queue: {cmd.MessageId}");
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Business Scenarios:**

* **Batch Processing** - Process large volumes of data
* **Asynchronous Workflows** - Decouple processing from user requests
* **Retry Logic** - Handle failed operations with automatic retries
* **Load Balancing** - Distribute workload across multiple instances

#### **3. Event Grid Trigger**

**Use Case**: React to Azure Event Grid events

```csharp
// FlexBase Handler for Event Grid
public class EventGridHandler : IEventGridHandler
{
    private readonly EventGridPublisherClient _eventGridClient;
    private readonly ILogger<EventGridHandler> _logger;
    
    public EventGridHandler(IConfiguration configuration, ILogger<EventGridHandler> logger)
    {
        var eventGridEndpoint = configuration["EventGrid:Endpoint"];
        var eventGridKey = configuration["EventGrid:Key"];
        _eventGridClient = new EventGridPublisherClient(
            new Uri(eventGridEndpoint), 
            new AzureKeyCredential(eventGridKey));
        _logger = logger;
    }
    
    public async Task Execute(PublishEventCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var events = new List<EventGridEvent>
        {
            new EventGridEvent(cmd.Subject, cmd.EventType, "1.0", cmd.EventData)
        };
        
        await _eventGridClient.SendEventsAsync(events);
        
        _logger.LogInformation($"Event published: {cmd.EventType}");
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Business Scenarios:**

* **Real-time Processing** - React to system events immediately
* **Integration Events** - Communicate between microservices
* **Audit Logging** - Track system changes and user actions
* **Compliance** - Meet regulatory requirements with event tracking

#### **4. Azure Service Bus Trigger**

**Use Case**: Process messages from Azure Service Bus

```csharp
// FlexBase Handler for Azure Service Bus
public class ServiceBusHandler : IServiceBusHandler
{
    private readonly ServiceBusClient _serviceBusClient;
    private readonly ILogger<ServiceBusHandler> _logger;
    
    public ServiceBusHandler(IConfiguration configuration, ILogger<ServiceBusHandler> logger)
    {
        var connectionString = configuration.GetConnectionString("ServiceBus");
        var queueName = configuration["ServiceBus:QueueName"];
        _serviceBusClient = new ServiceBusClient(connectionString);
        _logger = logger;
    }
    
    public async Task Execute(SendServiceBusMessageCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var sender = _serviceBusClient.CreateSender(cmd.QueueName);
        
        var serviceBusMessage = new ServiceBusMessage(JsonConvert.SerializeObject(cmd.MessageData))
        {
            MessageId = cmd.MessageId,
            Subject = cmd.Subject,
            ContentType = "application/json"
        };
        
        await sender.SendMessageAsync(serviceBusMessage);
        
        _logger.LogInformation($"Message sent to Service Bus: {cmd.MessageId}");
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Business Scenarios:**

* **Enterprise Messaging** - Reliable message delivery
* **Transaction Processing** - Ensure message processing consistency
* **Dead Letter Handling** - Manage failed message processing
* **Topic Subscriptions** - Publish-subscribe messaging patterns

### 🔄 Advanced Integration Patterns

#### **1. Multi-Step Workflow Orchestration with FlexBase Handlers and Subscribers**

FlexBase provides a sophisticated event-driven architecture for complex workflows using **Handlers** and **Subscribers** that seamlessly integrate with **Azure Logic Apps** for business logic execution. This pattern ensures resilience, scalability, and maintainability while leveraging the full power of Azure Logic Apps.

**Example: Order Processing Workflow with Azure Logic Apps Integration**

> **💡 Key Insight**: Each step in the workflow calls Azure Logic Apps to execute complex business logic, while FlexBase handles the orchestration, resilience, and event flow. You get the best of both worlds - FlexBase's robust architecture and Azure Logic Apps' powerful workflow capabilities.

```csharp
// Step 1: Command Handler - Process Payment (Synchronous)
public class ProcessPaymentHandler : IProcessPaymentHandler
{
    private readonly ILogger<ProcessPaymentHandler> _logger;
    private readonly PaymentProcessingRESTClient _restClient;
    
    public ProcessPaymentHandler(ILogger<ProcessPaymentHandler> logger, PaymentProcessingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(ProcessPaymentCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Validate payment data
        if (!ValidatePaymentData(cmd.PaymentData))
        {
            throw new BusinessException("Invalid payment data");
        }
        
        // Process payment via Azure Logic Apps - Complex business logic executed in Logic Apps
        // Logic Apps handles: payment gateway selection, fraud detection, retry logic, compliance checks
        var response = await _restClient.ProcessPayment(cmd.PaymentData);
        
        if (response.IsSuccessStatusCode)
        {
            _logger.LogInformation($"Payment processed successfully for Order: {cmd.OrderId}");
            
            // Fire event to trigger next step - FlexBase handles the orchestration
            await this.Fire("PAYMENT_SUCCESS", serviceBusContext);
        }
        else
        {
            _logger.LogError($"Payment failed for Order: {cmd.OrderId}");
            await this.Fire("PAYMENT_FAILED", serviceBusContext);
        }
    }
}

// Step 2: Event Subscriber - Update Inventory (Asynchronous)
public class UpdateInventorySubscriber : IUpdateInventorySubscriber
{
    private readonly ILogger<UpdateInventorySubscriber> _logger;
    private readonly InventoryRESTClient _restClient;
    
    public UpdateInventorySubscriber(ILogger<UpdateInventorySubscriber> logger, InventoryRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(PaymentProcessedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _logger.LogInformation($"Updating inventory for Order: {@event.OrderId}");
        
        // Update inventory via Azure Logic Apps - Complex business logic executed in Logic Apps
        // Logic Apps handles: stock validation, allocation, reservation, low-stock alerts, supplier notifications
        var response = await _restClient.UpdateInventory(@event.OrderItems);
        
        if (response.IsSuccessStatusCode)
        {
            _logger.LogInformation($"Inventory updated successfully for Order: {@event.OrderId}");
            
            // Fire event to trigger next step - FlexBase handles the orchestration
            await this.Fire("INVENTORY_UPDATED", serviceBusContext);
        }
        else
        {
            _logger.LogError($"Inventory update failed for Order: {@event.OrderId}");
            await this.Fire("INVENTORY_UPDATE_FAILED", serviceBusContext);
        }
    }
}

// Step 3: Event Subscriber - Send Notifications (Asynchronous)
public class SendNotificationSubscriber : ISendNotificationSubscriber
{
    private readonly ILogger<SendNotificationSubscriber> _logger;
    private readonly NotificationRESTClient _restClient;
    
    public SendNotificationSubscriber(ILogger<SendNotificationSubscriber> logger, NotificationRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(InventoryUpdatedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _logger.LogInformation($"Sending notifications for Order: {@event.OrderId}");
        
        // Send notifications via Azure Logic Apps - Complex business logic executed in Logic Apps
        // Logic Apps handles: email template selection, personalization, multi-channel delivery, delivery tracking
        var response = await _restClient.SendOrderConfirmation(@event.OrderId, @event.CustomerEmail);
        
        if (response.IsSuccessStatusCode)
        {
            _logger.LogInformation($"Notifications sent successfully for Order: {@event.OrderId}");
        }
        else
        {
            _logger.LogError($"Notification sending failed for Order: {@event.OrderId}");
        }
    }
}
```

#### **2. Built-in Resilience in FlexBase Handlers**

FlexBase provides **built-in resilience** through NServiceBus integration, eliminating the need for custom retry logic:

**Automatic Retry Features:**

* **Exponential Backoff**: Automatic retry with increasing delays
* **Dead Letter Queue**: Failed messages moved to DLQ after max retries
* **Circuit Breaker**: Automatic circuit breaking on repeated failures
* **Message Durability**: Messages persisted until successfully processed
* **Idempotency**: Safe to retry operations without side effects

```csharp
// FlexBase handles resilience automatically - no custom retry code needed
public class ProcessPaymentHandler : IProcessPaymentHandler
{
    public async Task Execute(ProcessPaymentCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // FlexBase automatically handles:
        // - Retry on transient failures
        // - Exponential backoff
        // - Dead letter queue on permanent failures
        // - Message durability and ordering
        
        var response = await _restClient.ProcessPayment(cmd.PaymentData);
        
        // Business logic only - resilience is handled by FlexBase
        if (response.IsSuccessStatusCode)
        {
            await this.Fire("PAYMENT_SUCCESS", serviceBusContext);
        }
    }
}
```

#### **3. FlexBase + Azure Logic Apps: The Perfect Partnership**

**Why This Combination is Powerful:**

1. **FlexBase Handles**: Architecture, resilience, event orchestration, scaling, testing
2. **Azure Logic Apps Handles**: Complex business logic, integrations, visual workflows, connectors
3. **Result**: You get enterprise-grade architecture with powerful business logic execution

**What You Can Build with This Partnership:**

* **Complex Workflows**: Multi-step business processes with visual design
* **System Integrations**: Connect to 400+ services without custom code
* **Data Transformations**: Visual data mapping and transformation
* **Conditional Logic**: Branching workflows based on business rules
* **Error Handling**: Sophisticated retry and compensation logic
* **Monitoring**: Built-in workflow monitoring and analytics

#### **4. FlexBase Handler and Subscriber Pattern**

FlexBase implements a sophisticated **Command-Query-Event** pattern that provides clean separation of concerns and automatic resilience:

**Architecture Flow:**

```
┌─────────────────────────────────────────────────────────────────┐
│ 1. Command Handler (Synchronous)                               │
│    - ProcessPaymentHandler                                     │
│    - Validates data & calls Azure Logic Apps                   │
│    - Fires events on success/failure                          │
├─────────────────────────────────────────────────────────────────┤
│ 2. Event Subscribers (Asynchronous)                           │
│    - UpdateInventorySubscriber (triggered by PaymentProcessedEvent) │
│    - SendNotificationSubscriber (triggered by InventoryUpdatedEvent) │
│    - Each subscriber calls Azure Logic Apps independently     │
└─────────────────────────────────────────────────────────────────┘
```

**Key Benefits:**

1. **Separation of Concerns**: Each handler/subscriber has a single responsibility
2. **Automatic Resilience**: NServiceBus handles retries, dead letter queues, and circuit breakers
3. **Eventual Consistency**: Subscribers process events asynchronously
4. **Scalability**: Each component can be scaled independently
5. **Testability**: Each handler/subscriber can be tested in isolation
6. **Maintainability**: Easy to add/remove workflow steps

**Event Flow Example:**

```csharp
// 1. Command Handler fires event
await this.Fire("PAYMENT_SUCCESS", serviceBusContext);

// 2. Event automatically triggers subscribers
// - UpdateInventorySubscriber.Execute() is called
// - SendNotificationSubscriber.Execute() is called after inventory update

// 3. Each subscriber can fire its own events
await this.Fire("INVENTORY_UPDATED", serviceBusContext);
```

### 🚀 **The Power of FlexBase + Azure Logic Apps: Do Anything, Compromise Nothing**

**You Don't Have to Choose Between Architecture and Business Logic**

Many developers face a dilemma: use a robust enterprise framework (and lose flexibility) or use powerful business logic tools (and lose architectural benefits). With FlexBase + Azure Logic Apps, you get **both**.

#### **🎯 What This Means for You:**

**✅ Keep Your Azure Logic Apps Investment**

* **Visual Workflows**: Continue using the drag-and-drop designer
* **400+ Connectors**: Access all existing Logic Apps connectors
* **No Code Changes**: Your existing Logic Apps workflows work unchanged
* **Familiar Tools**: Use the Azure portal and Logic Apps designer

**✅ Get Enterprise Architecture Benefits**

* **Resilience**: Automatic retry, dead letter queues, circuit breakers
* **Scalability**: Scale handlers and subscribers independently
* **Testing**: Unit test each component in isolation
* **Monitoring**: Comprehensive logging and health checks
* **Security**: Built-in authentication and authorization

**✅ Build Anything You Can Imagine**

* **E-commerce**: Order processing, inventory management, payment flows
* **CRM Integration**: Lead management, customer onboarding, support workflows
* **Document Processing**: PDF generation, approval workflows, compliance
* **IoT**: Device data processing, alerting, automated responses
* **Financial**: Payment processing, fraud detection, reconciliation

#### **🔄 Real-World Example: E-commerce Order Processing**

```csharp
// Your existing Azure Logic Apps workflows remain unchanged
// FlexBase just orchestrates them with enterprise-grade reliability

// 1. Payment Processing Logic App
// - Handles multiple payment gateways
// - Fraud detection algorithms
// - Compliance checks
// - Retry logic for failed payments

// 2. Inventory Management Logic App  
// - Stock validation
// - Allocation algorithms
// - Supplier notifications
// - Low-stock alerts

// 3. Notification Logic App
// - Email template selection
// - Personalization engine
// - Multi-channel delivery
// - Delivery tracking

// FlexBase orchestrates these with:
// - Event-driven architecture
// - Automatic resilience
// - Independent scaling
// - Comprehensive monitoring
```

### 🛠️ FlexBase Integration Benefits

#### **1. Clean Architecture**

* **Separation of Concerns** - Clear boundaries between layers
* **Dependency Injection** - Easy testing and maintenance
* **Type Safety** - Compile-time validation throughout
* **Error Handling** - Consistent error management patterns

#### **2. Scalability**

* **Horizontal Scaling** - Stateless handlers can be scaled independently
* **Load Balancing** - Multiple instances can handle increased load
* **Async Processing** - Non-blocking operations for better performance
* **Resource Management** - Efficient HTTP client lifecycle management

#### **3. Maintainability**

* **Consistent Patterns** - Same structure across all integrations
* **Easy Testing** - Each layer can be tested independently
* **Configuration Management** - Centralized configuration for all integrations
* **Logging and Monitoring** - Built-in logging and monitoring capabilities

#### **4. Enterprise Features**

* **Authentication** - Built-in Azure authentication support
* **Security** - Secure communication with Azure services
* **Compliance** - Audit trails and compliance reporting
* **Monitoring** - Health checks and performance monitoring

### 🚀 Best Practices

#### **1. Error Handling**

```csharp
// Comprehensive error handling
public async Task<HttpResponseMessage> ExecuteWithErrorHandling<T>(T request)
{
    try
    {
        var response = await _restClient.ExecuteLogicApp(request);
        
        if (!response.IsSuccessStatusCode)
        {
            _logger.LogWarning($"Logic App returned {response.StatusCode}: {await response.Content.ReadAsStringAsync()}");
        }
        
        return response;
    }
    catch (HttpRequestException ex)
    {
        _logger.LogError(ex, "HTTP request failed");
        return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
    }
    catch (TaskCanceledException ex)
    {
        _logger.LogError(ex, "Request timeout");
        return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Unexpected error occurred");
        return new HttpResponseMessage(HttpStatusCode.InternalServerError);
    }
}
```

#### **2. Configuration Management**

```csharp
// Configuration-driven integration
public class LogicAppConfiguration
{
    public string BaseUrl { get; set; }
    public string WorkflowId { get; set; }
    public string Signature { get; set; }
    public int TimeoutSeconds { get; set; } = 30;
    public int MaxRetries { get; set; } = 3;
    public bool EnableLogging { get; set; } = true;
}
```

#### **3. Performance Optimization**

```csharp
// Performance-optimized HTTP client
public class OptimizedLogicAppClient
{
    private readonly HttpClient _httpClient;
    
    public OptimizedLogicAppClient(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("LogicAppClient");
        
        // Configure for optimal performance
        _httpClient.Timeout = TimeSpan.FromSeconds(30);
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "FlexBase-Client/1.0");
    }
    
    public async Task<HttpResponseMessage> ExecuteOptimized<T>(T request)
    {
        // Use connection pooling and keep-alive
        var response = await _httpClient.PostAsJsonAsync("workflows/execute", request);
        return response;
    }
}
```

### 🎯 Key Takeaways

#### **FlexBase + Azure Logic Apps = Powerful Integration**

1. **Clean Architecture** - Clear separation of concerns with FlexBase patterns
2. **Multiple Triggers** - Support for HTTP, Storage Queue, Event Grid, and Service Bus
3. **Enterprise Features** - Authentication, security, monitoring, and compliance
4. **Scalability** - Horizontal scaling and load balancing capabilities
5. **Maintainability** - Consistent patterns and easy testing

#### **Business Value**

* **Rapid Development** - Quick integration with Azure Logic Apps
* **Reliable Processing** - Robust error handling and retry logic
* **Cost Effective** - Pay-per-use Azure Logic Apps pricing
* **Future Proof** - Easy to extend and modify as requirements change

### 🔄 Common Azure Logic Apps Flow Examples

#### **1. Email Notification Flow**

**Business Scenario**: Send automated email notifications for order confirmations, password resets, or system alerts.

```csharp
// FlexBase Handler for Email Notification
public class EmailNotificationHandler : IEmailNotificationHandler
{
    private readonly ILogger<EmailNotificationHandler> _logger;
    private readonly EmailNotificationRESTClient _restClient;
    
    public EmailNotificationHandler(ILogger<EmailNotificationHandler> logger, EmailNotificationRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(SendEmailCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var emailRequest = new EmailNotificationRequestDto
        {
            To = cmd.RecipientEmail,
            Subject = cmd.Subject,
            Body = cmd.MessageBody,
            TemplateId = cmd.TemplateId
        };

        var response = await _restClient.SendEmailNotification(emailRequest);
        
        if (response.IsSuccessStatusCode)
        {
            _logger.LogInformation($"Email sent successfully to {cmd.RecipientEmail}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **HTTP Request Trigger** - Receive email request from FlexBase
2. **Condition** - Check if email template exists
3. **Get Template** - Retrieve email template from storage
4. **Send Email** - Send email via Office 365 or SendGrid
5. **Log Result** - Log success/failure to monitoring system

#### **2. Document Generation Flow**

**Business Scenario**: Generate PDF reports, invoices, or contracts automatically.

```csharp
// FlexBase Handler for Document Generation
public class DocumentGenerationHandler : IDocumentGenerationHandler
{
    private readonly ILogger<DocumentGenerationHandler> _logger;
    private readonly DocumentGenerationRESTClient _restClient;
    
    public DocumentGenerationHandler(ILogger<DocumentGenerationHandler> logger, DocumentGenerationRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(GenerateDocumentCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var documentRequest = new DocumentGenerationRequestDto
        {
            DocumentType = cmd.DocumentType,
            TemplateId = cmd.TemplateId,
            Data = cmd.DocumentData,
            OutputFormat = cmd.OutputFormat
        };

        var response = await _restClient.GenerateDocument(documentRequest);
        
        if (response.IsSuccessStatusCode)
        {
            var documentUrl = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"Document generated: {documentUrl}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **HTTP Request Trigger** - Receive document generation request
2. **Get Template** - Retrieve document template from Azure Storage
3. **Populate Template** - Fill template with provided data
4. **Generate PDF** - Convert to PDF using Azure Functions or third-party service
5. **Store Document** - Save to Azure Blob Storage
6. **Return URL** - Send document URL back to FlexBase

#### **3. Data Synchronization Flow**

**Business Scenario**: Sync data between different systems (CRM, ERP, external APIs).

```csharp
// FlexBase Handler for Data Synchronization
public class DataSyncHandler : IDataSyncHandler
{
    private readonly ILogger<DataSyncHandler> _logger;
    private readonly DataSyncRESTClient _restClient;
    
    public DataSyncHandler(ILogger<DataSyncHandler> logger, DataSyncRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(SyncDataCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var syncRequest = new DataSyncRequestDto
        {
            SourceSystem = cmd.SourceSystem,
            TargetSystem = cmd.TargetSystem,
            DataType = cmd.DataType,
            LastSyncDate = cmd.LastSyncDate
        };

        var response = await _restClient.SyncData(syncRequest);
        
        if (response.IsSuccessStatusCode)
        {
            var syncResult = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"Data sync completed: {syncResult}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **Recurrence Trigger** - Run every hour or daily
2. **Get Data** - Fetch data from source system (API, database)
3. **Transform Data** - Convert data format for target system
4. **Validate Data** - Check data integrity and business rules
5. **Send to Target** - Push data to target system
6. **Log Results** - Record sync statistics and errors

#### **4. Payment Processing Flow**

**Business Scenario**: Process payments through multiple payment gateways with fallback options.

```csharp
// FlexBase Handler for Payment Processing
public class PaymentProcessingHandler : IPaymentProcessingHandler
{
    private readonly ILogger<PaymentProcessingHandler> _logger;
    private readonly PaymentProcessingRESTClient _restClient;
    
    public PaymentProcessingHandler(ILogger<PaymentProcessingHandler> logger, PaymentProcessingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(ProcessPaymentCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var paymentRequest = new PaymentProcessingRequestDto
        {
            Amount = cmd.Amount,
            Currency = cmd.Currency,
            PaymentMethod = cmd.PaymentMethod,
            CustomerId = cmd.CustomerId,
            OrderId = cmd.OrderId
        };

        var response = await _restClient.ProcessPayment(paymentRequest);
        
        if (response.IsSuccessStatusCode)
        {
            var paymentResult = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"Payment processed: {paymentResult}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **HTTP Request Trigger** - Receive payment request
2. **Validate Payment** - Check payment details and business rules
3. **Try Primary Gateway** - Attempt payment with primary provider
4. **Condition** - Check if primary payment succeeded
5. **Try Secondary Gateway** - Fallback to secondary provider if needed
6. **Update Order Status** - Update order status in database
7. **Send Confirmation** - Send payment confirmation email

#### **5. File Processing Flow**

**Business Scenario**: Process uploaded files (images, documents, CSV files) with validation and transformation.

```csharp
// FlexBase Handler for File Processing
public class FileProcessingHandler : IFileProcessingHandler
{
    private readonly ILogger<FileProcessingHandler> _logger;
    private readonly FileProcessingRESTClient _restClient;
    
    public FileProcessingHandler(ILogger<FileProcessingHandler> logger, FileProcessingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(ProcessFileCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var fileRequest = new FileProcessingRequestDto
        {
            FileUrl = cmd.FileUrl,
            FileType = cmd.FileType,
            ProcessingOptions = cmd.ProcessingOptions,
            OutputFormat = cmd.OutputFormat
        };

        var response = await _restClient.ProcessFile(fileRequest);
        
        if (response.IsSuccessStatusCode)
        {
            var processingResult = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"File processed: {processingResult}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **HTTP Request Trigger** - Receive file processing request
2. **Download File** - Get file from Azure Blob Storage
3. **Validate File** - Check file format and size
4. **Process File** - Apply transformations (resize images, parse CSV, etc.)
5. **Store Processed File** - Save processed file to storage
6. **Update Database** - Record processing results
7. **Send Notification** - Notify user of completion

#### **6. Approval Workflow Flow**

**Business Scenario**: Implement approval workflows for expenses, leave requests, or document approvals.

```csharp
// FlexBase Handler for Approval Workflow
public class ApprovalWorkflowHandler : IApprovalWorkflowHandler
{
    private readonly ILogger<ApprovalWorkflowHandler> _logger;
    private readonly ApprovalWorkflowRESTClient _restClient;
    
    public ApprovalWorkflowHandler(ILogger<ApprovalWorkflowHandler> logger, ApprovalWorkflowRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(SubmitApprovalCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var approvalRequest = new ApprovalWorkflowRequestDto
        {
            RequestId = cmd.RequestId,
            RequestType = cmd.RequestType,
            RequesterId = cmd.RequesterId,
            ApproverId = cmd.ApproverId,
            RequestData = cmd.RequestData
        };

        var response = await _restClient.SubmitApproval(approvalRequest);
        
        if (response.IsSuccessStatusCode)
        {
            var approvalResult = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"Approval submitted: {approvalResult}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **HTTP Request Trigger** - Receive approval request
2. **Validate Request** - Check request data and business rules
3. **Send Approval Email** - Send approval request to approver
4. **Wait for Response** - Wait for approver decision (with timeout)
5. **Process Decision** - Handle approval or rejection
6. **Update Status** - Update request status in database
7. **Notify Requester** - Send notification to original requester

#### **7. Integration with External APIs Flow**

**Business Scenario**: Integrate with third-party services like weather APIs, shipping providers, or social media platforms.

```csharp
// FlexBase Handler for External API Integration
public class ExternalApiHandler : IExternalApiHandler
{
    private readonly ILogger<ExternalApiHandler> _logger;
    private readonly ExternalApiRESTClient _restClient;
    
    public ExternalApiHandler(ILogger<ExternalApiHandler> logger, ExternalApiRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }
    
    public async Task Execute(CallExternalApiCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        var apiRequest = new ExternalApiRequestDto
        {
            ApiEndpoint = cmd.ApiEndpoint,
            RequestData = cmd.RequestData,
            Authentication = cmd.Authentication,
            RetryCount = cmd.RetryCount
        };

        var response = await _restClient.CallExternalApi(apiRequest);
        
        if (response.IsSuccessStatusCode)
        {
            var apiResult = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"External API call successful: {apiResult}");
        }
        
        // Fire domain events if needed
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**Azure Logic Apps Flow:**

1. **HTTP Request Trigger** - Receive API call request
2. **Prepare Request** - Format request for external API
3. **Authenticate** - Handle API authentication (OAuth, API keys, etc.)
4. **Call External API** - Make HTTP request to external service
5. **Handle Response** - Process API response
6. **Transform Data** - Convert response to internal format
7. **Return Result** - Send processed data back to FlexBase

### 🎯 Flow Pattern Benefits

#### **1. Reliability**

* **Retry Logic** - Automatic retry on failures
* **Error Handling** - Comprehensive error management
* **Monitoring** - Built-in logging and monitoring
* **Fallback Options** - Alternative paths when primary fails

#### **2. Scalability**

* **Parallel Processing** - Handle multiple requests simultaneously
* **Load Balancing** - Distribute workload across instances
* **Auto-scaling** - Scale based on demand
* **Resource Management** - Efficient resource utilization

#### **3. Maintainability**

* **Visual Design** - Easy to understand and modify
* **Reusable Components** - Common patterns across workflows
* **Version Control** - Track changes and rollback if needed
* **Testing** - Built-in testing capabilities

#### **4. Integration**

* **Multiple Connectors** - Connect to hundreds of services
* **Custom Connectors** - Build custom integrations
* **API Management** - Secure and manage API calls
* **Data Transformation** - Easy data format conversion

***

*This document demonstrates how FlexBase provides a clean, maintainable, and scalable approach to integrating with Azure Logic Apps, enabling enterprise applications to leverage powerful workflow automation capabilities.*


# AI In Flexbase

## AI In Flexbase

## FlexBase AI-Powered Feature Component Generation

### Business Overview

#### What is AI Feature Generation?

FlexBase Studio leverages artificial intelligence to automatically generate the essential components needed for building business features. Instead of manually creating validation rules, domain events, and event subscribers, developers simply provide a feature name, and the AI intelligently generates a complete, production-ready feature structure.

#### The Business Challenge

Building enterprise applications requires developers to:

* **Design validation rules** that ensure data integrity and business compliance
* **Define domain events** that trigger downstream processes and notifications
* **Create event subscribers** that handle business workflows and integrations
* **Maintain consistency** across hundreds of features in large applications
* **Follow best practices** for domain-driven design and event-driven architecture

This process is:

* **Time-consuming**: Each feature requires careful analysis and manual configuration
* **Error-prone**: Missing validations or events can lead to data quality issues
* **Inconsistent**: Different developers may implement similar features differently
* **Knowledge-intensive**: Requires deep understanding of business rules and architectural patterns

#### How FlexBase Solves This

**1. Intelligent Feature Analysis (Currently Available)**

Simply enter a feature name (e.g., "CreateCustomer", "UpdateOrder", "ApproveInvoice"), and FlexBase AI:

* **Identifies the operation type** (Create, Update, Delete, Query, etc.)
* **Understands the business context** from the feature name
* **Applies domain-driven design principles** automatically

**2. Automatic Component Generation (Currently Available)**

The AI generates three critical components:

**Validation Rules**

* Business logic validations that ensure data quality
* Cross-field validations and complex business rules
* Automatically filters out simple validations that can be handled by standard attributes

**Domain Events**

* Success and failure events that trigger business processes
* Properly named events following naming conventions
* Context-aware event generation based on operation type

**Event Subscribers**

* Services that react to domain events
* Subscribers that can publish their own events (cascading workflows)
* Integration points for notifications, logging, and external systems

**3. Operation-Aware Intelligence (Currently Available)**

The AI understands different operation types and tailors suggestions accordingly:

* **Create Operations**: Generates validations for new data, creation events, and subscribers for new entity workflows
* **Update Operations**: Focuses on change validations, update events, and modification handlers
* **Delete Operations**: Includes deletion permissions, cleanup events, and cascade handlers
* **Query Operations**: Recognizes read-only operations and provides appropriate guidance

**🚀 Coming Soon: AI-Powered Requirements Translation**

**Note:** The following capability is currently in development and will be available in a future release.

FlexBase AI will bridge the gap between business requirements and technical implementation by:

**From Business Language to Technical Features**

* **Natural language input**: Business stakeholders describe needs in plain English
* **AI translation**: Converts business descriptions into properly structured feature names
* **Domain-driven design**: Automatically applies DDD principles and naming conventions

**Example Transformation:**

* **Business Input**: "We need to let customers add items to their shopping cart"
* **AI Output**: `AddItemToCart` (properly formatted, DDD-compliant feature name)

**Module and Feature Discovery**

* **Business domain analysis**: AI understands business domains and suggests relevant modules
* **Feature identification**: Automatically identifies all features needed for a business capability
* **Complete coverage**: Ensures no critical features are missed in the initial planning

#### Business Benefits

**⚡ Accelerated Development**

* **Reduce feature setup time by 70-80%**
* Generate complete feature structures in seconds instead of hours
* Focus development time on custom business logic, not boilerplate

**✅ Improved Quality**

* **Consistent implementation** across all features
* **Best practices built-in** - follows domain-driven design principles automatically
* **Reduced errors** - AI considers edge cases and business rules

**🎯 Enhanced Consistency**

* **Standardized naming conventions** across the entire application
* **Uniform architecture patterns** for all features
* **Predictable structure** that makes code easier to maintain

**💡 Knowledge Democratization**

* **No deep expertise required** - developers don't need to be DDD experts
* **Learning tool** - see how features should be structured
* **Onboarding accelerator** - new team members can be productive faster

**🔄 Two-Step Review Process**

1. **Review Phase**: See AI suggestions in plain English before committing
2. **Edit Phase**: Refine and customize the generated components as needed

This ensures developers maintain control while benefiting from AI assistance.

#### Real-World Impact

**Before FlexBase AI:**

* Developer spends 2-3 hours analyzing requirements
* Manually creates 5-10 validation rules
* Designs 3-5 domain events
* Configures 5-15 event subscribers
* Reviews and refines for consistency
* **Total: 4-6 hours per feature**

**With FlexBase AI:**

* Developer enters feature name
* Reviews AI-generated suggestions (5 minutes)
* Refines as needed (15-30 minutes)
* **Total: 20-35 minutes per feature**

**Result: 85-90% time savings on feature setup**

#### Complete Development Journey: From Business Requirements to Implementation

FlexBase AI currently supports **individual feature component generation**. Here's how it works with a real-world example:

**Real-World Example: Individual Feature Generation**

Let's see how FlexBase AI generates components for a single feature: **`CreateOrder`**

**Step 1: Developer Provides Feature Name** Developer enters: `CreateOrder`

**Step 2: AI Analyzes and Generates Components**

The AI analyzes the feature name and generates all necessary components automatically.

**Business Context:** When a customer places an order, we need to:

* Validate that the cart is not empty
* Verify product availability
* Check customer payment information
* Calculate total with taxes and shipping
* Create the order record
* Clear the shopping cart
* Send confirmation email
* Update inventory
* Trigger fulfillment process

**AI-Generated Components for `CreateOrder`:**

**Validations:**

1. **CartNotEmpty** - Ensures customer has items in cart before placing order
2. **ProductsInStock** - Verifies all cart items are available in inventory
3. **PaymentMethodValid** - Validates customer's payment method is active
4. **ShippingAddressComplete** - Ensures shipping address has all required fields
5. **OrderTotalCalculated** - Validates order total calculation is correct

**Domain Events:**

1. **OrderCreatedEvent** (OnSuccess)
   * Triggered when order is successfully created
   * Contains order details, customer information, and order total
2. **OrderCreationFailedEvent** (OnFailed)
   * Triggered when order creation fails
   * Contains failure reason and error details

**Event Subscribers:**

For **OrderCreatedEvent**:

1. **SendOrderConfirmation**
   * Sends email confirmation to customer
   * Publishes: `OrderConfirmationSentEvent` (OnSuccess)
2. **ClearShoppingCart**
   * Removes all items from customer's cart
   * Publishes: `CartClearedEvent` (OnSuccess)
3. **ReserveInventory**
   * Reserves products in inventory system
   * Publishes: `InventoryReservedEvent` (OnSuccess) or `InventoryReservationFailedEvent` (OnFailed)
4. **InitiatePaymentProcessing**
   * Sends order to payment gateway
   * Publishes: `PaymentInitiatedEvent` (OnSuccess) or `PaymentInitiationFailedEvent` (OnFailed)
5. **CreateFulfillmentOrder**
   * Creates order in warehouse management system
   * Publishes: `FulfillmentOrderCreatedEvent` (OnSuccess)

For **OrderCreationFailedEvent**:

1. **LogOrderFailure**
   * Logs failure for monitoring and debugging
   * Publishes: `OrderFailureLoggedEvent` (OnSuccess)

**Cascading Workflows:**

The AI also identifies cascading events:

* When `InventoryReservedEvent` is published, it triggers `NotifyWarehouse` subscriber
* When `PaymentInitiatedEvent` is published, it triggers `UpdateOrderPaymentStatus` subscriber
* When `FulfillmentOrderCreatedEvent` is published, it triggers `SendShippingNotification` subscriber

**Result:** From a single feature name `CreateOrder`, FlexBase AI generates:

* **5 validation rules** ensuring data integrity
* **2 domain events** for success and failure scenarios
* **6 event subscribers** handling all downstream processes
* **Multiple cascading workflows** for complete business process automation

**Time Savings:**

* **Manual approach**: 4-6 hours to design, document, and configure all components
* **With FlexBase AI**: 20-30 minutes to review and refine AI suggestions
* **Savings: 85-90% reduction in setup time**

***

#### 🚀 Coming Soon: AI Module and Feature Discovery

**Note:** The following capability is currently in development and will be available in a future release.

**Module and Feature Discovery from Business Requirements**

FlexBase AI will support translating business requirements into complete module structures and feature lists. This will enable:

**From Business Language to Technical Features**

**Example Scenario:** A business stakeholder says: *"We need an e-commerce platform where customers can browse products, add items to cart, place orders, and track shipments."*

**AI Module and Feature Discovery (Coming Soon):**

FlexBase AI will analyze this requirement and suggest the following structure:

**Module: Product Catalog**

* `GetProducts` (GETPAGEDLIST) - Browse products with pagination
* `GetProductById` (GETBYID) - View product details
* `GetProductsForLookup` (GETLIST) - Product dropdown for admin
* `GetCategoriesForLookup` (GETLIST) - Category selection

**Module: Shopping Cart**

* `AddItemToCart` (CREATE) - Add product to cart
* `UpdateCartItem` (UPDATE) - Update item quantity
* `RemoveCartItem` (DELETE) - Remove item from cart
* `GetCartItems` (GETLIST) - View cart contents
* `ClearCart` (DELETE) - Empty the cart

**Module: Order Management**

* `CreateOrder` (CREATE) - Place new order
* `GetOrders` (GETPAGEDLIST) - View order history
* `GetOrderById` (GETBYID) - View order details
* `CancelOrder` (SOFTDELETE) - Cancel an order
* `UpdateOrderStatus` (UPDATE) - Update order status

**Module: Shipping**

* `CreateShipment` (CREATE) - Create shipping record
* `UpdateShipmentStatus` (UPDATE) - Track shipment
* `GetShipmentByTrackingNumber` (GETSINGLE) - Track package

**How It Will Work:**

1. **Natural Language to Feature Names**
   * Business stakeholders describe features in plain English
   * AI converts descriptions to properly formatted, DDD-compliant feature names
   * Example: "Allow customers to place orders" → `CreateOrder`
2. **Module and Feature Discovery**
   * AI analyzes business domains and suggests complete module structures
   * Identifies all related features needed for a business capability
   * Ensures comprehensive coverage from the start

**Benefits (When Available):**

**1. Faster Requirements Translation**

* Convert business language to technical features in minutes
* No need for extensive technical documentation upfront
* Business stakeholders can validate features immediately

**2. Comprehensive Feature Discovery**

* AI suggests all related features for a business domain
* Reduces risk of missing critical functionality
* Ensures complete module coverage

**3. Better Requirements Understanding**

* AI-generated features serve as requirements documentation
* Business stakeholders can review and validate before development
* Technical team has clear, structured specifications

**4. Reduced Rework**

* Complete feature discovery upfront prevents late-stage additions
* Consistent patterns reduce refactoring needs
* Early validation catches issues before implementation

***

**Benefits of Individual Feature Generation (Currently Available)**

**1. Accelerated Implementation**

* Generate production-ready components instantly for any feature
* Focus on custom business logic, not boilerplate
* Maintain consistency across all features

**2. Consistent Quality**

* All features follow the same patterns and best practices
* Standardized validation rules, events, and subscribers
* Predictable structure makes code easier to maintain

**3. Reduced Development Time**

* 85-90% time savings on feature setup
* No need to manually design validation rules, events, and subscribers
* Quick review and refinement process

**4. Knowledge Transfer**

* AI-generated components serve as examples of best practices
* New team members learn patterns quickly
* Onboarding accelerator for developers

#### Use Cases

**Enterprise Application Development**

* **Rapid prototyping**: Quickly generate feature structures for proof-of-concept
* **Legacy modernization**: Standardize features when migrating legacy systems
* **Team scaling**: Onboard new developers faster with consistent patterns
* **Requirements gathering**: Translate business needs into technical features automatically

**Business Process Automation**

* **Workflow features**: Automatically generate event-driven workflows
* **Integration points**: Create subscribers for external system integrations
* **Audit trails**: Generate events for compliance and tracking
* **End-to-end automation**: Identify complete workflows from business requirements

**Quality Assurance**

* **Consistency checks**: Ensure all features follow the same patterns
* **Best practices enforcement**: AI applies industry standards automatically
* **Documentation**: Generated components serve as living documentation
* **Requirements validation**: AI suggestions help identify missing requirements early

#### Key Differentiators

1. **Context-Aware**: Understands business context from feature names
2. **Operation-Intelligent**: Adapts suggestions based on operation type
3. **Best Practice Compliant**: Follows domain-driven design and event-driven architecture principles
4. **Developer-Friendly**: Two-step review process ensures control and quality
5. **Production-Ready**: Generates components that follow enterprise patterns

#### Summary

FlexBase AI Feature Generation transforms the way enterprise applications are built by automating the most time-consuming and knowledge-intensive aspects of feature development. It enables teams to:

* **Build faster** with AI-generated, production-ready components
* **Build better** with consistent, best-practice implementations
* **Build smarter** by focusing on unique business logic, not boilerplate

The result is a significant reduction in development time, improved code quality, and faster time-to-market for business features.

***

*This document provides a business overview of FlexBase AI Feature Generation. For technical implementation details, please refer to the technical documentation.*


# Thinking in Flexbase

Welcome to the **Thinking in Flexbase** section! This is where you'll learn the fundamental concepts and patterns that make FlexBase applications powerful, maintainable, and scalable.

## 🎯 What You'll Learn Here

This section contains essential guides that will transform how you think about building enterprise applications with FlexBase:

### 📋 **Flexbase Control Flow** (`flexbase-control-flow.md`)

* **Complete request-to-response journey** for Insert and Query operations
* **Step-by-step breakdown** of how your code executes
* **Real-world examples** showing the magic behind FlexBase
* **Performance insights** that make your apps lightning-fast

### 🏗️ **Modules & Features Mapping** (`modules-and-features.md`)

* **Business requirements → Technical implementation** mapping
* **Screen actions → API endpoints** translation
* **Module organization** strategies for enterprise applications
* **Feature development workflow** that saves you hours

## 🚀 Why This Matters

Understanding these concepts will help you:

* **Build faster**: Know exactly what to create and how
* **Debug smarter**: Understand the flow when things go wrong
* **Scale confidently**: Design applications that grow with your business
* **Maintain easily**: Write code that's clear and organized

## 🎯 How to Use This Section

1. **Start with Control Flow** - Understand how your code executes
2. **Move to Modules & Features** - Learn how to organize your application
3. **Apply the patterns** - Use these concepts in your own projects
4. **Reference back** - Come back when you need a refresher

## 💡 Pro Tips

* **Read the examples carefully** - They show real-world patterns you'll use
* **Try the code samples** - Hands-on learning is the best way to understand
* **Think about your domain** - How would these patterns apply to your business?
* **Ask questions** - Understanding the "why" behind patterns makes you a better developer

***

**Ready to dive in?** Start with [Flexbase Control Flow](/thinking-in-flexbase/flexbase-control-flow) to see how your applications work under the hood, then explore [Modules & Features Mapping](/thinking-in-flexbase/modules-and-features) to learn how to organize your code like a pro! 🚀


# Flexbase Control Flow

## 🎯 Overview

This document explains the complete control flow for Flexbase features - from API call to execution completion. We'll cover one **Insert (POST)** and one **Query (GET)** example.

***

## 📝 Insert Feature Flow: AddOrder

### **1. API Request**

```
POST /api/Orders/AddOrder
Content-Type: application/json

{
  "customerId": "12345",
  "totalAmount": 299.99,
  "orderItems": [...]
}
```

### **2. Controller Layer**

```csharp
[HttpPost]
[Route("AddOrder")]
public async Task<IActionResult> AddOrder([FromBody] AddOrderDto dto)
{
    return await RunService(201, dto, _processOrdersService.AddOrder);
}
```

**What happens:** Controller receives request, validates DTO, calls service

### **3. Service Layer**

```csharp
public async Task<IActionResult> AddOrder(AddOrderDto dto)
{
    var command = new AddOrderCommand { Dto = dto };
    await _addOrderHandler.Execute(command, _serviceBusContext);
    return new OkResult();
}
```

**What happens:** Service creates command, calls handler

### **4. Command Handler**

```csharp
public async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    // 1. Initialize repository
    _repoFactory.Init(cmd.Dto);
    
    // 2. Call domain method
    _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
    
    // 3. Persist to database
    _repoFactory.GetRepo().InsertOrUpdate(_model);
    await _repoFactory.GetRepo().SaveAsync();
    
    // 4. Publish events
    await this.Fire(EventCondition, serviceBusContext);
}
```

**What happens:** Handler orchestrates the operation, calls domain, persists data, publishes events

### **5. Domain Method (Your Business Logic)**

```csharp
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // Your business rules
    if (cmd.Dto.TotalAmount <= 0)
        throw new BusinessException("Invalid amount");
    
    // Apply business logic
    this.Convert(cmd.Dto);
    this.SetAdded(cmd.Dto.GetGeneratedId());
    this.CalculateTotal();
    
    return this;
}
```

**What happens:** Domain validates business rules, applies logic, returns entity

### **6. Database Persistence**

```csharp
_repoFactory.GetRepo().InsertOrUpdate(_model);
await _repoFactory.GetRepo().SaveAsync();
```

**What happens:** Entity Framework saves to database

### **7. Event Publishing**

```csharp
await this.Fire(EventCondition, serviceBusContext);
```

**What happens:** Domain events published to message bus for side effects

### **8. Response**

```
HTTP 201 Created
Location: /api/Orders/{orderId}
```

***

## 🔍 Query Feature Flow: GetOrders

### **1. API Request**

```
GET /api/Orders/GetOrders?status=Pending
```

### **2. Controller Layer**

```csharp
[HttpGet]
[Route("GetOrders")]
public async Task<IActionResult> GetOrders([FromQuery] GetOrdersQuery query)
{
    return await RunService(200, query, _processOrdersService.GetOrders);
}
```

**What happens:** Controller receives request, calls service

### **3. Service Layer**

```csharp
public async Task<IActionResult> GetOrders(GetOrdersQuery query)
{
    var result = _getOrdersHandler.Fetch();
    return new OkObjectResult(result);
}
```

**What happens:** Service calls query handler

### **4. Query Handler**

```csharp
public override IEnumerable<GetOrdersDto> Fetch()
{
    return _repoFactory.GetRepo()
        .FindAll<Order>()
        .Where(o => o.Status == query.Status)
        .Include(o => o.Customer)
        .SelectTo<GetOrdersDto>()
        .ToList();
}
```

**What happens:** Handler executes optimized database query with projection

### **5. Database Query**

```sql
-- Generated SQL (optimized)
SELECT 
    o.Id,
    c.Name AS CustomerName,
    o.TotalAmount,
    o.Status,
    o.OrderDate
FROM Orders o
LEFT JOIN Customers c ON o.CustomerId = c.Id
WHERE o.Status = @Status
```

**What happens:** Only required fields fetched from database

### **6. Projection Mapping**

```csharp
// AutoMapper automatically maps to DTO
CreateMap<Order, GetOrdersDto>()
    .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name));
```

**What happens:** Database results mapped to DTO

### **7. Response**

```json
HTTP 200 OK
[
  {
    "id": "12345",
    "customerName": "John Doe",
    "totalAmount": 299.99,
    "status": "Pending",
    "orderDate": "2024-01-15T10:30:00Z"
  }
]
```

***

## 🔄 Complete Flow Summary

### **Insert Flow:**

```
API Request → Controller → Service → Command Handler → Domain Method → Database → Events → Response
```

### **Query Flow:**

```
API Request → Controller → Service → Query Handler → Database Query → Projection → Response
```

***

## 🎯 Key Points

### **Insert Features:**

* **Command Pattern** - Encapsulates operation
* **Domain Logic** - Business rules in domain layer
* **Event Publishing** - Side effects handled asynchronously
* **Transaction Management** - Automatic rollback on errors

### **Query Features:**

* **Projection-Based** - Only fetch required fields
* **Optimized SQL** - Generated automatically
* **Type Safety** - Compile-time validation
* **Performance** - Database-level optimization

### **Common Benefits:**

* **Separation of Concerns** - Each layer has single responsibility
* **Testability** - Each layer can be tested independently
* **Maintainability** - Clear, readable code structure
* **Consistency** - Same pattern across all features

***

*This control flow ensures reliable, maintainable, and performant enterprise applications with Flexbase.*


# Features and Modules

## 🎯 Understanding Modules and Features

**Flexbase** organizes enterprise applications into **Modules** and **Features** - a clear, business-focused approach that maps directly to your requirements and user interface actions.

***

## 📦 What is a Module?

A **Module** represents a complete business domain or functional area of your application. Think of it as a self-contained unit that handles all operations related to a specific business concept.

### **Examples of Modules:**

* 🛒 **Orders Module** - Complete order management
* 📦 **Products Module** - Product catalog and inventory
* 💳 **Payments Module** - Payment processing
* 👥 **Customers Module** - Customer management
* 📊 **Reports Module** - Analytics and reporting

***

## ⚡ What is a Feature?

A **Feature** represents a single business action or operation within a module. Every button click, form submission, or user action in your application typically maps to one feature.

### **Feature Examples:**

* **Insert (POST)**: `AddOrder`, `CreateProduct`, `RegisterCustomer`
* **Query (GET)**: `GetOrders`, `SearchProducts`, `GetCustomerDetails`
* **Update (PUT)**: `UpdateOrder`, `ModifyProduct`, `EditCustomer`
* **Delete (DELETE)**: `CancelOrder`, `RemoveProduct`, `DeactivateCustomer`

***

## 🔄 Business Requirements → Technical Mapping

### **The Mapping Process:**

1. **Identify Business Domains** → Create **Modules**
2. **Identify User Actions** → Create **Features**
3. **Define Data Requirements** → Create **DTOs**
4. **Specify Business Rules** → Create **Domain Logic**

***

## 📋 Real-World Example: E-Commerce Application

Let's walk through a complete example of how business requirements translate to Flexbase modules and features.

### **Business Requirements:**

> *"We need an e-commerce system where customers can browse products, place orders, and make payments. Administrators should be able to manage products and view order reports."*

***

## 🛒 Module 1: Orders Module

### **Business Domain:** Order Management

### **Purpose:** Handle all order-related operations

### **Features in Orders Module:**

#### **1. AddOrder Feature (POST)**

**Business Requirement:** *"Customer clicks 'Place Order' button"*

**Screen Action:** Customer fills order form and clicks "Place Order"

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpPost]
[Route("AddOrder")]
public async Task<IActionResult> AddOrder([FromBody] AddOrderDto dto)
{
    return await RunService(201, dto, _processOrdersService.AddOrder);
}

// Generated DTO
public partial class AddOrderDto : DtoBridge
{
    [Required]
    public string CustomerId { get; set; }
    
    [Required]
    public List<OrderItemDto> OrderItems { get; set; }
    
    [Range(0.01, double.MaxValue)]
    public decimal TotalAmount { get; set; }
    
    public string? Notes { get; set; }
}

// Generated Command Handler
public partial class AddOrderHandler : IAddOrderHandler
{
    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        await _repoFactory.GetRepo().SaveAsync();
        await this.Fire(EventCondition, serviceBusContext);
    }
}

// Domain Logic (You Write This)
public partial class Order : DomainModelBridge
{
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // Business validation
        if (cmd.Dto.TotalAmount <= 0)
            throw new BusinessException("Order total must be greater than zero");
        
        // Business rules
        if (cmd.Dto.OrderItems.Count == 0)
            throw new BusinessException("Order must contain at least one item");
        
        // Apply business logic
        this.Convert(cmd.Dto);
        this.SetAdded(cmd.Dto.GetGeneratedId());
        this.CalculateTotal();
        this.SetOrderStatus("Pending");
        
        return this;
    }
}
```

**API Endpoint:** `POST /api/Orders/AddOrder`

#### **2. GetOrders Feature (GET)**

**Business Requirement:** *"Admin clicks 'View Orders' to see all orders"*

**Screen Action:** Admin navigates to Orders page

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpGet]
[Route("GetOrders")]
public async Task<IActionResult> GetOrders([FromQuery] GetOrdersQuery query)
{
    return await RunService(200, query, _processOrdersService.GetOrders);
}

// Generated Query DTO
public partial class GetOrdersDto : DtoBridge
{
    public Guid Id { get; set; }
    public string CustomerId { get; set; }
    public string CustomerName { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; }
    public DateTime OrderDate { get; set; }
    public int ItemCount { get; set; }
}

// Generated Query Handler
public class GetOrders : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()
            .ToList();
    }
}

// Custom Query with Filters (You Can Extend)
public class GetOrdersByStatus : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public string Status { get; set; }
    
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.Status == Status)
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()
            .ToList();
    }
}
```

### **🚀 Database Optimization Magic - No Complex SQL Required!**

**The beauty of Flexbase queries is that you don't write complex SELECT statements!** Here's what happens automatically:

#### **1. Automatic Projection to Output Model**

```csharp
// You define what you want in the output DTO
public partial class GetOrdersDto : DtoBridge
{
    public Guid Id { get; set; }           // Only these fields
    public string CustomerName { get; set; } // are fetched from DB
    public decimal TotalAmount { get; set; } // automatically!
    public string Status { get; set; }
    public DateTime OrderDate { get; set; }
    // Note: No complex SELECT statements needed!
}
```

#### **2. Database-Level Optimization**

**What Flexbase generates automatically:**

```sql
-- Instead of: SELECT * FROM Orders (fetches ALL columns)
-- Flexbase generates: SELECT only the fields you need
SELECT 
    o.Id,
    c.Name AS CustomerName,  -- From joined Customer table
    o.TotalAmount,
    o.Status,
    o.OrderDate
FROM Orders o
LEFT JOIN Customers c ON o.CustomerId = c.Id
WHERE o.Status = @Status
```

#### **3. Performance Benefits**

* ✅ **Only Required Fields** - Database fetches only what's in your DTO
* ✅ **Automatic Joins** - Include() statements become optimized SQL JOINs
* ✅ **No N+1 Queries** - Single query with proper joins
* ✅ **Memory Efficient** - No unnecessary data loaded into memory
* ✅ **Network Optimized** - Less data transferred over the network

#### **4. Complex Projections Made Simple**

```csharp
// You can add calculated fields without complex SQL
public partial class GetOrdersDto : DtoBridge
{
    public Guid Id { get; set; }
    public string CustomerName { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; }
    public DateTime OrderDate { get; set; }
    
    // Calculated fields - Flexbase handles the SQL automatically
    public int DaysSinceOrder { get; set; }
    public string StatusDisplay { get; set; }
    public bool IsHighValue { get; set; }
}

// AutoMapper configuration (generated automatically)
CreateMap<Order, GetOrdersDto>()
    .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
    .ForMember(dest => dest.DaysSinceOrder, opt => opt.MapFrom(src => (DateTime.UtcNow - src.OrderDate).Days))
    .ForMember(dest => dest.StatusDisplay, opt => opt.MapFrom(src => GetStatusDisplay(src.Status)))
    .ForMember(dest => dest.IsHighValue, opt => opt.MapFrom(src => src.TotalAmount > 1000));
```

#### **5. What You DON'T Have to Write**

```sql
-- ❌ You DON'T write this complex SQL:
SELECT 
    o.Id,
    c.Name AS CustomerName,
    o.TotalAmount,
    o.Status,
    o.OrderDate,
    CASE 
        WHEN o.Status = 'Pending' THEN 'Awaiting Processing'
        WHEN o.Status = 'Processing' THEN 'Being Processed'
        WHEN o.Status = 'Shipped' THEN 'On the Way'
        ELSE 'Unknown'
    END AS StatusDisplay,
    DATEDIFF(day, o.OrderDate, GETDATE()) AS DaysSinceOrder,
    CASE 
        WHEN o.TotalAmount > 1000 THEN 1 
        ELSE 0 
    END AS IsHighValue
FROM Orders o
LEFT JOIN Customers c ON o.CustomerId = c.Id
WHERE o.Status = @Status
ORDER BY o.OrderDate DESC
```

#### **6. What You DO Write (Simple and Clean)**

```csharp
// ✅ You write this simple, readable code:
public class GetOrdersByStatus : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public string Status { get; set; }
    
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.Status == Status)
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()  // Magic happens here!
            .ToList();
    }
}
```

### **🎯 Key Benefits:**

1. **No SQL Knowledge Required** - Write C# LINQ, get optimized SQL
2. **Automatic Optimization** - Only fetch what you need
3. **Type Safety** - Compile-time validation of all projections
4. **Maintainable** - Changes to DTO automatically update SQL
5. **Performance** - Database-level optimization without complexity
6. **Readable** - Business logic is clear and understandable

### **💡 The Magic of SelectTo()**

The `SelectTo<GetOrdersDto>()` method:

* ✅ **Analyzes your DTO** - Sees what fields you need
* ✅ **Generates optimized SQL** - Only selects required columns
* ✅ **Handles joins automatically** - Based on Include() statements
* ✅ **Applies projections** - Maps complex calculations
* ✅ **Optimizes performance** - Database-level efficiency

**Result:** You focus on business logic while Flexbase handles all the complex SQL optimization automatically!

**API Endpoint:** `GET /api/Orders/GetOrders`

***

## 📦 Module 2: Products Module

### **Business Domain:** Product Catalog Management

### **Purpose:** Handle all product-related operations

### **Features in Products Module:**

#### **1. AddProduct Feature (POST)**

**Business Requirement:** *"Admin clicks 'Add New Product' button"*

**Screen Action:** Admin fills product form and clicks "Save Product"

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpPost]
[Route("AddProduct")]
public async Task<IActionResult> AddProduct([FromBody] AddProductDto dto)
{
    return await RunService(201, dto, _processProductsService.AddProduct);
}

// Generated DTO
public partial class AddProductDto : DtoBridge
{
    [Required]
    [StringLength(100)]
    public string Name { get; set; }
    
    [Required]
    [StringLength(500)]
    public string Description { get; set; }
    
    [Range(0.01, double.MaxValue)]
    public decimal Price { get; set; }
    
    [Range(0, int.MaxValue)]
    public int StockQuantity { get; set; }
    
    [Required]
    public string Category { get; set; }
    
    public string? ImageUrl { get; set; }
}

// Domain Logic (You Write This)
public partial class Product : DomainModelBridge
{
    public virtual Product AddProduct(AddProductCommand cmd)
    {
        // Business validation
        if (cmd.Dto.Price <= 0)
            throw new BusinessException("Product price must be greater than zero");
        
        if (cmd.Dto.StockQuantity < 0)
            throw new BusinessException("Stock quantity cannot be negative");
        
        // Apply business logic
        this.Convert(cmd.Dto);
        this.SetAdded(cmd.Dto.GetGeneratedId());
        this.SetProductStatus("Active");
        this.GenerateSku();
        
        return this;
    }
}
```

**API Endpoint:** `POST /api/Products/AddProduct`

#### **2. GetProducts Feature (GET)**

**Business Requirement:** *"Customer clicks 'Browse Products' to see available products"*

**Screen Action:** Customer navigates to Products page

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpGet]
[Route("GetProducts")]
public async Task<IActionResult> GetProducts([FromQuery] GetProductsQuery query)
{
    return await RunService(200, query, _processProductsService.GetProducts);
}

// Generated Query DTO
public partial class GetProductsDto : DtoBridge
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
    public string Category { get; set; }
    public string Status { get; set; }
    public string Sku { get; set; }
    public string? ImageUrl { get; set; }
}

// Generated Query Handler
public class GetProducts : FlexiQueryEnumerableBridge<GetProductsDto>
{
    public override IEnumerable<GetProductsDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Product>()
            .Where(p => p.Status == "Active")
            .SelectTo<GetProductsDto>()
            .ToList();
    }
}

// Custom Search Query (You Can Extend)
public class SearchProducts : FlexiQueryEnumerableBridge<GetProductsDto>
{
    public string SearchTerm { get; set; }
    public string Category { get; set; }
    public decimal? MinPrice { get; set; }
    public decimal? MaxPrice { get; set; }
    
    public override IEnumerable<GetProductsDto> Fetch()
    {
        var query = _repoFactory.GetRepo().FindAll<Product>()
            .Where(p => p.Status == "Active");
        
        if (!string.IsNullOrEmpty(SearchTerm))
            query = query.Where(p => p.Name.Contains(SearchTerm) || p.Description.Contains(SearchTerm));
        
        if (!string.IsNullOrEmpty(Category))
            query = query.Where(p => p.Category == Category);
        
        if (MinPrice.HasValue)
            query = query.Where(p => p.Price >= MinPrice.Value);
        
        if (MaxPrice.HasValue)
            query = query.Where(p => p.Price <= MaxPrice.Value);
        
        return query.SelectTo<GetProductsDto>().ToList();
    }
}
```

**API Endpoint:** `GET /api/Products/GetProducts`

***

## 🎯 Screen-to-Feature Mapping Examples

### **Example 1: Customer Order Screen**

| Screen Element        | User Action | Feature           | HTTP Method | Endpoint                        |
| --------------------- | ----------- | ----------------- | ----------- | ------------------------------- |
| "Place Order" Button  | Click       | AddOrder          | POST        | `/api/Orders/AddOrder`          |
| "View My Orders" Link | Click       | GetCustomerOrders | GET         | `/api/Orders/GetCustomerOrders` |
| "Order Details" Link  | Click       | GetOrderDetails   | GET         | `/api/Orders/GetOrderDetails`   |
| "Cancel Order" Button | Click       | CancelOrder       | PUT         | `/api/Orders/CancelOrder`       |

### **Example 2: Admin Product Management Screen**

| Screen Element                | User Action  | Feature               | HTTP Method | Endpoint                              |
| ----------------------------- | ------------ | --------------------- | ----------- | ------------------------------------- |
| "Add Product" Button          | Click        | AddProduct            | POST        | `/api/Products/AddProduct`            |
| "Edit Product" Button         | Click        | UpdateProduct         | PUT         | `/api/Products/UpdateProduct`         |
| "Delete Product" Button       | Click        | DeleteProduct         | DELETE      | `/api/Products/DeleteProduct`         |
| "Search Products" Input       | Type + Enter | SearchProducts        | GET         | `/api/Products/SearchProducts`        |
| "Filter by Category" Dropdown | Select       | GetProductsByCategory | GET         | `/api/Products/GetProductsByCategory` |

### **Example 3: Customer Dashboard Screen**

| Screen Element        | User Action | Feature               | HTTP Method | Endpoint                               |
| --------------------- | ----------- | --------------------- | ----------- | -------------------------------------- |
| "View Profile" Link   | Click       | GetCustomerProfile    | GET         | `/api/Customers/GetCustomerProfile`    |
| "Edit Profile" Button | Click       | UpdateCustomerProfile | PUT         | `/api/Customers/UpdateCustomerProfile` |
| "Order History" Tab   | Click       | GetOrderHistory       | GET         | `/api/Orders/GetOrderHistory`          |
| "Wishlist" Tab        | Click       | GetWishlist           | GET         | `/api/Products/GetWishlist`            |

***

## 🏗️ Complete Module Structure

### **Typical Module Contains:**

```
📦 OrdersModule/
├── 🎯 Domain/
│   ├── Order.cs (Domain Model)
│   ├── AddOrder.cs (Business Logic)
│   └── Order_SeedData.cs (Test Data)
├── 🌐 Controllers/
│   └── OrdersController.cs (REST API)
├── 📝 DTOs/
│   ├── AddOrderDto.cs (Input)
│   ├── GetOrdersDto.cs (Output)
│   └── OrderDto.cs (Domain)
├── 🔧 Handlers/
│   ├── AddOrderHandler.cs (Command)
│   └── GetOrdersHandler.cs (Query)
├── 📡 Events/
│   ├── OrderCreatedEvent.cs
│   └── OrderUpdatedEvent.cs
└── 🧪 Tests/
    ├── AddOrderTests.cs
    └── GetOrdersTests.cs
```

***

## 🎯 Feature Development Workflow

### **Step 1: Identify Business Requirement**

> *"Customer needs to be able to place an order"*

### **Step 2: Map to Screen Action**

> *"Customer clicks 'Place Order' button on order form"*

### **Step 3: Define Feature**

> *"AddOrder feature in Orders module"*

### **Step 4: Generate Code**

```bash
dotnet run --generate-feature Orders AddOrder
```

### **Step 5: Add Business Logic**

```csharp
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // Your business rules here
    ValidateOrder(cmd.Dto);
    ApplyBusinessRules(cmd.Dto);
    return this;
}
```

### **Step 6: Test and Deploy**

* ✅ Unit tests generated automatically
* ✅ Integration tests ready
* ✅ API documentation generated
* ✅ Ready for deployment

***

## 📊 Module Planning Template

### **For Each Business Domain, Ask:**

1. **What is the main business concept?** → Module Name
2. **What actions can users perform?** → Features
3. **What data is needed for each action?** → DTOs
4. **What business rules apply?** → Domain Logic
5. **What events should be published?** → Domain Events

### **Example: Customer Management Module**

| Question                  | Answer                                                        |
| ------------------------- | ------------------------------------------------------------- |
| **Main Business Concept** | Customer Management                                           |
| **User Actions**          | Register, Login, Update Profile, View Profile, Deactivate     |
| **Data Requirements**     | Name, Email, Phone, Address, Preferences                      |
| **Business Rules**        | Email validation, Password requirements, Profile completeness |
| **Events**                | CustomerRegistered, ProfileUpdated, CustomerDeactivated       |

***

## 🚀 Best Practices

### **Module Design:**

* ✅ **Single Responsibility** - One business domain per module
* ✅ **Clear Boundaries** - Minimal coupling between modules
* ✅ **Consistent Naming** - Follow business terminology
* ✅ **Complete Coverage** - All related features in one module

### **Feature Design:**

* ✅ **One Action Per Feature** - Each feature does one thing
* ✅ **Clear Input/Output** - Well-defined DTOs
* ✅ **Business Logic in Domain** - Keep controllers thin
* ✅ **Proper Validation** - Validate at multiple levels

### **Naming Conventions:**

* **Modules:** `OrdersModule`, `ProductsModule`, `CustomersModule`
* **Features:** `AddOrder`, `GetOrders`, `UpdateProduct`, `DeleteCustomer`
* **DTOs:** `AddOrderDto`, `GetOrdersDto`, `OrderDto`
* **Handlers:** `AddOrderHandler`, `GetOrdersHandler`

***

## 🎉 Summary

**Flexbase Modules and Features provide a clear, business-focused approach to enterprise application development:**

* **Modules** = Business domains (Orders, Products, Customers)
* **Features** = User actions (AddOrder, GetProducts, UpdateCustomer)
* **Screen Actions** = Direct mapping to features
* **Business Requirements** = Clear path to technical implementation

**The result:** A maintainable, scalable application that directly reflects your business needs and user interface requirements.

***

*Start mapping your business requirements to Flexbase modules and features today. Transform your ideas into working enterprise applications in minutes, not months.*


# Flexbase MCP AI Prompts

This directory contains ready-to-use prompt templates for working with FlexBase applications through the **FlexBase MCP Server** (Model Context Protocol). Copy any prompt into your AI agent (GitHub Copilot, Cursor, etc.) and replace placeholders with your values.

## Prerequisites

Your AI agent must have the **FlexBase MCP server** configured. The MCP server provides guides, conventions, and prompt templates that the agent loads automatically when processing your requests.

## How to Use

1. Pick the prompt guide that matches your task
2. Copy the relevant prompt from the guide
3. Replace placeholders (`[EntityName]`, `[ModuleName]`, `@[BRD_FILE].md`) with your values
4. Paste into your AI agent — the MCP tools load all patterns and conventions automatically

**Or, use the agent orchestration tool:**

* Just tell your AI agent what you want (e.g., "analyze this BRD", "complete the implementation")
* The agent auto-detects the workflow and drives the pipeline

## Index

### 0. Agent Orchestration — Start Here (Easiest Way)

* [**Agent Orchestration**](/flexbase-mcp-ai-prompts/agent-orchestration-prompts) — Tell the agent what you want and it orchestrates the entire pipeline. Auto-detects extraction vs implementation, entry point (Legacy/BRD/New App), and drives all tasks autonomously. Includes stored procedure extraction, DataStore/Provider integration, and workflow state extraction.

### 1. Implementation Completion (Post Code-Generation)

* [**Implementation Completion**](/flexbase-mcp-ai-prompts/implementation-completion-prompts) — Complete API business logic and generate UI pages after FlexBase Studio code generation, driven by extraction JSON/Markdown artifacts — works for **all entry points** (Legacy Migration, BRD Extraction, New Application).

### 1a. Domain Original Names (Standalone — Optional)

* [**Domain Original Names**](/flexbase-mcp-ai-prompts/domain-original-names-prompts) — Apply `[Table]` and `[Column]` EF Core annotations to domain models for legacy database compatibility. Standalone prompt — run independently at any time.

### 2. API Development

* [**FlexBase API Patterns**](/flexbase-mcp-ai-prompts/flexbase-api-guide-prompts) — DTOs, mappers, queries, handlers, providers, workflow states, concurrency, DataStore/Provider integration.
* [**HIPAA Compliance**](/flexbase-mcp-ai-prompts/hipaa-compliance-prompts) — HIPAA applicability review, PHI touchpoint analysis, minimum-necessary access, auditability, disclosure control, and remediation planning using FlexBase standards.

### 3. UI Framework Guides

* [**Blazor FluentUI Patterns**](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts) — FluentUI Blazor v4.x pages, dialogs, REST clients, design system, module generation.
* [**Angular UI Patterns**](/flexbase-mcp-ai-prompts/angular-ui-guide-prompts) — Angular services, components, forms, auth, routing.
* [**React UI Patterns**](/flexbase-mcp-ai-prompts/react-js-ui-guide-prompts) — React hooks, services, forms, auth, routing.

### 4. Legacy Application Migration

* [**Legacy Migration → Markdown**](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file) — Analyze legacy code and extract to Markdown (supports all platforms including PowerBuilder/4GL).
* [**Legacy Migration → JSON**](/flexbase-mcp-ai-prompts/legacy-migration-prompts-json-file) — Generate FlexBase JSON from legacy applications.
* [**PowerBuilder Project Analysis**](/flexbase-mcp-ai-prompts/legacy-migration-pb-analysis-prompts) — Auto-detect PB project format and read source files.
* [**Stored Procedure & Trigger Extraction**](/flexbase-mcp-ai-prompts/legacy-migration-stored-procedures-prompts) — Extract and map stored procedures, triggers, and embedded SQL from databases.

### 5. Business Requirements Extraction

* [**BRD Extraction → Markdown**](/flexbase-mcp-ai-prompts/brd-extraction-prompts-md-file) — Extract modules, features, validations, events from BRDs to Markdown.
* [**BRD Extraction → JSON**](/flexbase-mcp-ai-prompts/brd-extraction-prompts-json-file) — Generate FlexBase JSON import files from BRDs.

### 6. New Application Development

* [**New Application → Markdown**](/flexbase-mcp-ai-prompts/new-application-add-moduels-features-to-existing-application-prompts-md-file) — Design new applications using DDD principles.
* [**New Application → JSON**](/flexbase-mcp-ai-prompts/new-application-add-moduels-features-to-existing-application-prompts-json-file) — Generate FlexBase JSON for new applications.

### 7. Project Estimation

* [**Estimation Prompts**](/flexbase-mcp-ai-prompts/estimation-prompts) — Generate detailed per-module, per-feature project estimates with complexity classification (Simple/Medium/Complex/Very Complex), API + UI split, unit test and manual test case effort, delivery phasing, and output as Markdown, Excel, or HTML.

**Available guide (loaded automatically by MCP when you use the prompts below):**

* **Estimation Guide** (`getGuideSection("estimation", ...)`) — Complexity tiers, hour benchmarks per operation type, UI page estimation with/without wireframes, testing formulas, phase-based delivery grouping, real project benchmarks (SSW 25 modules, KG 13 modules)

### 8. Manual Test Case Generation (QA)

* [**Test Cases Prompts**](/flexbase-mcp-ai-prompts/test-cases-prompts) — All module-based, page-based, Excel workbook, and Postman collection prompt templates for manual test case generation.

Generate comprehensive manual test cases from **any requirement source** — BRDs, extraction JSON/Markdown, legacy application artifacts, or design documents. Test cases are organized by FlexBase modules and features, with concrete sample data, assumptions, and expected results that a manual QA tester can execute.

**Available guides (loaded automatically by MCP when you use the prompts below):**

* **Manual Test Case Guide** (`getGuideSection("manual-test-cases", ...)`) — Core test case structure, categories per operation type, organization modes
* **Postman Collection Guide** (`getGuideSection("postman-collection", ...)`) — Generate Postman v2.1 collections with test scripts, pre-request scripts, Newman CI/CD integration
* **Excel Workbook Guide** (`getGuideSection("excel-test-workbook", ...)`) — Generate Excel workbooks with priority colors, status dropdowns, per-module sheets
* **Conventions** (`getCodeConventions("manual-test-case")`) — Naming rules, field validation derivation, styling rules

**Quick prompts — copy, replace placeholders, paste into your AI agent:**

#### From a BRD or Requirement Document

```
Analyze this BRD and generate manual test cases organized by module with concrete sample data, assumptions, and expected results for each feature

@[BRD_FILE].md
```

```
Generate manual test cases for the [ModuleName] module from this requirements document. Include positive, negative, boundary, and validation test cases for every feature

@[REQUIREMENTS_FILE].md
```

#### From FlexBase Extraction JSON

```
Parse this FlexBase extraction JSON and generate manual test cases for every feature. Derive field validations from domainServices attributes (required, maxLength, type). Include sample test data for every field

@[PROJECT]_Import.json
```

```
Generate manual test cases for the [ModuleName] module from this extraction JSON. Cover all features including events, subscribers, and workflow state transitions

@[PROJECT]_[ModuleName]_Features.json
```

#### From FlexBase Extraction Markdown

```
Parse this FlexBase extraction Markdown and generate manual test cases for all modules. Use entity attribute tables to derive field validation tests and sample data

@[PROJECT]_Summary.md
```

```
Generate manual test cases from this per-module extraction Markdown. Include cross-module integration tests for any subscriber chains

@[PROJECT]_[ModuleName].md
```

#### From Legacy Application Analysis

```
Analyze this legacy application output and generate manual test cases including data migration verification, trigger-to-subscriber mapping tests, and screen equivalence tests

@[LEGACY_ANALYSIS_FILE].md
```

```
Generate manual test cases from this legacy database schema. Map each table to a module, each CRUD operation to a feature, and each trigger to a subscriber test case

@[DATABASE_SCHEMA].sql
```

#### Single Feature — Quick

```
Generate all manual test cases for the [FeatureName] feature in the [ModuleName] module.
Operation type: [CREATE/UPDATE/DELETE/GETBYID/GETPAGEDLIST]
Entity fields: [Field1] (string, max 100, required), [Field2] (int, required), [Field3] (datetime, optional)
Validations: [Validation1 description], [Validation2 description]
Events: [EventName] → Subscribers: [Subscriber1], [Subscriber2]
```

#### Gap Analysis — Review Existing Test Cases

```
Review these test cases against the source requirements and identify gaps — missing test categories, uncovered validations, missing event/subscriber tests, and placeholder data that needs concrete values

Requirements: @[REQUIREMENTS_FILE].md
Test Cases: @[TESTCASES_FILE].md
```

#### Complete Module Test Suite

```
Generate a complete manual test suite for the [ModuleName] module from this extraction. Output:
1. Summary file with test distribution and global assumptions
2. Test cases for every feature (CREATE, UPDATE, DELETE, GET, GETPAGEDLIST)
3. Cross-module integration tests for events/subscribers
4. Reference data setup needed before testing

@[PROJECT]_Import.json
```

**What gets generated:**

* Test case ID convention: `TC-[MODULE]-[FEATURE]-[NNN]` (module-based) or `TC-PAGE-[GROUP]-[NNN]` (page-based)
* Priority levels: P0 (Critical), P1 (High), P2 (Medium), P3 (Low)
* Every test includes: preconditions, assumptions, sample data table, steps, expected results
* Minimum test counts: CREATE (14), UPDATE (10), DELETE (7), GETBYID (6), GETPAGEDLIST (9)
* Validation tests always in pass/fail pairs
* Event and subscriber verification tests
* Workflow state transition tests (valid + invalid)
* Files split per module when output is large
* **Output formats:** Markdown files (default) or Excel workbook (.xlsx) with priority colors, status dropdowns, and per-module sheets

#### Page-Based Test Cases (UI / UX Perspective)

```
Analyze this page inventory and generate page-based test cases organized by page group (PublicCMS, BookingFlow, GuestAccount, AdminCalendar, etc.) with responsive and accessibility checks

@[PAGE_INVENTORY_OR_ESTIMATION_DOC].md
```

```
Generate page-based test cases for the [GroupName] page group. Include page load, user interaction, responsive layout (375px / 768px / 1200px+), and accessibility (tab order, ARIA labels, contrast) checks

@[UI_DESIGNS_OR_WIREFRAMES].md
```

```
Generate both module-based test cases (by API feature) AND page-based test cases (by UI page) from this BRD. Output separate file sets for each perspective

@[BRD_FILE].md
```

#### Excel Workbook Output

```
Analyze this BRD and generate an Excel workbook (.xlsx) with all manual test cases organized by module — include priority colors (P0=red, P1=yellow, P2=green, P3=grey), frozen headers, auto-filters, and status dropdown columns

@[BRD_FILE].md
```

```
Generate a Node.js ExcelJS script that parses all Markdown test case files in TestCases/ and produces a multi-sheet Excel workbook with per-module sheets, priority colors, status dropdowns, and a summary sheet

@TestCases/
```

```
Convert these existing Markdown test case files to an Excel workbook with frozen headers, color-coded priorities, status tracking dropdowns, and per-module sheets

@[PROJECT]_TestCases_*.md
```

#### Markdown → Excel Conversion (Existing Test Cases)

```
Parse all page-based test case files in PageTestCases/ and produce an Excel workbook with per-page-group sheets, responsive/accessibility columns, and a summary sheet

@PageTestCases/
```

```
Generate a combined Excel workbook with both module-based tests (from TestCases/) and page-based tests (from PageTestCases/) on separate sheet groups, plus a unified summary sheet

@TestCases/ @PageTestCases/
```

#### Postman Collection Output (API Tests)

```
Generate a Postman Collection v2.1 JSON from these module test case Markdown files — map each test case to an HTTP request with test scripts asserting expected status codes and response bodies. Include environment file with baseUrl and auth token

@TestCases/
```

```
Analyze this BRD and generate a Postman collection with API test requests for every feature — include happy path, validation, boundary, and negative test cases with concrete sample data and test script assertions

@[BRD_FILE].md
```

```
Parse this FlexBase extraction JSON and generate a Postman collection with requests for every feature. Derive request bodies from domainServices attributes and test scripts from expected validation messages

@[PROJECT]_Import.json
```

```
Generate a Postman collection for the [ModuleName] module with requests for all features (CREATE, UPDATE, DELETE, GET, GETPAGEDLIST) including positive, negative, and boundary test cases. Include pre-request scripts for dynamic data and test scripts for assertions

@[PROJECT]_TestCases_[ModuleName].md
```

### 9. Endpoints Configuration & DevOps

* [**Endpoints Configuration and DevOps Prompts**](/flexbase-mcp-ai-prompts/endpoints-configuration-and-devops-prompts) — Configuration of API endpoints, environment setup, CI/CD pipelines, deployment strategies, and DevOps best practices for FlexBase applications.

## Related Documentation

* [Core Concepts](/core-concepts)
* [Solution Structure](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/solution-structure/README.md)
* [Thinking in Flexbase](/thinking-in-flexbase)


# Agent Orchestration Prompts

> **One tool call to rule them all.** Tell your AI agent what you want to do and the agent orchestrates the entire workflow — extraction, JSON generation, UI derivation, and implementation completion — automatically.

## How to Use

Just tell your AI agent what you want to do. The agent detects your intent, loads the right conventions and guides, then executes the workflow autonomously.

**Copy-paste any prompt below into your AI agent chat:**

### Phase 1 — Extraction & Analysis

**Analyze a BRD:**

```
Analyze this BRD and prepare FlexBase files
```

**Migrate a legacy application:**

```
Migrate this legacy application to FlexBase
```

**Migrate with stored procedure & trigger extraction:**

```
Migrate this legacy application to FlexBase — extract stored procedures and triggers too
```

**Design a new application:**

```
Design a new scheduling app for healthcare
```

**Full pipeline (extract → Studio → complete):**

```
Build me the full app from this requirements doc
```

### Phase 3 — Implementation Completion

**Complete API business logic (after FlexBase Studio code generation):**

```
Complete the implementation — code was generated by FlexBase Studio
```

**Complete with stored procedure strategy override:**

```
Complete the implementation — use stored procedures for complex queries
```

### Phase 3 — UI Generation

**Generate Blazor UI for a module:**

```
Generate Blazor pages for the Orders module
```

**Setup FlexBase theme (one-time, before any UI work):**

```
Setup FlexBase theme for my Blazor FluentUI project
```

### Standalone — Optional Tasks

**Apply original database names to domain models:**

```
Apply original database names to the domain models
```

**Integrate a DataStore or Provider:**

```
Add CosmosDB document storage to the Orders handler
```

***

## Task Catalog

### Task 1: Full Pipeline (Extract → Studio Handoff → Complete)

**Goal:** End-to-end: analyze source → generate JSON → \[user does Studio] → complete API + UI\
**User provides:** Source material (BRD, legacy code, or business requirements)

### Task 2: Extract from Source (Phase 1 Only)

**Goal:** Analyze source material and produce Markdown + JSON files\
**User provides:** BRD, legacy code, or business description\
**Produces:** Markdown extraction files, JSON import files with UI metadata, Studio handoff instructions

### Task 3: Complete Implementation (Phase 3 Only)

**Goal:** Complete API business logic and generate UI pages from generated skeleton code\
**User provides:** Generated FlexBase solution + extraction artifacts (JSON/Markdown)

### Task 4: Resume After Studio

**Goal:** Pick up where Phase 1 left off — user has generated code and wants implementation completed\
**User provides:** Says "I've generated the code" or "complete the implementation"

### Task 5: Generate UI Only — Complete Module UI from One Command

**Goal:** Generate the complete UI stack for a module — REST client, DTOs, dialog, list page, navigation — without touching the API project\
**User provides:** Module name (e.g., "Products", "Orders", "Customers") and optionally UI framework preference\
**User says:** "Generate Blazor pages for the Products module" or "Build the UI for Orders"

### Task 6: Setup FlexBase Theme for Blazor FluentUI (One-Time)

**Goal:** Configure business-domain-themed admin layout with FluentDesignTheme, sidebar navigation, and FluentUI providers — first step before any functional UI work\
**User provides:** Generated Blazor FluentUI solution + business domain context

### Task 7: Apply Original Database Names to Domain Models

**Goal:** Add `[Table]` and `[Column]` EF Core annotations to domain models for legacy database compatibility\
**User provides:** FlexBase solution with domain models + extraction JSON containing `originalName` / `sourceTable` metadata\
**This task is standalone** — run it independently at any time after domain models are generated.

### Task 8: Legacy Migration with Database Stored Procedure & Trigger Extraction

**Goal:** Same as Task 2 (Legacy Migration extraction) **plus** extract stored procedure and trigger definitions from the legacy database\
**User provides:** Legacy source material (+ optionally exported SP/trigger scripts)\
**User says:** "Migrate this legacy application to FlexBase — extract stored procedures and triggers too"\
**Default behavior:** SP logic will be implemented as C# code in Phase 3\
**User override:** Say "keep the stored procedures" to retain them in the database

### Task 9: Stored Procedure Implementation Strategy (Phase 3) — OVERRIDE Only

**Goal:** Override the default SP handling during implementation completion\
**When needed:** Only when the user explicitly says "use stored procedures" or "keep stored procedures". The default implementation automatically translates SP logic to C# code without any extra prompt.\
**Options:**

* **Move to Code (DEFAULT):** SP logic becomes C# handler/query code
* **Call Stored Procedures:** Keep SPs in the database and call them from FlexBase handlers
* **Mixed Strategy:** Per-feature control — some SPs move to code, others stay as stored procedures

### Task 10: DataStore & Provider Integration

**Goal:** Integrate FlexBase DataStore or Provider operations into handlers, queries, subscribers, or validation plugins\
**User provides:** The store/provider type and business use case\
**User says:** Any of the following:

```
Add CosmosDB document storage to the Orders handler
```

```
Implement vector search with PgVector for product recommendations
```

```
Set up email notifications using SendGrid for order confirmations
```

```
Add Redis caching to the GetProducts query
```

```
Store uploaded files in Azure Blob Storage from the Documents handler
```

**Supported stores and providers:**

| Type              | Examples                                        |
| ----------------- | ----------------------------------------------- |
| Document Store    | CosmosDB, MongoDB, DynamoDB, RavenDB            |
| Vector Store      | PgVector, Azure AI Search, OpenSearch           |
| Graph Store       | Neo4j, Apache AGE, Amazon Neptune               |
| Search Store      | Elasticsearch, Azure AI Search, Algolia         |
| File Store        | Azure Blob, AWS S3, GCP Storage                 |
| Time Series Store | TimescaleDB, InfluxDB, Azure Data Explorer      |
| Cache Store       | Redis, Memcached, NCache                        |
| AI Provider       | Azure OpenAI, OpenAI, Anthropic, Gemini, Ollama |
| Email Provider    | SMTP, SendGrid, Console (dev)                   |

### Sub-Prompt: Workflow State Extraction

**When:** During Phase 1 extraction, any domain entity that has a status/state column (e.g., `Status`, `State`, `OrderStatus`, `IsActive`)\
**Goal:** Extract complete workflow state definitions and transitions per entity — handled automatically during extraction.

***

## Intent Detection — Quick Reference

| User Says                                               | What Happens                             |
| ------------------------------------------------------- | ---------------------------------------- |
| "analyze this BRD", "extract requirements"              | Phase 1 — BRD extraction                 |
| "migrate this app", "convert this code"                 | Phase 1 — Legacy migration               |
| "design a new app", "build me an app for..."            | Phase 1 — New application                |
| "complete the implementation", "finish the code"        | Phase 3 — Implementation completion      |
| "generate Blazor pages", "build the UI"                 | Phase 3 — UI generation                  |
| "setup FlexBase theme"                                  | Phase 3 — Theme setup                    |
| "apply original database names"                         | Phase 3 — Domain name annotations        |
| "migrate with stored procedures"                        | Phase 1 — Legacy + SP extraction         |
| "use stored procedures", "create database scripts"      | Phase 3 — SP implementation override     |
| "add CosmosDB to handler", "set up email notifications" | Phase 3 — DataStore/Provider integration |

***

## Scope Control

The agent stays within the documented scope. It does NOT:

* Invent features not in the source material
* Add entities not in the extraction JSON
* Create UI screens for features that don't exist
* Expand scope unless the user explicitly asks


# Implementation Completion Prompts

> After FlexBase Studio generates skeleton code, use these tasks to **complete API business logic** and **generate UI pages/components** — driven by your extraction JSON and Markdown artifacts.
>
> **Works for all entry points:** Legacy Migration, BRD Extraction, and New Application Design.

## How to Use

Tell your AI agent which feature or module to implement. It will load the implementation completion guide and relevant conventions to produce production-ready code.

**Example prompts you can give your AI agent:**

```
Complete the API business logic for the Schedule module using the extraction JSON
```

```
Generate Blazor CRUD pages for the Person entity from the feature JSON
```

```
Add [Table] and [Column] annotations for legacy database column names
```

```
Implement all validations for CreateBooking from the extraction data
```

```
Complete the Angular service and list component for Orders
```

```
Walk me through implementing the entire Customer module end-to-end
```

```
Complete the implementation — move stored procedure logic to C# handlers
```

```
Complete the implementation — use stored procedures for complex queries
```

```
Generate database scripts for the stored procedures
```

```
Implement the CreateProduct handler using Document Store for CosmosDB
```

```
Add Redis caching to the GetProducts query with cache-aside pattern
```

```
Send a confirmation email after order creation using Email Provider
```

```
Implement AI-powered product classification using Azure OpenAI in the CreateProduct handler
```

```
Add vector search to the SearchArticles query using PgVector for semantic results
```

```
Store uploaded documents in Azure Blob Storage from the CreateDocument handler
```

***

## Task Catalog

### Task 1: Complete Domain Model from Extraction JSON

**Goal:** Fill in generated domain model partial classes with attributes, relationships, and legacy name annotations\
**User provides:** Module name, extraction JSON file path (or entity name)

### Task 1b: Configure Database Indexes

**Goal:** Add index configuration from extraction JSON index definitions\
**User provides:** Extraction JSON with index arrays per domain entity

### Task 2: Complete Domain Factory Methods

**Goal:** Implement Create and Update factory methods using extraction feature details\
**User provides:** Entity name, extraction JSON feature for CREATE/UPDATE

### Task 2b: Complete Handler with Stored Procedure Logic

**Goal:** Implement handler using stored procedure documentation as the specification\
**User provides:** Feature name with SP flag in extraction JSON + SP documentation file

**Options:**

* **Move to Code (DEFAULT):** SP logic translated to C# handler/query code
* **Call Stored Procedures:** Keep SPs in the database and call them from handlers — generates database migration scripts

### Task 3: Complete Handler Business Logic

**Goal:** Implement handler Execute method with orchestration from extraction features\
**User provides:** Feature name (e.g., CreateSchedule), extraction JSON

### Task 4: Complete Query Implementations

**Goal:** Implement query filters, includes, and projections from extraction features\
**User provides:** Module or entity name, extraction JSON with GETPAGEDLIST/GETLIST features

### Task 5: Complete Validation Plugins

**Goal:** Implement pre-bus validation logic from extraction validations\
**User provides:** Feature name, extraction JSON validations section

### Task 6: Complete DTOs and Mappers

**Goal:** Fill in generated DTOs with properties and validation annotations from extraction, then create mapper expressions\
**User provides:** Entity name, extraction JSON domain services

### Task 7: Complete Workflow States

**Goal:** Implement workflow state pattern from extraction workflow/status information\
**User provides:** Entity name, extraction JSON or Markdown with workflow/status information

### Task 8: Complete Event Subscribers

**Goal:** Implement event reactions from extraction events and subscribers\
**User provides:** Feature name, extraction JSON events/subscribers section

### Task 9: Add Legacy Name Retention

**Goal:** Add `[Table]` and `[Column]` annotations for legacy database compatibility\
**User provides:** Entity name or "all entities", extraction JSON with originalName fields

### Task 10: Generate Blazor UI from Extraction — Complete Module

**Goal:** Create the full Blazor FluentUI v4.x UI stack for a module — REST client, DTOs, dialog, list page, navigation — from extraction JSON or API project discovery\
**User provides:** Module name (e.g., "Products"), extraction JSON files or FlexBase API project\
**User says:** "Generate Blazor pages for the Products module"

**What gets generated:**

1. UI DTOs (list + detail with validation annotations)
2. REST client service with CRUD methods
3. DI registration
4. Edit dialog (view/edit/create modes)
5. List page (DataGrid with search, filter, CRUD)
6. Sidebar/navigation entry

### Task 11: Generate Angular UI from Extraction

**Goal:** Create Angular components and services from extraction JSON\
**User provides:** Module or entity name, extraction JSON, target Angular project

### Task 12: Generate React UI from Extraction

**Goal:** Create React components and hooks from extraction JSON\
**User provides:** Module or entity name, extraction JSON, target React project

### Task 13: Complete Entire Module (API + UI)

**Goal:** End-to-end implementation of a module — all domain models, handlers, queries, validations, DTOs, and UI\
**User provides:** Module name, all extraction JSON files, target UI framework

**Implementation order:**

1. Domain models → DTOs & mappers → Queries → Validations → Handlers → Subscribers → UI → Build & verify

***

## DataStore, AI & Email Provider Integration

These prompts add non-relational data store, AI, or email operations into FlexBase handlers, queries, subscribers, and validation plugins. Each provider follows the same pattern: inject the bridge interface, call the provider-specific operations, and let the MCP guide handle the rest.

> **Tip — Operation type for subscribers & validation plugins:** Handlers and queries have an explicit operation type (CREATE, UPDATE, GETPAGEDLIST, etc.). Subscribers and validation plugins **infer the operation from the class/event name** (e.g., `OnOrderCreated...` → Create). If the name is ambiguous, specify the operation explicitly in your prompt: *"...for **Update** operation using Document Store"*.

***

### Document Store (CosmosDB, MongoDB, DynamoDB, RavenDB)

Use when a feature needs to store, retrieve, or query JSON documents in a NoSQL database.

**Handler — Create/Update/Delete a document:**

```
Implement the [FeatureName] handler using Document Store for [Create|Update|Delete] operation on [DocumentType] documents
```

**Query — Retrieve documents:**

```
Implement the [FeatureName] query using Document Store to retrieve [DocumentType] documents with filtering and pagination
```

**Subscriber — React to events with document operations:**

```
Implement the [EventName] subscriber using Document Store to [create|update|delete] [DocumentType] documents after the event
```

**Validation Plugin — Validate against document data:**

```
Implement the [FeatureName] validation plugin to check [business rule] against Document Store before [Create|Update]
```

***

### Vector Store (PgVector, Azure AI Search, OpenSearch, Qdrant, Pinecone)

Use when a feature needs similarity search, semantic search, or embedding storage.

**Handler — Store embeddings:**

```
Implement the [FeatureName] handler using Vector Store to generate and store embeddings for [EntityType] content
```

**Query — Similarity search:**

```
Implement the [FeatureName] query using Vector Store to find similar [items/documents] based on a search query with optional filters
```

**Subscriber — Auto-index on changes:**

```
Implement the [EventName] subscriber using Vector Store to update the vector index when [EntityType] is [created|updated|deleted]
```

***

### Graph Store (Neo4j, Apache AGE, Amazon Neptune)

Use when a feature needs relationship traversal, path finding, or connected data queries.

**Handler — Create graph nodes and relationships:**

```
Implement the [FeatureName] handler using Graph Store to create [NodeType] nodes and [RelationshipType] relationships
```

**Query — Traverse relationships:**

```
Implement the [FeatureName] query using Graph Store to find [connections|paths|recommendations] between [NodeType] entities
```

**Subscriber — Maintain graph on entity changes:**

```
Implement the [EventName] subscriber using Graph Store to update graph nodes/relationships when [EntityType] changes
```

***

### Search Store (Elasticsearch, Azure AI Search, Algolia)

Use when a feature needs full-text search, faceted search, or search indexing.

**Handler — Index content:**

```
Implement the [FeatureName] handler using Search Store to index [EntityType] documents for full-text search
```

**Query — Full-text search:**

```
Implement the [FeatureName] query using Search Store to search [EntityType] with full-text, facets, and filters
```

**Subscriber — Auto-index on changes:**

```
Implement the [EventName] subscriber using Search Store to update the search index when [EntityType] is [created|updated|deleted]
```

***

### File Store (Azure Blob, AWS S3, GCP Storage)

Use when a feature needs to upload, download, or manage files in cloud storage.

**Handler — Upload/manage files:**

```
Implement the [FeatureName] handler using File Store to [upload|download|delete] files in [container/bucket] organized by [path strategy]
```

**Query — List/check files:**

```
Implement the [FeatureName] query using File Store to list files in [container] with prefix filtering
```

**Subscriber — Process files after events:**

```
Implement the [EventName] subscriber using File Store to [archive|copy|generate] files when [EntityType] is [created|approved|completed]
```

***

### Time Series Store (TimescaleDB, InfluxDB, Azure Data Explorer)

Use when a feature needs to store or query time-stamped measurements, metrics, or IoT data.

**Handler — Write data points:**

```
Implement the [FeatureName] handler using Time Series Store to write [metric/measurement] data points with tags and timestamp
```

**Query — Aggregate time series data:**

```
Implement the [FeatureName] query using Time Series Store to aggregate [metric] over [time range] grouped by [interval] with optional tag filters
```

**Subscriber — Record metrics on events:**

```
Implement the [EventName] subscriber using Time Series Store to record a [metric] data point when [EntityType] is [created|updated|state-changed]
```

***

### Cache Store (Redis, Memcached, NCache)

Use when a feature needs caching, session storage, or fast key-value lookups.

**Handler — Cache management:**

```
Implement the [FeatureName] handler using Cache Store to [set|invalidate] cache entries for [EntityType] with [duration] TTL
```

**Query — Cache-aside pattern:**

```
Implement the [FeatureName] query using Cache Store with cache-aside pattern — check cache first, fall back to database, then cache the result
```

**Subscriber — Invalidate cache on changes:**

```
Implement the [EventName] subscriber using Cache Store to invalidate cached [EntityType] entries when the entity is [updated|deleted]
```

***

### AI Provider (Azure OpenAI, OpenAI, Anthropic, Gemini, Ollama)

Use when a feature needs chat completions, content generation, classification, embeddings, or streaming AI responses.

**Handler — AI-powered operations:**

```
Implement the [FeatureName] handler using AI Provider to [generate|classify|summarize|extract] [content type] from [input]
```

**Handler — Structured output (typed response):**

```
Implement the [FeatureName] handler using AI Provider with structured output to return a typed [ResponseType] from the AI response
```

**Handler — Streaming response:**

```
Implement the [FeatureName] handler using AI Provider with streaming to send incremental AI responses for [use case]
```

**Query — AI-assisted search (RAG pattern):**

```
Implement the [FeatureName] query using AI Provider + Vector Store for RAG — embed the question, search for context, then generate an answer
```

**Handler — Generate embeddings:**

```
Implement the [FeatureName] handler using AI Provider to generate embeddings for [content] and store them in Vector Store
```

**Subscriber — AI processing after events:**

```
Implement the [EventName] subscriber using AI Provider to [classify|summarize|tag] [EntityType] content when it is [created|updated]
```

**Validation Plugin — AI-assisted validation:**

```
Implement the [FeatureName] validation plugin using AI Provider to check [content quality|appropriateness|classification] before [Create|Update]
```

***

### Email Provider (SMTP, SendGrid, AWS SES, Azure Communication Services)

Use when a feature needs to send emails — notifications, confirmations, alerts, or bulk communications.

**Handler — Send email directly:**

```
Implement the [FeatureName] handler using Email Provider to send a [notification|confirmation|alert] email to [recipient] after [action]
```

**Handler — Send HTML email with attachments:**

```
Implement the [FeatureName] handler using Email Provider to send an HTML email with [attachments/inline images] for [use case]
```

**Handler — Send templated email:**

```
Implement the [FeatureName] handler using Email Provider to send a templated email using template [templateId] with dynamic data for [use case]
```

**Handler — Bulk email:**

```
Implement the [FeatureName] handler using Email Provider to send bulk emails to [recipient list] for [use case — e.g., newsletter, announcements]
```

**PostBus Plugin — Send email after handler completes:**

```
Implement a PostBus plugin for [FeatureName] using Email Provider to send a [notification|confirmation] email after the handler succeeds
```

**Subscriber — Send email on event:**

```
Implement the [EventName] subscriber using Email Provider to send a [welcome|confirmation|alert] email when [EntityType] is [created|approved|cancelled]
```

**Validation Plugin — Validate email before sending:**

```
Implement the [FeatureName] validation plugin using Email Provider to validate email format and deliverability before [Create|Update]
```

***

### Configuration Notes

All DataStore and Provider integrations follow the same pattern:

* **Registration:** Each provider is registered in `Program.cs` / startup using FlexBase's `AddFlex[ProviderType]()` extension methods
* **Environment-specific:** Use Console/InMemory providers for development, real providers for production
* **Bridge interfaces:** Inject the bridge interface (not the raw provider) in handlers, queries, subscribers, and plugins
* **Multiple instances:** Use keyed registration when you need multiple instances of the same provider type (e.g., two different AI models)

***

## Unit Testing (xUnit, NUnit, MSTest)

FlexBase supports **3 test frameworks** across **4 test projects**. The MCP guides detect which framework to use from the existing `.csproj` or from the user's prompt.

### Feature-Level Tests (All 4 Projects)

```
Write unit tests for the [FeatureName] feature in the [ModuleName] module using [xUnit | NUnit | MSTest]. Identify ALL components (domain model, mappers, handlers, validation plugins, queries, subscribers) and generate tests across all 4 test projects per FlexBase_UnitTest_Implementation_Guide.
```

### Module-Level Tests (All Features)

```
Write unit tests for ALL features in the [ModuleName] module using [xUnit | NUnit | MSTest]. For each feature, identify every component and generate tests across all 4 test projects per FlexBase_UnitTest_Implementation_Guide.
```

### DomainModels.Tests — Model & Mapper Tests

```
Write ALL DomainModels.Tests for [FeatureName] using [xUnit | NUnit | MSTest]: domain model tests (defaults, properties) + Create/Update/Delete mapper tests per FlexBase_UnitTest_Implementation_Guide.
```

### Handlers.Tests — Handler, Subscriber & PostBus Tests

```
Write ALL handler tests for [FeatureName] in Handlers.Tests using [xUnit | NUnit | MSTest]: Create, Update, Delete handlers. Mock IRepoFactory, test happy path, event firing, and error scenarios per FlexBase_UnitTest_Implementation_Guide.
```

### PreBus.Tests — Validation Plugin Tests

```
Write ALL validation plugin tests for [FeatureName] in PreBus.Tests using [xUnit | NUnit | MSTest]: Create and Update validation plugins. Test required fields, format validations, and boundary values per FlexBase_UnitTest_Implementation_Guide.
```

### Queries.Tests — Query Tests with DB Strategy

```
Write ALL query tests for [FeatureName] in Queries.Tests using [xUnit | NUnit | MSTest] with [InMemory EF Core | SQLite | Docker SQL Server | Docker PostgreSQL | Podman]: GetById, GetAll, filtered, paged queries per FlexBase_UnitTest_Implementation_Guide.
```

### Test Data Infrastructure

```
Create a test data builder for [FeatureName] entity with fluent API. Include sensible defaults, With*() methods, Build() and BuildAndSeed(IRepoFactory). Also create DTO builders per FlexBase_UnitTest_TestData_Infrastructure_Guide.
```

### DataStore/Provider Feature Tests

```
Write unit tests for [FeatureName] feature using [Document Store | Cache Store | AI Provider | Email Provider | Vector Store] using [xUnit | NUnit | MSTest]. Mock the provider bridge interface per FlexBase_UnitTest_Implementation_Guide.
```

***

## Related

* **API patterns:** [FlexBase API Patterns](/flexbase-mcp-ai-prompts/flexbase-api-guide-prompts)
* **Blazor patterns:** [Blazor FluentUI](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts)
* **Angular patterns:** [Angular UI](/flexbase-mcp-ai-prompts/angular-ui-guide-prompts)
* **React patterns:** [React UI](/flexbase-mcp-ai-prompts/react-js-ui-guide-prompts)


# Domain Original Names Prompts

> **Standalone prompt for applying `[Table]` and `[Column]` EF Core annotations to domain models.**\
> Use this when the user wants to map FlexBase domain models back to their original database table and column names — enabling EF Core migrations to generate the correct schema.
>
> **This is separate from the main implementation completion workflow** — it can be run independently on any FlexBase domain model project that has extraction JSON with `originalName` / `sourceTable` metadata.

## When to Use

* **Legacy migrations** — keeping the original database schema so existing data doesn't require restructuring
* **Brownfield projects** — new FlexBase API layer on top of an existing database
* **Database-first scenarios** — FlexBase domain models must match an existing schema exactly
* **Post-implementation** — can be applied at any time after domain models are generated

## How to Use

Copy-paste any prompt below into your AI agent chat:

**Apply all original names:**

```
Apply original database names to the domain models
```

**Explicit Table/Column request:**

```
Add [Table] and [Column] attributes from the extraction JSON
```

**Legacy schema mapping:**

```
Map domain models to their legacy database schema
```

**EF Core annotation shorthand:**

```
Add EF Core annotations for the original table and column names
```

***

## What It Does

The agent reads the extraction JSON (`*_DomainServices.json`) and applies:

1. **`[Table("name", Schema = "schema")]`** to each domain model class based on `metadata.sourceTable`
2. **`[Column("originalName")]`** to each property where the original column name differs from the property name
3. **FK type fixes** — ensures all foreign key properties are `string` type (not int/Guid)
4. **C# keyword handling** — properties renamed to avoid C# keywords get `[Column]` to preserve the original name
5. **Build verification** — 0 errors after all annotations applied

**Prerequisites:** Domain model `.cs` files must exist (generated by FlexBase Studio) and extraction JSON must contain `originalName` / `sourceTable` metadata.

***

## Related

* **Full implementation completion:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* **Legacy migration extraction:** [Legacy Migration → Markdown](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file)


# Flexbase API Guide Prompts

> Ready-to-use prompts for implementing FlexBase API patterns, conventions, and best practices.

**Important:** Module names should be in **PLURAL** form (e.g., `Applications`, `Candidates`, `Orders`, `Customers`).

***

## How to Use

Tell your AI agent what API task you need. It will load the relevant patterns and conventions automatically.

**Example prompts you can give your AI agent:**

```
Implement the complete Orders feature — DTOs, mapper, query, handler
```

```
Review all Update DTOs to ensure they have the mandatory Id property
```

```
Create a List/Output DTO for the Customer entity
```

```
Add concurrency handling to the CreateBooking handler
```

```
Implement workflow states for the Order entity
```

```
Set up email notifications using SendGrid
```

***

## Critical Rules

These are enforced automatically by the agent:

* **NEVER remove `Id` from Update/SoftDelete/Delete DTOs** — causes silent API failures
* **All ID properties are `string` type** — never Guid or UUID
* **Protected setters** — use domain factory methods, not direct assignment in handlers
* **EF-agnostic queries** — use FlexBase query patterns, not EF Core–specific APIs
* **Workflow states** — use FlexState pattern, not string `Status` columns

***

## Task Catalog

### DTO Tasks

| Task                                 | Goal                                                    |
| ------------------------------------ | ------------------------------------------------------- |
| **Review DTO rules**                 | Summarize all DTO patterns and identify violations      |
| **Create List/Output DTO**           | Create a proper output DTO for an entity                |
| **Create Lookup DTO**                | Create a minimal DTO for lookups/dropdowns              |
| **Create Input DTO (Create/Update)** | Create input DTOs with validation annotations           |
| **Create Action DTO**                | Create DTOs for actions (Submit, Approve, Reject, etc.) |
| **Fix DTO violations**               | Review and fix all DTO rule violations in the project   |
| **Complete empty DTOs**              | Fill in empty/incomplete DTOs based on domain models    |

### Mapper Tasks

| Task                               | Goal                                                |
| ---------------------------------- | --------------------------------------------------- |
| **Create Domain Mapper**           | Map Entity ↔ EntityDto                              |
| **Create Feature Mapper (Output)** | Map Entity → Feature DTO                            |
| **Create Feature Mapper (Input)**  | Map Input DTO → Entity                              |
| **Simplify mappers**               | Remove unnecessary complexity from existing mappers |

### Query & Handler Tasks

| Task                           | Goal                                            |
| ------------------------------ | ----------------------------------------------- |
| **Create Query**               | Implement query with filtering, sorting, paging |
| **Implement Complete Feature** | Full feature: DTO + Mapper + Query/Handler      |

### Domain Model Tasks

| Task                         | Goal                                                |
| ---------------------------- | --------------------------------------------------- |
| **Review Domain Models**     | Verify domain models follow conventions             |
| **Verify Project Structure** | Check folder organization matches FlexBase patterns |

### Workflow & Concurrency Tasks

| Task                             | Goal                                                          |
| -------------------------------- | ------------------------------------------------------------- |
| **Implement FlexState Workflow** | Create workflow states with transitions and role-based access |
| **Add Concurrency Handling**     | Add optimistic concurrency with logical checks                |
| **Make Subscriber Idempotent**   | Add duplicate detection to event subscribers                  |
| **Capacity-Based Booking**       | Implement capacity checks with state transitions              |

### Provider & DataStore Tasks

| Task                      | Goal                                                                 |
| ------------------------- | -------------------------------------------------------------------- |
| **Integrate AI Provider** | Set up AI capabilities (chat, embeddings, streaming)                 |
| **Implement RAG**         | Set up vector store + AI provider for retrieval-augmented generation |
| **Email Notifications**   | Configure email provider for notifications                           |
| **Document Store**        | Set up CosmosDB, MongoDB, or other document stores                   |
| **File Storage**          | Set up Azure Blob, AWS S3, or GCP Storage                            |
| **Multiple AI Providers** | Configure multiple AI providers for different use cases              |
| **Cache Store**           | Set up Redis or other cache providers                                |

### Review Tasks

| Task                        | Goal                                         |
| --------------------------- | -------------------------------------------- |
| **Complete Project Review** | Full audit against all FlexBase API patterns |
| **Sync DTOs with API**      | Compare UI interfaces with API DTOs          |

***

## Usage Tips

1. **Replace placeholders:**
   * `[EntityName]` → Your actual entity name (e.g., `Candidate`, `Order`)
   * `[ModuleName]` → Your actual module name (e.g., `Orders`, `Customers`)
   * `[ProjectName]` → Your actual project name
2. **Common workflow:**
   * Implement complete feature (DTO + Mapper + Handler/Query)
   * Review and fix any violations
   * Generate UI pages from the Blazor/Angular/React guide

***

## Related

* **After building APIs:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* **Build UI:** [Blazor FluentUI](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts) | [Angular](/flexbase-mcp-ai-prompts/angular-ui-guide-prompts) | [React](/flexbase-mcp-ai-prompts/react-js-ui-guide-prompts)


# HIPAA Compliance Prompts

> Ready-to-use prompts for checking HIPAA applicability, reviewing PHI exposure, and creating HIPAA-aligned remediation plans using FlexBase standards.

## How to Use

Tell your AI agent what compliance task you need. The MCP server should load the HIPAA guide together with the relevant FlexBase API, query, handler, DTO, and UI conventions.

**Example prompts you can give your AI agent:**

```
Review the Bookings module for HIPAA applicability using FlexBase standards
```

```
Review the CreateBooking feature for HIPAA compliance and list the missing controls
```

```
Create a HIPAA remediation plan for the Guests module using existing FlexBase patterns
```

```
Review all notification templates in the Payments module for HIPAA disclosure risks
```

```
Review the Blazor UI for the Patient module for PHI overexposure
```

***

## What the Agent Should Check

For HIPAA-relevant modules or features, the review should cover:

* PHI touchpoints in DTOs, handlers, queries, subscribers, UI, notifications, files, and integrations
* minimum-necessary access
* authorization and role separation
* audit trail and traceability
* safe external disclosures
* logging and telemetry leakage
* idempotency and duplicate disclosure risks
* secure handling of files, exports, and notifications

***

## Task Catalog

### 1. HIPAA Applicability Review

**Goal:** Determine whether a module or feature is HIPAA relevant and identify PHI-bearing paths.

**Prompt:**

```
Review the [ModuleName] module for HIPAA applicability using FlexBase standards.

Identify:
- whether the module handles PHI directly, indirectly, or not at all
- all PHI touchpoints across DTOs, handlers, queries, subscribers, notifications, exports, UI pages, and integrations
- whether the current design follows minimum-necessary access

Output:
- applicability verdict
- PHI field classification
- top compliance risks
- required FlexBase changes by artifact type
```

### 2. Single Feature HIPAA Review

**Goal:** Inspect one feature end-to-end for HIPAA exposure and missing safeguards.

**Prompt:**

```
Review the [ModuleName] / [FeatureName] feature for HIPAA compliance using FlexBase patterns.

Inspect:
- request/response DTOs
- query projections
- handler logic
- subscriber side effects
- UI pages/dialogs
- external communications

Produce:
- HIPAA relevance summary
- missing controls
- minimum-necessary violations
- audit trail gaps
- recommended remediation tasks
```

### 3. Create HIPAA Remediation Plan

**Goal:** Generate implementation tasks to harden a module or feature.

**Prompt:**

```
Create a FlexBase implementation plan to make [ModuleName] / [FeatureName] HIPAA compliant.

Include concrete changes for:
- domain/data model
- DTOs
- handlers
- queries
- subscribers
- UI pages/dialogs
- notifications / exports / integrations
- logging / monitoring / operational controls

Follow existing FlexBase standards and avoid inventing non-standard patterns.
```

### 4. DTO Minimum-Necessary Review

**Goal:** Find DTOs that expose more PHI than necessary.

**Prompt:**

```
Review all DTOs used by [ModuleName] for HIPAA minimum-necessary compliance.

Find:
- fields that expose more PHI than needed
- list DTOs that should be split from detail DTOs
- patient/operator/admin DTOs that should be separated
- fields that should be masked or excluded

Return a DTO remediation plan with exact recommended DTO changes.
```

### 5. Query Leakage Review

**Goal:** Ensure queries do not over-return PHI and are properly scoped.

**Prompt:**

```
Review all queries in [ModuleName] for HIPAA and minimum-necessary access.

Check:
- projection discipline
- filter discipline
- tenant/user/role scoping
- list endpoints returning excessive columns
- exports/detail queries needing stronger controls

Return findings ordered by risk and propose FlexBase-compliant query changes.
```

### 6. Handler and Subscriber Review

**Goal:** Review mutations and async flows for authorization, audit, and disclosure safety.

**Prompt:**

```
Review handlers and subscribers for [ModuleName] / [FeatureName] for HIPAA-aligned controls.

Check for:
- authorization enforcement
- audit logging / traceability
- unsafe logging of PHI
- duplicate downstream disclosures
- minimum-necessary outbound payloads
- concurrency and idempotency risks

Return a remediation plan grouped into handlers, subscribers, and operational controls.
```

### 7. Notifications and Integrations Review

**Goal:** Reduce disclosure risk in external communications.

**Prompt:**

```
Review all notifications and external integrations used by [ModuleName] for HIPAA disclosure risk.

Check:
- email templates
- SMS / WhatsApp content
- webhook payloads
- CRM synchronization fields
- exports and downloadable documents

Identify which payload fields should be removed, masked, generalized, or moved behind authenticated retrieval.
```

### 8. Blazor UI PHI Exposure Review

**Goal:** Review screens, dialogs, lists, and messages for PHI overexposure.

**Prompt:**

```
Review the Blazor pages, dialogs, grids, and dashboards for [ModuleName] for HIPAA exposure risks.

Check:
- list pages showing too much PHI
- dialogs loading more data than needed
- badges/toasts/messages leaking sensitive information
- detail pages lacking role separation
- print/export views exposing PHI broadly

Return recommended UI hardening changes using existing FlexBase FluentUI Blazor patterns.
```

### 9. Module-Level HIPAA Checklist

**Goal:** Produce a reusable readiness checklist for a whole module.

**Prompt:**

```
Create a HIPAA readiness checklist for the [ModuleName] module using FlexBase implementation standards.

Group the checklist into:
- PHI identification
- DTO/query minimization
- authorization
- audit trail
- integration controls
- notifications
- file/document access
- logging/monitoring
- verification tests
```

### 10. Release Gate for HIPAA-Relevant Features

**Goal:** Create a pass/fail release gate before shipping a module or feature.

**Prompt:**

```
Generate a pre-release HIPAA compliance gate for [ModuleName] / [FeatureName].

The output should be a release checklist with pass/fail items for:
- API
- UI
- events/subscribers
- integrations
- notifications
- logging and monitoring
- access control
- audit evidence
```

***

## Recommended Output Shape

For best results, ask the agent to respond using this structure:

```
1. Applicability
2. PHI touchpoints
3. Findings ordered by severity
4. Required FlexBase changes by artifact type
5. Verification checklist
```

***

## Related

* [FlexBase API Guide Prompts](/flexbase-mcp-ai-prompts/flexbase-api-guide-prompts)
* [Implementation Completion Prompts](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* [Blazor Fluent UI Guide Prompts](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts)


# Blazor Fluent UI Guide Prompts

> Implement FlexBase UI with Microsoft FluentUI Blazor v4.x: pages, dialogs, data grids, REST clients, design system, and more.

## How to Use

Tell your AI agent what UI you want to build. It will load Blazor conventions and guide sections automatically.

**Example prompts you can give your AI agent:**

```
Create a CRUD list page for Customers with data grid
```

```
Create an edit dialog for the Order entity
```

```
Set up the REST client service for the Products module
```

```
Fix the response deserialization issue in my service
```

```
Review all DTOs and fix missing Id properties
```

```
Implement the complete UI for the Invoices entity
```

***

## Task Catalog

### Theme Setup (One-Time — Do This First)

> Configure the FluentDesignTheme with a business-domain-specific color, admin layout pattern (sidebar + header), CSS design system, and FluentUI providers. **This is the first step before any functional UI work.**

| Task                     | Goal                                                                          |
| ------------------------ | ----------------------------------------------------------------------------- |
| **Setup FlexBase Theme** | Configure domain-themed admin layout + design system CSS + FluentUI providers |

### Setup & Layout Tasks

| Task                             | Goal                                             |
| -------------------------------- | ------------------------------------------------ |
| **Setup FluentUI Providers**     | Configure MainLayout with FluentUI provider tree |
| **Integrate Design System CSS**  | Add FlexBase design tokens, spacing, typography  |
| **Implement FluentStack Layout** | Use FluentStack for horizontal/vertical layouts  |
| **Implement FluentToolbar**      | Command bar with actions, filters, search        |
| **Apply Layout & Spacing**       | Consistent spacing using design system utilities |

### Generate Complete Module UI (End-to-End)

**This is the primary task for module-level UI generation.** One command generates all artifacts.

| Task                                   | Goal                                                           |
| -------------------------------------- | -------------------------------------------------------------- |
| **Generate Blazor pages for {Module}** | Complete module: REST client + DTOs + dialog + list page + nav |

**What gets generated:**

1. UI DTOs (list + detail with validation annotations)
2. REST client service with CRUD methods
3. DI registration
4. Edit dialog (view/edit/create modes)
5. List page (DataGrid with search, filter, CRUD, pagination)
6. Sidebar/navigation entry

### REST Client & Data Tasks

| Task                                | Goal                                                 |
| ----------------------------------- | ---------------------------------------------------- |
| **Create REST Client Service**      | HTTP service with response unwrapping and resilience |
| **Review REST Client Services**     | Audit existing services for convention violations    |
| **Fix Response Deserialization**    | Resolve JSON deserialization issues                  |
| **Diagnose Deserialization Errors** | Debug response handling failures                     |

### Dialog Tasks

| Task                     | Goal                                        |
| ------------------------ | ------------------------------------------- |
| **Create Edit Dialog**   | Three-mode dialog (view/edit/create)        |
| **Create View Dialog**   | Read-only detail dialog                     |
| **Create Lookup Dialog** | Search/select dialog for foreign key fields |

### Page Tasks

| Task                      | Goal                                                    |
| ------------------------- | ------------------------------------------------------- |
| **Create CRUD List Page** | DataGrid with pagination, sorting, search, CRUD actions |
| **Create Detail Page**    | Entity detail view with related data                    |

### UX Pattern Tasks

| Task                         | Goal                                            |
| ---------------------------- | ----------------------------------------------- |
| **Loading States**           | Skeleton loading, spinners, three-state pattern |
| **Validation Error Display** | Form validation with field-level messages       |
| **Toast Notifications**      | Success/error/warning toast messages            |
| **Confirmation Dialogs**     | Delete/action confirmation patterns             |
| **Breadcrumbs**              | Page breadcrumb navigation                      |

### Authentication Tasks

| Task                         | Goal                                   |
| ---------------------------- | -------------------------------------- |
| **Token Validation Service** | Implement token storage and validation |
| **Logout Pattern**           | Implement proper logout flow           |

### Critical DTO Rules

| Task                           | Goal                                          |
| ------------------------------ | --------------------------------------------- |
| **Verify Update DTOs Have Id** | Audit all Update/Delete DTOs for mandatory Id |
| **Review DTO ID Types**        | Ensure all IDs are string type                |

***

## Related

* **API patterns (build API first):** [FlexBase API Patterns](/flexbase-mcp-ai-prompts/flexbase-api-guide-prompts)
* **Generate UI from extraction JSON:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* **Angular alternative:** [Angular UI](/flexbase-mcp-ai-prompts/angular-ui-guide-prompts)
* **React alternative:** [React UI](/flexbase-mcp-ai-prompts/react-js-ui-guide-prompts)


# Angular UI Guide Prompts

> Implement FlexBase UI with Angular: services, components, forms, dialogs, authentication, API response handling, and more.

## How to Use

Tell your AI agent what Angular UI you want to build. It will load the right conventions and guide sections automatically.

**Example prompts you can give your AI agent:**

```
Create the Angular service for the Products module
```

```
Build a list component with pagination for Customers
```

```
Set up the authentication interceptor
```

```
Fix the API response unwrapping in my base service
```

```
Create a reactive form with validation for Order editing
```

```
Implement the complete Angular UI for Invoices
```

***

## Task Catalog

### Critical Rules (Applied Automatically)

* **NEVER remove `id` from Update/Delete DTOs** — causes silent API failures
* **All IDs are `string` type** in TypeScript interfaces
* **ApiResponse\<T> wrapper** — always unwrap `.result` from API responses

***

### Service Tasks

| Task                        | Goal                                                     |
| --------------------------- | -------------------------------------------------------- |
| **Create Base API Service** | HttpClient base with response unwrapping, error handling |
| **Create Module Service**   | Entity-specific service extending base                   |
| **Review API Services**     | Audit services for pattern violations                    |

### Authentication Tasks

| Task                       | Goal                               |
| -------------------------- | ---------------------------------- |
| **Token Storage Service**  | Secure token storage and retrieval |
| **Authentication Service** | Login/logout/refresh token flows   |
| **HTTP Auth Interceptor**  | Attach bearer token to requests    |
| **Error Interceptor**      | Global HTTP error handling         |

### Component Tasks

| Task                              | Goal                                           |
| --------------------------------- | ---------------------------------------------- |
| **Create List Component**         | Data table with pagination, sorting, filtering |
| **Create Reactive Form**          | Form with FormBuilder, validation              |
| **Autocomplete for Foreign Keys** | Lookup/search for related entities             |

### Dialog Tasks

| Task                        | Goal                       |
| --------------------------- | -------------------------- |
| **PrimeNG Dialog**          | Modal dialog with PrimeNG  |
| **Angular Material Dialog** | Modal dialog with Material |

### Routing & State Tasks

| Task                    | Goal                                  |
| ----------------------- | ------------------------------------- |
| **Configure Routes**    | Module routing setup                  |
| **Service-Based State** | State management with BehaviorSubject |
| **NgRx State**          | Redux-style state with NgRx           |

### Complete Implementation Tasks

| Task                        | Goal                                     |
| --------------------------- | ---------------------------------------- |
| **Complete Entity UI**      | Full UI: list + form + service + routing |
| **Complete Project Review** | Full audit against Angular guide         |
| **Sync DTOs with API**      | Compare Angular interfaces with API DTOs |

***

## Related

* **API patterns (build API first):** [FlexBase API Patterns](/flexbase-mcp-ai-prompts/flexbase-api-guide-prompts)
* **Generate UI from extraction JSON:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* **Blazor alternative:** [Blazor FluentUI](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts)
* **React alternative:** [React UI](/flexbase-mcp-ai-prompts/react-js-ui-guide-prompts)


# React Js UI Guide Prompts

> Implement FlexBase UI with React: hooks, services, forms, dialogs, authentication, API response handling, and more.

## How to Use

Tell your AI agent what React UI you want to build. It will load the right conventions and guide sections automatically.

**Example prompts you can give your AI agent:**

```
Create the API service for the Products module
```

```
Build a list component with pagination for Customers
```

```
Create a custom hook for the Orders API
```

```
Set up the authentication context
```

```
Fix the API response unwrapping in my base service
```

```
Create a form with React Hook Form for Order editing
```

```
Implement the complete React UI for Invoices
```

***

## Task Catalog

### Critical Rules (Applied Automatically)

* **NEVER remove `id` from Update/Delete DTOs** — causes silent API failures
* **All IDs are `string` type** in TypeScript interfaces
* **ApiResponse\<T> wrapper** — always unwrap `.result` from API responses

***

### Service Tasks

| Task                        | Goal                                                      |
| --------------------------- | --------------------------------------------------------- |
| **Create Base API Service** | Axios/fetch base with response unwrapping, error handling |
| **Create Module Service**   | Entity-specific service extending base                    |
| **Create Custom Hook**      | useEntity hook wrapping API calls                         |
| **Review API Services**     | Audit services for pattern violations                     |

### Authentication Tasks

| Task                       | Goal                                   |
| -------------------------- | -------------------------------------- |
| **Token Storage Service**  | Secure token storage and retrieval     |
| **Authentication Service** | Login/logout/refresh token flows       |
| **Auth Context**           | React Context for authentication state |

### Component Tasks

| Task                              | Goal                                           |
| --------------------------------- | ---------------------------------------------- |
| **Create List Component**         | Data table with pagination, sorting, filtering |
| **Create Form (React Hook Form)** | Form with validation                           |
| **Autocomplete for Foreign Keys** | Lookup/search for related entities             |

### Dialog Tasks

| Task                       | Goal                          |
| -------------------------- | ----------------------------- |
| **Create Dialog Service**  | Centralized dialog management |
| **Create Modal Component** | Modal with form/view content  |

### Routing & State Tasks

| Task                        | Goal                            |
| --------------------------- | ------------------------------- |
| **Configure Routes**        | React Router setup              |
| **Private Route Component** | Auth-protected routes           |
| **Context API State**       | State with Context + useReducer |
| **Redux State**             | Redux Toolkit state management  |

### Complete Implementation Tasks

| Task                        | Goal                                     |
| --------------------------- | ---------------------------------------- |
| **Complete Entity UI**      | Full UI: list + form + service + routing |
| **Complete Project Review** | Full audit against React guide           |
| **Sync DTOs with API**      | Compare React interfaces with API DTOs   |

***

## Related

* **API patterns (build API first):** [FlexBase API Patterns](/flexbase-mcp-ai-prompts/flexbase-api-guide-prompts)
* **Generate UI from extraction JSON:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* **Blazor alternative:** [Blazor FluentUI](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts)
* **Angular alternative:** [Angular UI](/flexbase-mcp-ai-prompts/angular-ui-guide-prompts)


# Legacy Migration Prompts - md file

> Analyze legacy application source code, extract modules, features, validations, and domain services, and produce FlexBase-ready Markdown and JSON.

## How to Use

Point your AI agent at the legacy project folder. It will auto-detect the platform, load the appropriate analysis patterns, and extract all migration artifacts.

**Example prompts you can give your AI agent:**

```
Migrate this legacy application to FlexBase
```

```
Analyze this legacy codebase and extract all modules and features
```

```
Migrate this PowerBuilder application to FlexBase
```

```
Migrate this legacy application to FlexBase — extract stored procedures and triggers too
```

```
Convert this Java Spring Boot application to FlexBase
```

***

## Key Rules (Applied Automatically)

The agent loads migration conventions via MCP tools. Key rules:

* **All names PascalCase** — modules, features, validations, events, subscribers, domain services
* **Module names PLURAL** (e.g., `Orders`, `Customers`, `Payments` — NOT `OrderManagement`)
* **Feature names operation-centric** (e.g., `CreateOrder`, `UpdateOrder`, `GetOrderById`)
* **All `description` fields ≤150 characters**
* **Domain entities include `metadata.originalName`** — lowercase original table/source name
* **Events include conditions** — `OnSuccess` (primary) or `OnFailed` (primary)
* **Large files split automatically** — per-module Markdown and JSON files

***

## Supported Platforms

The agent auto-detects the legacy platform from project file signatures:

| Platform              | Detection                                |
| --------------------- | ---------------------------------------- |
| PowerBuilder          | `.pbl`, `.pbt`, `.pbproj` files          |
| .NET (C#/VB.NET)      | `.csproj`, `.sln`, `.vbproj` files       |
| Java / Spring         | `pom.xml`, `build.gradle` files          |
| Python / Django/Flask | `manage.py`, `requirements.txt` files    |
| PHP / Laravel/Symfony | `composer.json`, `artisan` files         |
| Ruby on Rails         | `Gemfile`, `config/routes.rb` files      |
| JavaScript / Node.js  | `package.json` with Express/Nest markers |

After detection, the agent reports the detected platform, UI framework, and analysis strategy.

***

## Extraction Modes

**With Database Access (Recommended):**

* Agent auto-discovers database connection from config files
* Complete entity definitions with FK relationships and column metadata
* FK chain analysis discovers junction tables and lookups

**Without Database Access (Artifact-Only):**

* Extracts from source code artifacts only
* Flags potential gaps for user review

***

## Prompts

The extraction prompts are organized into dedicated files:

| File                                                                                                         | Contents                                                         |
| ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| [Legacy Migration → Markdown](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file)                     | Markdown extraction (modules, features, events, domain services) |
| [Legacy Migration → JSON](/flexbase-mcp-ai-prompts/legacy-migration-prompts-json-file)                       | JSON generation                                                  |
| [PowerBuilder Project Analysis](/flexbase-mcp-ai-prompts/legacy-migration-pb-analysis-prompts)               | PB format detection & reading                                    |
| [Stored Procedure & Trigger Extraction](/flexbase-mcp-ai-prompts/legacy-migration-stored-procedures-prompts) | SP/trigger extraction and mapping                                |

***

## Recommended Workflow

1. **Auto-detect** the legacy platform (automatic)
2. **Extract to Markdown** first (review & refine)
3. **Generate JSON** from reviewed extraction
4. **Import JSON** into FlexBase Studio

***

## Related

* **BRD extraction:** [BRD → Markdown](/flexbase-mcp-ai-prompts/brd-extraction-prompts-md-file) | [BRD → JSON](/flexbase-mcp-ai-prompts/brd-extraction-prompts-json-file)
* **After extraction:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)
* **UI generation:** [Blazor](/flexbase-mcp-ai-prompts/blazor-fluent-ui-guide-prompts) | [Angular](/flexbase-mcp-ai-prompts/angular-ui-guide-prompts) | [React](/flexbase-mcp-ai-prompts/react-js-ui-guide-prompts)


# Legacy Migration Prompts - json file

> Generate FlexBase JSON import files from legacy application code (or from previously extracted Markdown).

## How to Use

Tell your AI agent what you need. It will load the JSON structure rules and conventions automatically.

**Example prompts you can give your AI agent:**

```
Generate a FlexBase JSON import file from this legacy codebase
```

```
Convert the legacy extraction markdown to FlexBase JSON
```

```
Create JSON for just the domain services from this legacy app
```

```
Generate FlexBase JSON from this PowerBuilder application
```

***

## Task Catalog

### Task 1: Quick JSON Generation

**Goal:** Generate a complete FlexBase JSON import file with all defaults applied\
**User provides:** Legacy code folder or existing extraction markdown\
**Output:** `[ProjectName]_Flexbase_Import.json`

### Task 2: Complete JSON with Verification

**Goal:** Generate JSON with explicit verification of all structure rules\
**User provides:** Legacy code folder or existing extraction markdown\
**Output:** `[ProjectName]_Flexbase_Import.json` + verification checklist

### Task 3: Modules JSON Only

**Goal:** Generate only the modules array\
**User provides:** Legacy code folder or existing extraction markdown\
**Output:** `[ProjectName]_Modules.json`

### Task 4: Domain Services JSON Only

**Goal:** Generate only the consolidated domain services array\
**User provides:** Legacy code folder or existing extraction markdown\
**Output:** `[ProjectName]_DomainServices.json`

### Task 5: Domain Services with Properties

**Goal:** Generate domain services JSON with full attribute, relationship, and index definitions\
**User provides:** Legacy code folder or existing extraction markdown\
**Output:** `[ProjectName]_DomainServices.json` — includes attributes, relationships, and indexes per entity

### Task 6: Complete Legacy Application JSON (Any Language)

**Goal:** Generate FlexBase JSON from any legacy application using platform-specific mapping\
**User provides:** Legacy project folder + optionally database connection for FK chain analysis\
**Output:** `[ProjectName]_Flexbase_Import.json` with platform-specific metadata

The agent auto-detects the platform (PowerBuilder, .NET, Java, Python, PHP, Ruby, Node.js) and maps source artifacts to FlexBase components automatically.

### Task 7: UI-Enriched JSON Generation

**Goal:** Generate FlexBase JSON with screen/UI metadata on each feature\
**User provides:** Legacy code folder with UI (web pages, desktop forms, DataWindows)\
**Output:** JSON with `metadata.screenFlow` on UI-facing features

### Task 8: Screen Definition JSON Generation

**Goal:** Generate screen definitions with controls referencing features\
**User provides:** Legacy code folder with UI or existing extraction markdown with screen flow data\
**Output:** `[ProjectName]_[ModuleName]_Screens.json` — one per module

***

## Key Rules (Applied Automatically)

* **3-section JSON structure** (4 sections when UI screens are present): `modules`, `domainServices`, `modulesWithFeatures`, `modulesWithScreens`
* **Every operation = one feature** — no operations array inside features
* **Module names PLURAL** PascalCase
* **Files auto-split when large** — per-module JSON files + full combined import

***

## Related

* **Extraction first:** [Legacy Migration → Markdown](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file)
* **PowerBuilder analysis:** [PowerBuilder Project Analysis](/flexbase-mcp-ai-prompts/legacy-migration-pb-analysis-prompts)
* **SP extraction:** [Stored Procedure & Trigger Extraction](/flexbase-mcp-ai-prompts/legacy-migration-stored-procedures-prompts)
* **After import:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)


# PowerBuilder Project Analysis Prompts

> Auto-detect PowerBuilder project format (Exported Solution vs Binary Workspace), read source files appropriately, and extract complete migration artifacts.

## How to Use

Point your AI agent at a PowerBuilder project folder. It will auto-detect the format and read source files accordingly.

**Example prompts you can give your AI agent:**

```
Analyze this PowerBuilder project folder for FlexBase migration
```

```
Read this PowerBuilder application and extract all DataWindows, windows, and user objects
```

```
Detect the PowerBuilder format and extract migration data from this folder
```

***

## PowerBuilder Project Formats

PowerBuilder projects exist in two distinct formats:

| Format                | What It Means                                                              | Analysis Depth                                                       |
| --------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| **Exported Solution** | `.pbl` entries are folders with text source files (`.srd`, `.sru`, `.srw`) | Full source analysis — complete extraction                           |
| **Binary Workspace**  | `.pbl` entries are binary files                                            | Limited to config/metadata files — export PBLs for complete analysis |

The agent auto-detects the format and reports it to you before proceeding.

***

## What Gets Extracted

**From Exported Solutions (full analysis):**

* DataWindow definitions → domain entities with attributes and relationships
* Window scripts → features (CRUD operations, navigation)
* User objects → services and utilities
* Menu/RibbonBar → module and feature structure
* Config files → database connection, settings
* Post-COMMIT calls → events and subscribers

**From Binary Workspaces (limited):**

* Library list from `.pbt` → module boundaries
* Config files, RibbonBar XML, theme JSON, README
* Database schema (if DB access available)

***

## Database Access

For complete extraction, provide database access via one of:

* Connection string in the prompt
* Config.ini in the PB app folder (auto-discovered)
* "No database access available" for artifact-only mode

With DB access, the agent performs FK chain analysis to discover all related entities, junction tables, and lookup tables.

***

## Related

* **General migration:** [Legacy Migration → Markdown](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file)
* **SP extraction:** [Stored Procedure & Trigger Extraction](/flexbase-mcp-ai-prompts/legacy-migration-stored-procedures-prompts)
* **JSON generation:** [Legacy Migration → JSON](/flexbase-mcp-ai-prompts/legacy-migration-prompts-json-file)


# Legacy Migration Stored Procedures Prompts

> Extract stored procedures, triggers, computed columns, and embedded SQL patterns from legacy databases and source code. Map them to FlexBase features and subscribers.

## How to Use

This prompt is loaded automatically when the user says "extract stored procedures and triggers too" alongside a legacy migration request.

**Example prompts:**

```
Migrate this legacy application to FlexBase — extract stored procedures and triggers too
```

```
Extract the stored procedures and triggers from this database
```

```
Include database triggers in the migration analysis
```

***

## What Gets Extracted

The agent queries the database system catalogs and analyzes source code to extract:

| Category                   | What the Agent Finds                                             |
| -------------------------- | ---------------------------------------------------------------- |
| **Stored Procedures**      | All SPs in the database — not just ones referenced by app code   |
| **Triggers**               | INSERT, UPDATE, DELETE triggers on all tables                    |
| **Computed Columns**       | Database-level computed expressions                              |
| **Embedded SQL**           | Non-SP SQL patterns in application source code                   |
| **Validations from SPs**   | Guard clauses, existence checks, business rules inside SP bodies |
| **Business Flow from SPs** | Conditional logic, state transitions, cross-table updates        |

**Important:** The agent extracts ALL stored procedures from the database, even those not directly referenced by the application. Unmapped SPs are flagged for review.

***

## SP Migration Strategy

| Strategy                   | When Used                                         | What Happens                                            |
| -------------------------- | ------------------------------------------------- | ------------------------------------------------------- |
| **Move to Code** (DEFAULT) | Always, unless user overrides                     | SP logic translated to C# handler/query code in Phase 3 |
| **Keep Stored Procedure**  | User explicitly says "keep the stored procedures" | SP remains in database, handler calls it at runtime     |
| **Mixed**                  | Per-feature control                               | Some SPs move to code, others stay in database          |

***

## Trigger Mapping

| Trigger Type       | FlexBase Mapping                      |
| ------------------ | ------------------------------------- |
| INSERT trigger     | CREATE feature → OnSuccess subscriber |
| UPDATE trigger     | UPDATE feature → OnSuccess subscriber |
| DELETE trigger     | DELETE feature → OnSuccess subscriber |
| INSTEAD OF trigger | Pre-processor on the mapped feature   |

***

## Output

The agent generates `[ProjectName]_StoredProcedures_Triggers.md` containing:

* Complete SP documentation with source code and feature mapping
* Trigger documentation with subscriber mapping
* Computed column mappings
* Validations and business flow extracted from SP bodies
* Unmapped SPs/triggers flagged for review
* Migration strategy summary

**Supported databases:** SQL Server, PostgreSQL, Oracle, MySQL, DB2, SQLite

***

## Related

* **General migration:** [Legacy Migration → Markdown](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file)
* **PowerBuilder analysis:** [PowerBuilder Project Analysis](/flexbase-mcp-ai-prompts/legacy-migration-pb-analysis-prompts)
* **After extraction:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)


# BRD Extraction Prompts - md file

> Extract modules, features, validations, domain services, events, subscribers, workflow states, and generate JSON from Business Requirements Documents (BRDs).

## How to Use

Tell your AI agent what you need. It will load the extraction conventions and rules automatically from the MCP server.

**Example prompts you can give your AI agent:**

```
Analyze this BRD and extract all modules and features to Markdown
```

```
Generate FlexBase JSON import files from this BRD
```

```
Extract domain services with full attributes and relationships from this BRD
```

```
Extract workflow states for all entities that have status columns
```

***

## Key Rules (Applied Automatically)

The agent loads complete extraction conventions via MCP tools. These are the most important rules to be aware of:

* **Module names must be PLURAL** PascalCase (e.g., `Orders`, `Customers`, `Payments`)
* **All names must be PascalCase** — modules, features, validations, events, subscribers, domain services
* **Every operation = one feature** — `CreateUser`, `UpdateUser`, `GetUserById` are 3 separate features
* **Valid operation types:** CREATE, UPDATE, DELETE, SOFTDELETE, GETPAGEDLIST, GETLIST, GETBYID, GETSINGLE (READ is NOT valid)
* **featureType:** WebAPI (user-initiated) or CronJob (scheduled)
* **isEventual:** `false` for GET operations, `true` for mutating operations (unless time-sensitive like financial deductions)
* **Events** must include conditions: `OnSuccess` (primary) or `OnFailed` (primary)
* **Only complex validations** in JSON — skip simple attribute validations (Required, MaxLength, email format)
* **Large files are split automatically** — per-module Markdown and JSON files

***

## Prompts

The extraction prompts are organized into dedicated files:

| File                                                                                 | Contents                                                         |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| [BRD Extraction → Markdown](/flexbase-mcp-ai-prompts/brd-extraction-prompts-md-file) | Markdown extraction (modules, features, events, domain services) |
| [BRD Extraction → JSON](/flexbase-mcp-ai-prompts/brd-extraction-prompts-json-file)   | JSON generation (quick, complete, focused modules/services)      |

***

## Related

* **Legacy Migration:** [Legacy Migration → Markdown](/flexbase-mcp-ai-prompts/legacy-migration-prompts-md-file) | [Legacy Migration → JSON](/flexbase-mcp-ai-prompts/legacy-migration-prompts-json-file)
* **New Application:** [New Application → Markdown](/flexbase-mcp-ai-prompts/new-application-add-moduels-features-to-existing-application-prompts-md-file) | [New Application → JSON](/flexbase-mcp-ai-prompts/new-application-add-moduels-features-to-existing-application-prompts-json-file)
* **After extraction:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)


# BRD Extraction Prompts - json file

> Generate FlexBase JSON import files from a BRD (or from previously extracted Markdown).

## How to Use

Tell your AI agent what you need. It will load JSON structure rules and conventions automatically.

**Example prompts you can give your AI agent:**

```
Generate a FlexBase JSON import file from this BRD
```

```
Create the JSON for just the Orders module
```

```
Extract domain services to JSON with all properties
```

```
Convert this BRD extraction markdown to FlexBase JSON
```

***

## Task Catalog

### Task 1: Quick JSON Generation

**Goal:** Generate a complete FlexBase JSON import file with all defaults applied\
**User provides:** BRD file or existing extraction markdown\
**Output:** `[ProjectName]_Flexbase_Import.json`

### Task 2: Complete JSON with Verification

**Goal:** Generate JSON with explicit verification of all rules and structure\
**User provides:** BRD file or existing extraction markdown\
**Output:** `[ProjectName]_Flexbase_Import.json` + verification checklist

### Task 3: Modules JSON Only

**Goal:** Generate only the modules array\
**User provides:** BRD file or existing extraction markdown\
**Output:** `[ProjectName]_Modules.json`

### Task 4: Domain Services JSON Only

**Goal:** Generate only the consolidated domain services array\
**User provides:** BRD file or existing extraction markdown\
**Output:** `[ProjectName]_DomainServices.json`

### Task 5: Domain Services with Properties

**Goal:** Generate domain services JSON with full attribute, relationship, and index definitions\
**User provides:** BRD file or existing extraction markdown\
**Output:** `[ProjectName]_DomainServices.json` — includes attributes, relationships, and indexes per entity

### Task 6: UI-Enriched JSON Generation

**Goal:** Generate FlexBase JSON with screen/UI metadata on each feature, capturing UI structure from BRD wireframes or derived from feature patterns\
**User provides:** BRD (with or without UI descriptions) or previously extracted Markdown\
**Output:** `[ProjectName]_Flexbase_Import.json` with `metadata.screenFlow` on every UI-facing feature

### Task 7: Screen Definition JSON Generation

**Goal:** Generate screen definitions with controls referencing features\
**User provides:** BRD (with UI descriptions or wireframes) or existing extraction markdown with screen flow data\
**Output:** `[ProjectName]_[ModuleName]_Screens.json` — one per module

***

## Key Rules (Applied Automatically)

* **3-section JSON structure** (4 sections when UI screens are present): `modules`, `domainServices`, `modulesWithFeatures`, `modulesWithScreens`
* **Every operation = one feature** — no operations array inside features
* **Module names PLURAL** PascalCase
* **Only complex validations** in JSON — skip simple attribute validations
* **Files auto-split when large** — per-module JSON files + full combined import

***

## Related

* **Markdown extraction first:** [BRD Extraction → Markdown](/flexbase-mcp-ai-prompts/brd-extraction-prompts-md-file)
* **After import:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)


# New Application / Add Moduels-Features to Existing Application Prompts - md file

> Design new applications or add modules/features to existing applications using DDD principles, and generate structured Markdown output.

## When to Use

* User describes a **new business application** they want to build
* User wants to **add new modules** to an existing application
* User wants to **add new features** to an existing module
* User explains **business flows or processes** without existing code/BRD

## How to Use

Tell your AI agent what you want to build. It will apply DDD principles and generate structured FlexBase-ready Markdown.

**Example prompts you can give your AI agent:**

```
Design a new scheduling app for healthcare with patient, provider, and appointment management
```

```
Add a new Payments module to my existing application
```

```
Add invoice generation and reporting features to the Orders module
```

```
Convert these user stories into FlexBase features
```

```
Analyze this business flow and provide a quick FlexBase design
```

***

## Task Catalog

### Task 1: Complete New Application Design

**Goal:** Design an entire new application with multiple modules\
**User provides:** Business application requirements\
**Output:** Organized Markdown with modules, features, validations, events/subscribers, domain services

### Task 2: New Module Design (Add to Existing App)

**Goal:** Design a new module for an existing application\
**User provides:** Module requirements and existing application context\
**Output:** Module Markdown with features, validations, events/subscribers, cross-module integration

### Task 3: New Feature Design (Add to Existing Module)

**Goal:** Design specific features for an existing module\
**User provides:** Feature requirements and target module name\
**Output:** Feature Markdown with validations, events/subscribers per feature

### Task 4: Quick Flow Analysis

**Goal:** Quick analysis of a simple business flow\
**User provides:** Business flow description\
**Output:** Concise Markdown with module, features, entities, validations, events

### Task 5: User Story to Feature Mapping

**Goal:** Convert user stories into FlexBase features\
**User provides:** User stories\
**Output:** Mapped features with operation types, validations, events

### Task 6: API & Integration Design

**Goal:** Design external API integrations\
**User provides:** API descriptions or Swagger/OpenAPI specs\
**Output:** RestServiceModel domain services + integration features

### Task 7: Scheduled Task / CronJob Design

**Goal:** Design automated/scheduled features\
**User provides:** Scheduled process requirements\
**Output:** CronJob features with triggers and subscribers

### Task 8: Event-Driven Architecture Design

**Goal:** Design complex event chains with multi-level subscribers\
**User provides:** Event flow description\
**Output:** Event hierarchy with first-level and second-level subscribers

### Task 9: Screen / UI Flow Design

**Goal:** Design UI layouts and screen flows from requirements\
**User provides:** Application requirements with UI descriptions\
**Output:** Screen flow metadata enriching features with layout information

***

## Key Rules (Applied Automatically)

* **Module names PLURAL** PascalCase (e.g., `Orders`, `Customers`, `Payments`)
* **Feature names operation-centric** PascalCase (e.g., `CreateOrder`, `GetCustomerById`)
* **DDD principles** — bounded contexts → modules, aggregate roots → domain entities
* **Valid operation types:** CREATE, UPDATE, DELETE, SOFTDELETE, GETPAGEDLIST, GETLIST, GETBYID, GETSINGLE
* **featureType:** WebAPI (user-initiated) or CronJob (scheduled)
* **Large files split automatically** — per-module files

***

## Related

* **Generate JSON from Markdown:** [New Application → JSON](/flexbase-mcp-ai-prompts/new-application-add-moduels-features-to-existing-application-prompts-json-file)
* **After extraction:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)


# New Application / Add Moduels-Features to Existing Application Prompts - json file

> Generate FlexBase-ready JSON from new application requirements or module/feature designs following DDD principles.

## When to Use

* You have analyzed business requirements and need **FlexBase JSON output**
* You want to generate JSON **directly from user requirements**
* You need **structured JSON** for FlexBase Studio import

## How to Use

Tell your AI agent what JSON you need. It will load the JSON structure rules and conventions automatically.

**Example prompts you can give your AI agent:**

```
Generate FlexBase JSON for a new healthcare scheduling application
```

```
Create FlexBase JSON for a new Payments module
```

```
Generate domain services JSON with full attributes for my new application
```

```
Convert this application design markdown to FlexBase JSON
```

***

## Task Catalog

### Task 1: Complete Application JSON

**Goal:** Generate JSON for an entire new application\
**User provides:** Business requirements\
**Output:** `[ProjectName]_Flexbase_Import.json`

### Task 2: New Module JSON

**Goal:** Generate JSON for a new module to add to an existing application\
**User provides:** Module requirements\
**Output:** Module JSON with features, validations, events

### Task 3: New Features JSON

**Goal:** Generate JSON for new features in an existing module\
**User provides:** Feature requirements and target module\
**Output:** Features JSON with validations and events

### Task 4: Quick JSON from Requirements

**Goal:** Fast JSON generation from brief requirements\
**User provides:** Brief business description\
**Output:** `[ProjectName]_Flexbase_Import.json`

### Task 5: Domain Services with Full Properties

**Goal:** Generate detailed domain services with attributes, relationships, and indexes\
**User provides:** Entity descriptions or existing analysis\
**Output:** `[ProjectName]_DomainServices.json` with full attribute definitions

### Task 6: UI-Enriched JSON

**Goal:** Generate JSON with screen/UI metadata on features\
**User provides:** Application requirements with UI descriptions\
**Output:** JSON with `metadata.screenFlow` on UI-facing features

### Task 7: Screen Definition JSON

**Goal:** Generate screen definitions with controls referencing features\
**User provides:** Application requirements with UI descriptions\
**Output:** `[ProjectName]_[ModuleName]_Screens.json` — one per module

### Task 8: Incremental Feature Addition JSON

**Goal:** Generate JSON for additional features to merge with existing import\
**User provides:** New feature requirements + existing module context\
**Output:** Per-module feature JSON files

### Task 9: Event-Driven Architecture JSON

**Goal:** Generate JSON with complex event chains and multi-level subscribers\
**User provides:** Event flow description\
**Output:** Features JSON with nested event/subscriber hierarchies

***

## Key Rules (Applied Automatically)

* **3-section JSON structure:** `modules`, `domainServices`, `modulesWithFeatures` (+ `modulesWithScreens` for UI apps)
* **Every operation = one feature** — no operations array inside features
* **Module names PLURAL** PascalCase
* **Only complex validations** in JSON — skip simple attribute validations
* **Files auto-split when large** — per-module JSON files + full combined import

***

## Related

* **Markdown design first:** [New Application → Markdown](/flexbase-mcp-ai-prompts/new-application-add-moduels-features-to-existing-application-prompts-md-file)
* **After import:** [Implementation Completion](/flexbase-mcp-ai-prompts/implementation-completion-prompts)


# Test Cases Prompts

Generate comprehensive manual test cases from **any requirement source** — BRDs, extraction JSON/Markdown, legacy application artifacts, or design documents. Test cases are organized by FlexBase modules and features, with concrete sample data, assumptions, and expected results that a manual QA tester can execute.

## Prerequisites

Your AI agent must have the **FlexBase MCP server** configured. The MCP server provides guides, conventions, and prompt templates that the agent loads automatically when processing your requests.

## Guides & Conventions (Loaded Automatically by MCP)

| Guide                    | MCP Call                                      | Purpose                                                                                            |
| ------------------------ | --------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Manual Test Case Guide   | `getGuideSection("manual-test-cases", ...)`   | Core test case structure, categories per operation type, organization modes                        |
| Postman Collection Guide | `getGuideSection("postman-collection", ...)`  | Generate Postman v2.1 collections with test scripts, pre-request scripts, Newman CI/CD integration |
| Excel Workbook Guide     | `getGuideSection("excel-test-workbook", ...)` | Generate Excel workbooks with priority colors, status dropdowns, per-module sheets                 |
| Conventions              | `getCodeConventions("manual-test-case")`      | Naming rules, field validation derivation, styling rules                                           |

## What Gets Generated

* **Test Case ID convention:** `TC-[MODULE]-[FEATURE]-[NNN]` (module-based) or `TC-PAGE-[GROUP]-[NNN]` (page-based)
* **Priority levels:** P0 (Critical), P1 (High), P2 (Medium), P3 (Low)
* Every test includes: preconditions, assumptions, sample data table, steps, expected results
* **Minimum test counts:** CREATE (14), UPDATE (10), DELETE (7), GETBYID (6), GETPAGEDLIST (9)
* Validation tests always in pass/fail pairs
* Event and subscriber verification tests
* Workflow state transition tests (valid + invalid)
* Files split per module when output is large
* **Output formats:** Markdown files (default) or Excel workbook (.xlsx) with priority colors, status dropdowns, and per-module sheets

***

## Prompts — Module-Based Test Cases

Copy any prompt below, replace placeholders with your values, and paste into your AI agent.

### From a BRD or Requirement Document

```
Analyze this BRD and generate manual test cases organized by module with concrete sample data, assumptions, and expected results for each feature

@[BRD_FILE].md
```

```
Generate manual test cases for the [ModuleName] module from this requirements document. Include positive, negative, boundary, and validation test cases for every feature

@[REQUIREMENTS_FILE].md
```

### From FlexBase Extraction JSON

```
Parse this FlexBase extraction JSON and generate manual test cases for every feature. Derive field validations from domainServices attributes (required, maxLength, type). Include sample test data for every field

@[PROJECT]_Import.json
```

```
Generate manual test cases for the [ModuleName] module from this extraction JSON. Cover all features including events, subscribers, and workflow state transitions

@[PROJECT]_[ModuleName]_Features.json
```

### From FlexBase Extraction Markdown

```
Parse this FlexBase extraction Markdown and generate manual test cases for all modules. Use entity attribute tables to derive field validation tests and sample data

@[PROJECT]_Summary.md
```

```
Generate manual test cases from this per-module extraction Markdown. Include cross-module integration tests for any subscriber chains

@[PROJECT]_[ModuleName].md
```

### From Legacy Application Analysis

```
Analyze this legacy application output and generate manual test cases including data migration verification, trigger-to-subscriber mapping tests, and screen equivalence tests

@[LEGACY_ANALYSIS_FILE].md
```

```
Generate manual test cases from this legacy database schema. Map each table to a module, each CRUD operation to a feature, and each trigger to a subscriber test case

@[DATABASE_SCHEMA].sql
```

### Single Feature — Quick

```
Generate all manual test cases for the [FeatureName] feature in the [ModuleName] module.
Operation type: [CREATE/UPDATE/DELETE/GETBYID/GETPAGEDLIST]
Entity fields: [Field1] (string, max 100, required), [Field2] (int, required), [Field3] (datetime, optional)
Validations: [Validation1 description], [Validation2 description]
Events: [EventName] → Subscribers: [Subscriber1], [Subscriber2]
```

### Gap Analysis — Review Existing Test Cases

```
Review these test cases against the source requirements and identify gaps — missing test categories, uncovered validations, missing event/subscriber tests, and placeholder data that needs concrete values

Requirements: @[REQUIREMENTS_FILE].md
Test Cases: @[TESTCASES_FILE].md
```

### Complete Module Test Suite

```
Generate a complete manual test suite for the [ModuleName] module from this extraction. Output:
1. Summary file with test distribution and global assumptions
2. Test cases for every feature (CREATE, UPDATE, DELETE, GET, GETPAGEDLIST)
3. Cross-module integration tests for events/subscribers
4. Reference data setup needed before testing

@[PROJECT]_Import.json
```

***

## Prompts — Page-Based Test Cases (UI / UX Perspective)

```
Analyze this page inventory and generate page-based test cases organized by page group (PublicCMS, BookingFlow, GuestAccount, AdminCalendar, etc.) with responsive and accessibility checks

@[PAGE_INVENTORY_OR_ESTIMATION_DOC].md
```

```
Generate page-based test cases for the [GroupName] page group. Include page load, user interaction, responsive layout (375px / 768px / 1200px+), and accessibility (tab order, ARIA labels, contrast) checks

@[UI_DESIGNS_OR_WIREFRAMES].md
```

```
Generate both module-based test cases (by API feature) AND page-based test cases (by UI page) from this BRD. Output separate file sets for each perspective

@[BRD_FILE].md
```

***

## Prompts — Excel Workbook Output

```
Analyze this BRD and generate an Excel workbook (.xlsx) with all manual test cases organized by module — include priority colors (P0=red, P1=yellow, P2=green, P3=grey), frozen headers, auto-filters, and status dropdown columns

@[BRD_FILE].md
```

```
Generate a Node.js ExcelJS script that parses all Markdown test case files in TestCases/ and produces a multi-sheet Excel workbook with per-module sheets, priority colors, status dropdowns, and a summary sheet

@TestCases/
```

```
Convert these existing Markdown test case files to an Excel workbook with frozen headers, color-coded priorities, status tracking dropdowns, and per-module sheets

@[PROJECT]_TestCases_*.md
```

### Markdown → Excel Conversion (Existing Test Cases)

```
Parse all page-based test case files in PageTestCases/ and produce an Excel workbook with per-page-group sheets, responsive/accessibility columns, and a summary sheet

@PageTestCases/
```

```
Generate a combined Excel workbook with both module-based tests (from TestCases/) and page-based tests (from PageTestCases/) on separate sheet groups, plus a unified summary sheet

@TestCases/ @PageTestCases/
```

***

## Prompts — Postman Collection Output (API Tests)

```
Generate a Postman Collection v2.1 JSON from these module test case Markdown files — map each test case to an HTTP request with test scripts asserting expected status codes and response bodies. Include environment file with baseUrl and auth token

@TestCases/
```

```
Analyze this BRD and generate a Postman collection with API test requests for every feature — include happy path, validation, boundary, and negative test cases with concrete sample data and test script assertions

@[BRD_FILE].md
```

```
Parse this FlexBase extraction JSON and generate a Postman collection with requests for every feature. Derive request bodies from domainServices attributes and test scripts from expected validation messages

@[PROJECT]_Import.json
```

```
Generate a Postman collection for the [ModuleName] module with requests for all features (CREATE, UPDATE, DELETE, GET, GETPAGEDLIST) including positive, negative, and boundary test cases. Include pre-request scripts for dynamic data and test scripts for assertions

@[PROJECT]_TestCases_[ModuleName].md
```

***

## Examples

| Project                 | Type                                  | Location                                              |
| ----------------------- | ------------------------------------- | ----------------------------------------------------- |
| SSW (Sri Sri Wellbeing) | Module tests (24 modules, 620+ tests) | `Samples/Welbeing/TestCases/`                         |
| SSW                     | Page tests (79 pages, 12 groups)      | `Samples/Welbeing/PageTestCases/`                     |
| SSW                     | Excel generator (markdown → xlsx)     | `Samples/Welbeing/generate-all-module-tests-excel.js` |
| SSW                     | Sample Excel generator                | `Samples/Welbeing/generate-test-excel.js`             |
| KG (KaalGyan Calendar)  | Module tests (13 modules, 114 tests)  | `Samples/KG/TestCases/`                               |
| KG                      | Excel generator (embedded test data)  | `Samples/KG/TestCases/generate-kg-test-excel.js`      |


# Endpoints configuration and Devops prompts


# Estimation Prompts

Generate detailed project estimates for FlexBase applications — per module, per feature, with complexity classification, UI/API split, testing effort, and delivery phasing. Estimates cover the full lifecycle: extraction, code generation, code completion, UI development, unit testing, manual test case generation, and test execution.

## Prerequisites

Your AI agent must have the **FlexBase MCP server** configured. The MCP server provides the estimation guide, conventions, and benchmarks that the agent loads automatically when processing your requests.

## Guides & Conventions (Loaded Automatically by MCP)

| Guide                  | MCP Call                                    | Purpose                                                                         |
| ---------------------- | ------------------------------------------- | ------------------------------------------------------------------------------- |
| Estimation Guide       | `getGuideSection("estimation", ...)`        | Complexity tiers, hour benchmarks, templates, formulas, real project benchmarks |
| API Patterns Guide     | `getGuideSection("api", ...)`               | Feature operation types, handler patterns                                       |
| Manual Test Case Guide | `getGuideSection("manual-test-cases", ...)` | Test case counts per operation type for QA estimation                           |

## What Gets Generated

* **Per-module breakdown** with feature-level hours, complexity tiers, subscriber counts, external dependencies
* **UI estimation** with or without wireframes — per page or heuristic-based
* **Testing breakdown**: unit test generation, manual test case generation, manual test execution (with industry benchmarks)
* **Phase grouping** for incremental delivery planning
* **Project-level roll-up** with category totals (API, UI, Testing, Infrastructure)
* **Complexity classification**: Simple, Medium, Complex, Very Complex per feature
* **External integration** estimated separately from core modules
* **Output formats**: Markdown (default), Excel workbook (.xlsx), or HTML report

***

## Prompts — Full Project Estimation

### From a BRD or Requirement Document

```
Analyze this BRD and generate a complete FlexBase project estimation with per-module, per-feature breakdown. For each feature, classify complexity (Simple/Medium/Complex/Very Complex), estimate FlexBase hours, identify subscribers and external dependencies. Include:
1. API estimation per module with feature-level hours
2. UI estimation (note: wireframes not available — use heuristic)
3. Unit test estimation (features × 0.4 hrs)
4. Manual test case generation (modules × 1.5 hrs)
5. Manual test execution estimate based on test case counts
6. Extraction + code generation phase
7. Project-level roll-up with totals and delivery phases

@[BRD_FILE].md
```

```
Analyze this BRD and produce a detailed estimation. Identify which modules are Simple (CRUD, 0 subscribers), Medium (1-2 validations), Complex (3+ subscribers, external deps), or Very Complex (state machine, background jobs). Output a per-module table with feature count, API hours, UI hours, test hours, and total hours.

@[BRD_FILE].md
```

### From FlexBase Extraction JSON/Markdown

```
Parse this FlexBase extraction and generate a project estimation. For each module, use the feature list and domain service attributes to estimate hours. Count subscribers from events, identify external dependencies from subscriber names. Apply FlexBase hour benchmarks: GETLIST=0.5-1h, CREATE(simple)=1.5-2h, CREATE(complex)=5-14h, UPDATE(simple)=1-1.5h, UPDATE(complex)=4-28h, DELETE=0.5-1h.

@[PROJECT]_Import.json
```

```
Parse this extraction Markdown and produce a per-module estimation with:
- Feature-level breakdown (operation type, complexity, hours, subscribers)
- Module-level summary (total hours, complexity tier, key drivers)
- Testing estimate (unit tests + manual test cases + execution)
- Phase grouping for delivery planning

@[PROJECT]_Summary.md
```

### From Legacy Application Analysis

```
Analyze this legacy application output and estimate the FlexBase migration. For each legacy module:
1. Map legacy features → FlexBase operation types (CREATE, UPDATE, DELETE, GET, GETPAGEDLIST)
2. Identify triggers/procedures → subscriber effort
3. Estimate data migration verification time
4. Identify external system integrations and estimate separately
5. Flag features that increase complexity (state machines, batch jobs, complex reports)

@[LEGACY_ANALYSIS_FILE].md
```

***

## Prompts — API-Only Estimation

### Full API Estimation

```
Generate an API-only estimation for this project. For each module, provide:
1. Feature list with operation type and complexity tier
2. Subscriber count and per-subscriber hour estimate
3. External dependency identification and integration hours
4. Module total in hours and days (at 7 hrs/day)
5. Overall API development total with phase grouping

@[REQUIREMENTS_FILE].md
```

### Single Module API Estimation

```
Estimate the [ModuleName] module API development. It has these features:
[List features with operation types]

For each feature, classify complexity and estimate hours. Identify:
- Which features have subscribers (and how many)
- Which features call external systems
- Whether a state machine is involved
- Background/cron job requirements

Output a feature-level table with hours and a module total.
```

***

## Prompts — UI Estimation

### With Wireframes

```
Analyze these wireframes/mockups and estimate UI development for each page/component. Classify each page as Low (1-3h), Medium (4-7h), High (8-14h), or Very High (14-20h+) complexity. Include:
1. Per-page hours with complexity justification
2. UI infrastructure (one-time): scaffold, theme, REST client, shared components
3. Responsive considerations (if applicable)
4. Which API modules each page depends on
5. UI total hours

@[WIREFRAMES_OR_MOCKUPS].md
```

### Without Wireframes (Heuristic)

```
Generate a UI estimation based on these API modules (no wireframes available). For each module, estimate the admin pages needed using the heuristic:
- Simple module → 1 list/detail page (3-6 hrs)
- Standard entity → 1 list + 1 detail page (8-15 hrs)
- Transactional → 2-3 pages + 1 dialog (15-35 hrs)
- Complex transactional → 3-5 pages + 2 dialogs (30-60 hrs)
- Dashboard/Reports → 1-2 pages (6-14 hrs)

Do NOT bake contingency into per-page hours. Instead, show straight hours and note a recommended contingency % as a separate line item (e.g., +10% with wireframes, +20% without wireframes, +30% for vague requirements). Note which pages would benefit most from wireframe clarity.

Modules: [List modules with complexity tiers]
```

### Public + Admin UI Combined

```
Estimate the full UI for this project including:
1. Public-facing pages (CMS content + hybrid CMS/API + booking flows)
2. Admin pages (per API module using the module-to-page heuristic)
3. UI infrastructure (one-time setup)
4. Shared component library
5. Per-page breakdown with complexity and hours

Note which pages have wireframes and which use the heuristic estimate.

@[BRD_OR_REQUIREMENTS].md
```

### Separate UI Estimation (Standalone)

```
Generate a standalone UI estimation document separate from the API estimation. Organize by:
1. Public pages (grouped by section: CMS, Hybrid, Booking/Account)
2. Admin pages (grouped by module)
3. UI infrastructure (one-time)
4. Per-page: name, route, complexity, hours, API dependencies, notes
5. Total with recommended contingency shown as a separate line item (not baked in)

If wireframes are not available for certain pages, mark them with "⚠️ No wireframe — heuristic estimate" and list what wireframe information would reduce the estimate. Show a recommended contingency % as a separate line, not baked into page hours.

@[BRD_OR_REQUIREMENTS].md
```

***

## Prompts — Testing Estimation

### Unit Test Estimation

```
Estimate unit test effort for this project. For each module:
- Count features by operation type
- Apply: CREATE=0.5-0.75h, UPDATE=0.35-0.6h, DELETE=0.25-0.4h, GETBYID=0.15-0.25h, GETPAGEDLIST=0.25-0.4h per feature
- Calculate module subtotal and project total
- Note: AI generates tests, developer reviews/refines (~8-12% of dev time)

@[PROJECT_EXTRACTION_OR_BRD].md
```

### Manual Test Case + Execution Estimation

```
Estimate manual QA effort for this project:
1. Test case generation: modules × 1.5 hrs (AI-generated, developer-reviewed)
2. Test case count estimate using FlexBase minimums: CREATE=14, UPDATE=10, DELETE=7, GETBYID=6, GETPAGEDLIST=9
3. Test execution (first pass): P0 × 0.4h + P1 × 0.25h + P2 × 0.15h + P3 × 0.1h
4. Regression cycles: first pass × 0.6 (×2 cycles)
5. Defect retest: total cases × 12% defect rate × 0.25h per defect
6. Total QA effort in hours and days

@[PROJECT_EXTRACTION_OR_BRD].md
```

### Combined Testing Estimation

```
Generate a combined testing estimation for this project covering all testing activities:
1. Unit test generation and refinement (per module)
2. Manual test case generation (per module)
3. Manual test case execution — first pass (per module, by priority)
4. Regression cycles (2 cycles at 60% of first pass)
5. Defect discovery and retest
6. Test infrastructure setup (test data, environments)
7. Testing total as percentage of development effort
8. Industry benchmark comparison

@[PROJECT_EXTRACTION_OR_BRD].md
```

***

## Prompts — Module-by-Module Estimation

### Individual Module Estimation

```
Estimate the [ModuleName] module completely:

**API Estimation:**
- Features: [list features with operation types]
- Subscribers: [list or count]
- External deps: [list or "None"]
- State machine: [Yes/No, how many states]

**UI Estimation:**
- Wireframes available: [Yes/No]
- If yes: [describe pages/mockups]
- If no: use heuristic based on module complexity

**Testing Estimation:**
- Unit tests: per-feature calculation
- Manual test cases: count estimate with priority distribution
- Test execution: first pass + regression

Output the complete module estimate in the per-module template format.
```

### Batch Module Estimation (Multiple Modules)

```
Estimate these modules and provide a comparison table:

Module 1: [Name] — [brief description]
Module 2: [Name] — [brief description]
Module 3: [Name] — [brief description]
...

For each module, output:
| Module | Complexity | Features | API Hrs | UI Hrs | Unit Test | TC Gen | TC Exec | Total |

Then provide the project roll-up total.

@[REQUIREMENTS_FILE].md
```

***

## Prompts — Estimation Outputs

### Excel Workbook

```
Generate a Node.js ExcelJS script that produces a professional estimation workbook (.xlsx) for this project with:
1. Effort Breakdown sheet — all modules with #, Item, Route/Scope, Category, Complexity, UI Hrs, API Hrs, Total Hrs, Total Days, Notes
2. Per-phase section headers with color coding
3. Testing section with unit test + manual test breakdowns
4. Summary section with KPIs (total hours, days, weeks, team size)
5. Frozen headers, auto-filters, zebra striping
6. Complexity colors: Simple=green, Medium=amber, Complex=red, Very Complex=purple

@[PROJECT_ESTIMATION].md
```

### HTML Report

```
Generate an HTML estimation report for executive presentation with:
1. Project overview header with key metrics
2. Visual phase timeline (horizontal bar chart)
3. Module comparison table with complexity badges
4. FlexBase vs Traditional comparison callout
5. Cost projection section (configurable hourly rates)
6. Testing effort breakdown
7. Risk factors and open questions with hour impact
8. Professional styling with responsive layout

@[PROJECT_ESTIMATION].md
```

### Markdown Document

```
Generate a comprehensive estimation markdown document for this project with:
1. Executive summary (total hours, weeks, key metrics)
2. Methodology section (FlexBase approach, assumptions, 7h/day)
3. Per-module tables with feature-level breakdown
4. UI estimation (with wireframe availability noted per page)
5. Testing matrix (unit + manual + execution)
6. Phase delivery plan
7. External integration summary
8. Risk register with mitigation and hour impact
9. Open questions requiring stakeholder decisions

@[BRD_OR_EXTRACTION].md
```

***

## Prompts — Comparison & Analysis

### FlexBase vs Traditional Estimation

```
Produce a side-by-side comparison of FlexBase AI-assisted vs Traditional team development for this project:
- FlexBase: 1 dev + AI, 7h/day, 67% generated code, day-1 infrastructure
- Traditional: 6-10 person team, 8h/day, phase-gated, build infrastructure from scratch
- Compare: timeline (weeks), effort (person-days), cost (configurable rates)
- Show what FlexBase provides day-1 that traditional must build (CQRS, events, caching, audit, etc.)

@[BRD_OR_EXTRACTION].md
```

### Gap Analysis (Estimate vs Actual)

```
Compare this project's original estimate against actual hours spent. For each module:
- Estimated hours vs Actual hours
- Variance (% over/under)
- Root cause for significant variances
- Lessons learned for future estimation accuracy

Estimated: @[ORIGINAL_ESTIMATE].md
Actual: @[TIMESHEET_OR_ACTUAL].md
```

***

## Examples

| Project                   | Modules | API Hours | UI Hours  | Total      | Location                                                        |
| ------------------------- | ------- | --------- | --------- | ---------- | --------------------------------------------------------------- |
| SSW (Sri Sri Wellbeing)   | 25      | \~288 hrs | \~370 hrs | \~700 hrs  | `Samples/Welbeing/Analysis/`                                    |
| KG (KaalGyan Calendar)    | 13      | \~180 hrs | TBD       | \~180+ hrs | `Samples/KG/`                                                   |
| SSW Estimation v6 (Excel) | 25      | —         | —         | —          | `Samples/Welbeing/Analysis/generate-module-estimates-v6.js`     |
| SSW Estimation v8 (HTML)  | 25      | —         | —         | —          | `Samples/Welbeing/Analysis/SSW-RFP-Detailed-Estimation-v8.html` |


# Sample Application

**Work in Progress**


# Upgrade Guides


# Flexbase 10

This page contains self-contained upgrade instructions for FlexBase 10 dev builds.

## Upgrade Builds

* [10.0.0-Dev-Build026](#1000-dev-build026) (January 2026)
* [FlexBase 9 to 10 Migration Steps](#flexbase-9-to-10-migration-steps)

***

## 10.0.0-Dev-Build026

### What This Upgrade Changes

* Consolidates exception handling into `FlexExceptionFilter` + `UseFlexExceptionHandler()`
* Adds optional rate limiting support
* Adds optional OpenTelemetry configuration
* Standardizes EF Core feature configuration (Audit Trail, Soft Delete, Async Query Executor)
* Updates generated queries/handlers to use true async (`*AsyncFlex`)
* Adds optional Subscriber Idempotency configuration

***

### Upgrade Steps

#### Step 1: Exception Handling Improvements

**What to change**

1. Replace `FlexStandardExceptionFilter` with `FlexExceptionFilter` in your MVC filter registration.
2. Add `app.UseFlexExceptionHandler()` after CORS.

**Example**

```csharp
builder.Services.AddControllers(config =>
{
    // ... other config
    config.Filters.Add<FlexStandardResponseFilter>();
    config.Filters.Add<FlexExceptionFilter>();
});

var app = builder.Build();

app.UseCors(MyAllowSpecificOrigins);
app.UseFlexExceptionHandler();
```

***

#### Step 2: Rate Limiting Support (Optional)

**What to change**

If you want rate limiting:

```csharp
// builder.Services.AddFlexRateLimiting(builder.Configuration);

var app = builder.Build();

// app.UseFlexRateLimiting();
```

> Keep it commented out if you don't need rate limiting.

***

#### Step 3: OpenTelemetry Configuration (Optional)

**What to change**

If you want OpenTelemetry, wire it from your WebAPI startup (exact method names vary by template):

```csharp
// builder.Services.AddOpenTelemetryForAspNetCore(builder.Configuration, "EndPoint.WebAPI");
```

> Keep it commented out if you don't have an OTLP backend.

***

#### Step 4: EF Core Features Configuration

**What to change**

Create `EfCoreFeaturesConfig.cs` (if you don't already have it) and register it from wherever you build your DB services.

Typical wiring points:

* If you use `*.EndPoint.CommonConfigs/CommonHostConfig.cs`, add:
  * `services.AddFlexEfCoreFeatures(hostingContext.Configuration);`
* Otherwise, add it in your DB configuration method (often `DbEndPointConfig.AddFlexBaseDbServices(...)`).

***

#### Step 5: Async Query Executor

**What to change**

Ensure your EF Core feature registration includes the async query executor, and update queries/handlers to use `*AsyncFlex` methods.

Examples:

```csharp
var customers = await query.ToListAsyncFlex();
var customer = await query.FirstOrDefaultAsyncFlex();
var exists = await query.AnyAsyncFlex();
```

***

#### Step 6: Query Template Updates

**What to change**

In existing generated queries/handlers, update these patterns:

* `.ToList()` + `Task.FromResult(...)` → `await ... .ToListAsyncFlex()` and return directly
* `.FirstOrDefault()` + `Task.FromResult(...)` → `await ... .FirstOrDefaultAsyncFlex()` and return directly

***

#### Step 7: AppSettings Changes Summary

Add these sections if missing (merge into your environment-specific appsettings).

**OpenTelemetry**

```json
"OpenTelemetry": {
  "Enabled": true,
  "ServiceVersion": "1.0.0",
  "OtlpExporter": {
    "Enabled": false,
    "Endpoint": "http://localhost:4317"
  }
}
```

**FlexEfCore**

```json
"FlexEfCore": {
  "AuditTrail": {
    "Enabled": true,
    "IncludeAdded": true,
    "IncludeModified": true,
    "IncludeDeleted": true,
    "CaptureOldValues": true,
    "CaptureNewValues": true
  },
  "SoftDelete": {
    "Enabled": true
  }
}
```

**RateLimiting (Optional)**

```json
"RateLimiting": {
  "Enabled": true,
  "FixedWindow": {
    "Enabled": true,
    "PermitLimit": 100,
    "WindowSeconds": 60,
    "QueueLimit": 0
  },
  "PerUser": {
    "Enabled": true,
    "PermitLimit": 50,
    "WindowSeconds": 60
  },
  "PerIp": {
    "Enabled": true,
    "PermitLimit": 30,
    "WindowSeconds": 60
  }
}
```

***

#### Step 8: Subscriber Idempotency (Optional)

Subscriber idempotency ensures each subscriber processes a given event only once (even if the bus retries delivery).

**Configuration**

```json
"FlexIdempotency": {
  "Enabled": true,
  "StoreType": "Cache",
  "DefaultTimeToLiveDays": 7,
  "KeyPrefix": "flex:idempotency",
  "EnableAutoCleanup": false,
  "CleanupBatchSize": 1000
}
```

```json
"FlexCache": {
  "MaxPayloadBytes": 1048576,
  "DefaultExpirationMinutes": 60
}
```

**Startup wiring**

Call this during service registration (where you register other Flex services):

```csharp
services.AddFlexIdempotency(configuration);
```

> If your solution does not have the EF Core idempotency package/namespace available yet, keep `StoreType` as `Cache`.

***

#### Step 9: AI-Assisted Upgrade Prompt

```
You are upgrading an existing FlexBase application to FlexBase 10.0.0-Dev-Build026.

Goal: Apply ONLY the changes described in this page, and ensure the solution builds.

Tasks:
1) Update appsettings files:
   - Add OpenTelemetry, FlexEfCore.
   - (Optional) Add RateLimiting.
   - (Optional) Add FlexIdempotency and FlexCache.

2) Apply code changes:
   - Exception handling: use FlexExceptionFilter and add app.UseFlexExceptionHandler() after CORS.
   - (Optional) Add rate limiting registration and middleware.
   - Ensure EF Core features are registered via AddFlexEfCoreFeatures(configuration).
   - Update generated queries/handlers to use *AsyncFlex methods.
   - (Optional) Add subscriber idempotency by wiring services.AddFlexIdempotency(configuration).

3) Validate:
   - Run dotnet build for the full solution.
   - If build fails, report the exact error and fix only what’s required for this upgrade.

Constraints:
- Do not add unrelated features.
- Keep changes minimal and consistent with existing solution structure.
```

***

## FlexBase 9 to 10 Migration Steps

These steps help you align an existing FlexBase 9 solution with the FlexBase 10 solution structure.

> The older folder structure is still supported, so you can upgrade and run without doing these immediately. That said, adopting the newer structure typically improves navigation, consistency across modules, and the overall visual organization of the solution.

### Step 1: Folder Structure Alignment

FlexBase 10 introduces a cleaner application structure that groups related concerns together (contracts vs orchestration vs business logic). This is the first recommended step when moving from FlexBase 9 to 10.

#### Target Folder Layout (FlexBase 10)

Below is the recommended **FlexBase 10 folder structure**. Replace `{YourApplication}` with your application name.

```
{SolutionRoot}/
  DevNotes/                       (optional)

  {YourApplication}.Application/
    ControlContracts/
      {YourApplication}.DTOs/
        {YourApplication}.DTOs.csproj
      {YourApplication}.Messages/
        {YourApplication}.Messages.csproj
      {YourApplication}.SharedEvents/
        {YourApplication}.SharedEvents.csproj

    ControlHub/
      {YourApplication}.CronJobs/
        {YourApplication}.CronJobs.csproj
      {YourApplication}.WebControllers/
        {YourApplication}.WebControllers.csproj

    Domain/
      {YourApplication}.CommonLib/
        {YourApplication}.CommonLib.csproj
      {YourApplication}.DomainModels/
        {YourApplication}.DomainModels.csproj
      {YourApplication}.DomainModels.Tests/
        {YourApplication}.DomainModels.Tests.csproj
      {YourApplication}.Mappers/
        {YourApplication}.Mappers.csproj

    DomainHandler/
      {YourApplication}.Handlers/
        {YourApplication}.Handlers.csproj
      {YourApplication}.Handlers.Tests/
        {YourApplication}.Handlers.Tests.csproj
      {YourApplication}.PreBus/
        {YourApplication}.PreBus.csproj
      {YourApplication}.PreBus.Tests/
        {YourApplication}.PreBus.Tests.csproj
      {YourApplication}.Queries/
        {YourApplication}.Queries.csproj
      {YourApplication}.Queries.Tests/
        {YourApplication}.Queries.Tests.csproj
      {YourApplication}.RESTClients/
        {YourApplication}.RESTClients.csproj

    EndPoints/
      DbMigrations/
        {YourApplication}.Migrations.SqlServer/
          {YourApplication}.Migrations.SqlServer.csproj
        {YourApplication}.Migrations.PostgreSql/
          {YourApplication}.Migrations.PostgreSql.csproj
        {YourApplication}.Migrations.Tenant.SqlServer/
          {YourApplication}.Migrations.Tenant.SqlServer.csproj
        {YourApplication}.Migrations.Tenant.PostgreSql/
          {YourApplication}.Migrations.Tenant.PostgreSql.csproj

      {YourApplication}.EndPoint.CommonConfigs/
        {YourApplication}.EndPoint.CommonConfigs.csproj
      {YourApplication}.EndPoint.CronJob/
        {YourApplication}.EndPoint.CronJob.csproj
      {YourApplication}.EndPoint.Handlers.Default/
        {YourApplication}.EndPoint.Handlers.Default.csproj
      {YourApplication}.EndPoint.Subscribers.Default/
        {YourApplication}.EndPoint.Subscribers.Default.csproj
      {YourApplication}.EndPoint.WebAPI/
        {YourApplication}.EndPoint.WebAPI.csproj

    Infrastructure/
      Bus/
        {YourApplication}.Nsb/
          {YourApplication}.Nsb.csproj
      Db/
        {YourApplication}.BaseEF/
          {YourApplication}.BaseEF.csproj
        {YourApplication}.BaseEF.SqlServer/
          {YourApplication}.BaseEF.SqlServer.csproj
        {YourApplication}.BaseEF.PostgreSql/
          {YourApplication}.BaseEF.PostgreSql.csproj
      Providers/
        {YourApplication}.DataStoreProviders/
          {YourApplication}.DataStoreProviders.csproj

  {YourApplication}.Framework/
    Bridge/
      {YourApplication}.AspNetCoreBridge/
        {YourApplication}.AspNetCoreBridge.csproj
      {YourApplication}.CoreBridge/
        {YourApplication}.CoreBridge.csproj
      {YourApplication}.EFCoreBridge/
        {YourApplication}.EFCoreBridge.csproj

    PostBus/
      {YourApplication}.HandlerInterfaces/
        {YourApplication}.HandlerInterfaces.csproj
      {YourApplication}.Handlers.Default.Nsb/
        {YourApplication}.Handlers.Default.Nsb.csproj
      {YourApplication}.Subscribers.Default.Nsb/
        {YourApplication}.Subscribers.Default.Nsb.csproj
```

> Note: Your solution may not include every database-specific project (e.g., only SqlServer migrations, no PostgreSql), and provider projects can vary by implementation. Keep the folder structure consistent and include only the projects that apply to your application.

#### Recommended Folder Moves / Renames

Use these mappings as guidance (project names are equivalent; focus on structure):

1. **Queries**

* Old: `Application/Domain/{ProjectName}.Queries/`
* New: `Application/DomainHandler/{ProjectName}.Queries/`

2. **DTOs / Messages / Shared Events**

* Old: `Application/Dto/...`
* New: `Application/ControlContracts/...`

3. **Orchestration**

* Old: `Application/Orchestration/...`
* New: `Application/ControlHub/...`

4. **PreBus + REST Clients**

* Old: `Application/PreBus/...` and `Application/Orchestration/{ProjectName}.RESTClients/...`
* New: `Application/DomainHandler/{ProjectName}.PreBus/...` and `Application/DomainHandler/{ProjectName}.RESTClients/...`

5. **Handlers**

* Old: `Application/PostBus/{ProjectName}.Handlers.Plugins/...`
* New: `Application/DomainHandler/{ProjectName}.Handlers/`
  * Suggested subfolders: `CommandHandlers/` and `Subscribers/`

6. **Infrastructure Providers**

* Ensure `Application/Infrastructure/Providers/` exists for provider-related code (and keep `Bus/` and `Db/` alongside it).

#### Naming Convention Update (NSB Handlers)

* Old pattern: `*CommandHandler.cs`
* New pattern: `*NsbHandler.cs`

This typically means renaming both the file and class suffix from `CommandHandler` → `NsbHandler`.


# Getting Started


# Application

Welcome to the **Application** section! This is where you'll learn how to build enterprise-grade applications using the FlexBase Framework with Domain-Driven Design (DDD) principles and Clean Architecture patterns.

## 🎯 What You'll Learn Here

This section contains essential guides that will transform how you approach enterprise application development:

### 📋 **Introduction to Solution** (`introduction-to-solution.md`)

* **Complete solution architecture** overview with DDD and Clean Architecture principles
* **Project structure breakdown** showing how each component fits into the architectural layers
* **Technology stack** and framework integration patterns
* **Real-world examples** demonstrating enterprise application design

### ⚙️ **Common Configurations** (`common-configurations.md`)

* **Comprehensive configuration system** that scales from development to production
* **Security best practices** for protecting your application and data
* **Performance optimization** techniques that make your apps lightning-fast
* **Troubleshooting guides** that solve 90% of common configuration issues

## 🚀 Why This Matters

Understanding these concepts will help you:

* **Build enterprise applications** that follow industry best practices
* **Design scalable architectures** that grow with your business
* **Implement secure configurations** that protect your data and users
* **Deploy confidently** across multiple environments
* **Maintain easily** with clear, organized code and configurations

## 🎯 How to Use This Section

1. **Start with Solution Introduction** - Understand the overall architecture and project structure
2. **Move to Common Configurations** - Learn how to configure your applications properly
3. **Apply the patterns** - Use these concepts in your own projects
4. **Reference back** - Come back when you need a refresher

## 💡 Pro Tips

* **Read the architecture overview first** - Understanding the big picture makes everything else clearer
* **Study the project structure** - See how DDD principles map to actual code organization
* **Practice the configurations** - Hands-on experience with configuration patterns
* **Think about your domain** - How would these patterns apply to your specific business needs?
* **Ask questions** - Understanding the "why" behind architectural decisions makes you a better developer

***

**Ready to dive in?** Start with [Introduction to Solution](/solution-structure/getting-started/application/introduction-to-solution) to understand the architecture and project structure, then explore [Common Configurations](/solution-structure/getting-started/application/common-configurations) to learn how to configure your applications like a pro! 🚀


# Introduction to Solution

## Overview

The YourProject solution is a comprehensive enterprise application built using **FlexBase Framework** and following **Domain-Driven Design (DDD)** principles with **Clean Architecture** patterns. This solution demonstrates a modern, scalable approach to building business applications with clear separation of concerns, testability, and maintainability.

## Solution Architecture

The solution is organized into two main folders that represent the architectural layers:

### 1. YourProject.Application

The main application layer containing all business logic, domain models, and application services.

### 2. YourProject.Framework

The framework layer providing infrastructure abstractions and bridges to external systems.

## Project Structure and DDD Layers

### Domain Layer (Core Business Logic)

#### YourProject.DomainModels

* **Purpose**: Contains the core domain entities and rich domain models
* **DDD Role**: Domain Layer - Pure business logic
* **Key Components**:
  * **Rich Domain Models** - Main business entities with behavior that control access to their children (e.g., `EntityName.cs`, `EntityState.cs`)
  * **Value Objects** - Immutable objects defined by their attributes (e.g., `ValueObjectName.cs`, `ValueObjectStatus.cs`)
  * **Entities** - Objects with distinct identity (e.g., `EntityName.cs`, `EntityCategory.cs`)
  * **Domain Services** - Business logic that doesn't belong to a specific entity
* **Dependencies**: Only depends on `YourProject.CommonLib` and `YourProject.Messages`
* **Clean Architecture**: Innermost layer, no external dependencies

> **Example**: In an e-commerce system, you might have `Order` as a rich domain model with behavior, `OrderItem` as value objects, `Payment` as a separate rich domain model, and `Product` as a catalog entity.

#### YourProject.CommonLib

* **Purpose**: Shared domain utilities and common business logic
* **DDD Role**: Domain Layer - Shared kernel
* **Key Components**:
  * Custom exceptions (e.g., CustomExceptions.cs)
  * Database type constants (e.g., DbTypeConstants.cs)
  * HTTP response handlers (e.g., HttpResponseHandler.cs)
  * Logger category constants (e.g., LoggerCategoryConstants.cs)
* **Dependencies**: None (pure domain utilities)

#### YourProject.Mappers

* **Purpose**: Object mapping between domain models and DTOs
* **DDD Role**: Application Layer - Data transformation
* **Key Components**:
  * AutoMapper configurations (e.g., AutomapperConfiguration.cs)
  * Domain-to-DTO mappers (e.g., OrderDomainDtoMappers.cs, ProductDomainDtoMappers.cs)
  * Feature-specific mappers (e.g., OrderFeatureMappers.cs, ProductFeatureMappers.cs)
* **Dependencies**: Domain models and DTOs

### Application Layer (Use Cases and Application Services)

#### YourProject.Handlers

* **Purpose**: Command handlers implementing CQRS pattern
* **DDD Role**: Application Layer - Command handling
* **Key Components**:
  * **Create Handlers** - Handle entity creation commands (e.g., `AddEntityHandler.cs`, `CreateEntityHandler.cs`)
  * **Update Handlers** - Handle entity modification commands (e.g., `UpdateEntityHandler.cs`, `ModifyEntityHandler.cs`)
  * **Delete Handlers** - Handle entity removal commands (e.g., `DeleteEntityHandler.cs`, `RemoveEntityHandler.cs`)
  * **Business Process Handlers** - Handle complex business operations (e.g., `ProcessEntityHandler.cs`, `ExecuteWorkflowHandler.cs`)
* **Dependencies**: Domain models, repositories, and service bus

> **Example**: In an e-commerce system, you might have `AddOrderHandler.cs`, `UpdateOrderHandler.cs`, `DeleteOrderHandler.cs`, and `ProcessPaymentHandler.cs`.

#### YourProject.Queries

* **Purpose**: Query handlers for read operations (CQRS)
* **DDD Role**: Application Layer - Query handling
* **Key Components**:
  * **Single Entity Queries** - Retrieve individual entities (e.g., `GetEntityQuery.cs`, `FindEntityByIdQuery.cs`)
  * **List Queries** - Retrieve collections of entities (e.g., `GetEntityListQuery.cs`, `GetAllEntitiesQuery.cs`)
  * **Paged Queries** - Retrieve paginated results (e.g., `GetEntityPagedListQuery.cs`, `SearchEntitiesQuery.cs`)
  * **Complex Queries** - Retrieve data across multiple entities (e.g., `GetEntityWithDetailsQuery.cs`, `GetEntityReportQuery.cs`)
* **Dependencies**: Domain models and repositories

> **Example**: In an e-commerce system, you might have `GetOrderQuery.cs`, `GetOrderListQuery.cs`, `GetOrderPagedListQuery.cs`, and `GetOrderWithItemsQuery.cs`.

#### YourProject.PreBus

* **Purpose**: Pre-bus services for business logic orchestration
* **DDD Role**: Application Layer - Business orchestration
* **Key Components**:
  * **Entity Management Services** - Core business operations for entities (e.g., `EntityService.cs`, `EntityManagementService.cs`)
  * **Validation Services** - Business rule validation (e.g., `EntityValidationService.cs`, `BusinessRuleValidator.cs`)
  * **Workflow Services** - Complex business process orchestration (e.g., `EntityWorkflowService.cs`, `ProcessOrchestrator.cs`)
  * **Integration Services** - External system integration (e.g., `ExternalServiceClient.cs`, `ThirdPartyIntegrationService.cs`)
* **Dependencies**: Domain models, handlers, and queries

> **Example**: In an e-commerce system, you might have `OrderService.cs`, `OrderValidationService.cs`, `OrderWorkflowService.cs`, and `PaymentGatewayService.cs`.

#### YourProject.RESTClients

* **Purpose**: External service integration
* **DDD Role**: Application Layer - External service integration
* **Key Components**:
  * REST service clients (e.g., RESTServicesMaster\_Common.cs)
  * External API integrations (e.g., PaymentGatewayClient.cs, InventoryServiceClient.cs)
* **Dependencies**: Common libraries and HTTP clients

### Infrastructure Layer (External Concerns)

#### Database Infrastructure

**YourProject.BaseEF**

* **Purpose**: Base Entity Framework configuration
* **DDD Role**: Infrastructure Layer - Data persistence
* **Key Components**:
  * Base DbContext (e.g., YourProjectDbContext.cs)
  * Entity configurations (e.g., OrderConfiguration.cs, ProductConfiguration.cs)
  * Repository base classes (e.g., BaseRepository.cs)
* **Dependencies**: Entity Framework Core, domain models

**YourProject.BaseEF.SqlServer / MySql / PostgreSql**

* **Purpose**: Database-specific implementations
* **DDD Role**: Infrastructure Layer - Database providers
* **Key Components**:
  * Database-specific DbContext (e.g., YourProjectSqlServerDbContext.cs)
  * Provider-specific configurations (e.g., SqlServerOrderConfiguration.cs)
* **Dependencies**: Base EF, specific database providers

#### Message Bus Infrastructure

**YourProject.Nsb**

* **Purpose**: NServiceBus configuration and messaging
* **DDD Role**: Infrastructure Layer - Message transport
* **Key Features**:
  * Multiple transport options (RabbitMQ, Azure Service Bus, SQL Server)
  * Message persistence
  * Learning transport for development
* **Key Components**:
  * Bus configuration (e.g., NsbConfiguration.cs, NsbRouteConfig.cs)
  * Message routing (e.g., MessageRoutingConfiguration.cs)
* **Dependencies**: NServiceBus packages, core bridge

### Presentation Layer (API and Controllers)

#### YourProject.WebControllers

* **Purpose**: REST API controllers
* **DDD Role**: Presentation Layer - API endpoints
* **Key Components**:
  * **Entity Controllers** - RESTful endpoints for entity operations (e.g., `EntityController.cs`, `EntityManagementController.cs`)
  * **CRUD Operations** - Create, Read, Update, Delete endpoints (e.g., `EntityController_Add.cs`, `EntityController_Get.cs`)
  * **Search Controllers** - Search and filtering endpoints (e.g., `EntitySearchController.cs`, `EntityFilterController.cs`)
  * **Report Controllers** - Data reporting and analytics endpoints (e.g., `EntityReportController.cs`, `AnalyticsController.cs`)
* **Dependencies**: DTOs, mappers, and application services

> **Example**: In an e-commerce system, you might have `OrdersController_AddOrder.cs`, `OrdersController_GetOrders.cs`, `ProductsController.cs`, and `PaymentsController.cs`.

#### YourProject.CronJobs

* **Purpose**: Background job processing
* **DDD Role**: Presentation Layer - Background processing
* **Key Components**:
  * Scheduled job definitions (e.g., OrderCleanupJob.cs, PaymentProcessingJob.cs)
  * Job configuration (e.g., CronJobConfiguration.cs)
* **Dependencies**: Application services and infrastructure

### Control Contracts (API Contracts)

#### YourProject.DTOs

* **Purpose**: Data Transfer Objects for API contracts
* **DDD Role**: Presentation Layer - API contracts
* **Key Components**:
  * **Command DTOs** - Data for create/update operations (e.g., `AddEntityDto.cs`, `UpdateEntityDto.cs`)
  * **Query DTOs** - Data for read operations (e.g., `GetEntityDto.cs`, `EntityListDto.cs`)
  * **Input/Output DTOs** - Request/response data structures (e.g., `EntityInputDto.cs`, `EntityOutputDto.cs`)
  * **Domain DTOs** - Internal data transfer objects (e.g., `EntityDomainDto.cs`, `EntityDetailDto.cs`)
* **Dependencies**: Common libraries

> **Example**: In an e-commerce system, you might have `AddOrderDto.cs`, `UpdateOrderDto.cs`, `GetOrderDto.cs`, and `OrderDomainDto.cs`.

#### YourProject.Messages

* **Purpose**: Command and Event definitions
* **DDD Role**: Application Layer - Message contracts
* **Key Components**:
  * **Command Messages** - Instructions for business operations (e.g., `AddEntityCommand.cs`, `UpdateEntityCommand.cs`, `DeleteEntityCommand.cs`)
  * **Event Messages** - Notifications of state changes (e.g., `EntityAddedEvent.cs`, `EntityUpdatedEvent.cs`, `EntityDeletedEvent.cs`)
  * **Integration Events** - Cross-bounded context communications (e.g., `EntityProcessedEvent.cs`, `WorkflowCompletedEvent.cs`)
* **Dependencies**: Core framework

> **Example**: In an e-commerce system, you might have `AddOrderCommand.cs`, `UpdateOrderCommand.cs`, `OrderAddedEvent.cs`, and `PaymentProcessedEvent.cs`.

#### YourProject.SharedEvents

* **Purpose**: Cross-bounded context events
* **DDD Role**: Application Layer - Integration events
* **Key Components**:
  * Cross-domain events (e.g., OrderCompletedEvent.cs, InventoryUpdatedEvent.cs)
* **Dependencies**: Core framework

### Endpoints (Deployment Units)

#### YourProject.EndPoint.WebAPI

* **Purpose**: Main web API endpoint
* **DDD Role**: Presentation Layer - Web API host
* **Key Features**:
  * RESTful API endpoints
  * Swagger documentation
  * Authentication and authorization
  * Multi-database support
* **Key Components**:
  * Program.cs (e.g., Program.cs, Startup.cs)
  * Configuration files (e.g., appsettings.json, appsettings.Development.json)
* **Dependencies**: All application layers

#### YourProject.EndPoint.Handlers.Default

* **Purpose**: Message handler endpoint
* **DDD Role**: Application Layer - Message processing host
* **Key Components**:
  * Handler configuration (e.g., Program.cs, Worker.cs)
  * Message routing (e.g., NsbRouteConfig.cs)
* **Dependencies**: Handlers, infrastructure

#### YourProject.EndPoint.Subscribers.Default

* **Purpose**: Event subscriber endpoint
* **DDD Role**: Application Layer - Event processing host
* **Key Components**:
  * Subscriber configuration (e.g., Program.cs, Worker.cs)
  * Event routing (e.g., NsbRouteConfig.cs)
* **Dependencies**: Subscribers, infrastructure

#### YourProject.EndPoint.CronJob

* **Purpose**: Background job endpoint
* **DDD Role**: Application Layer - Background processing host
* **Key Components**:
  * Job configuration (e.g., Program.cs, Worker.cs)
  * Schedule definitions (e.g., CronJobConfiguration.cs)
* **Dependencies**: Cron jobs, infrastructure

### Database Migrations

#### YourProject.Migrations.\*

* **Purpose**: Database schema management
* **DDD Role**: Infrastructure Layer - Database versioning
* **Key Features**:
  * Multi-database support (SQL Server, MySQL, PostgreSQL)
  * Tenant-specific migrations
  * Schema versioning
* **Key Components**:
  * Migration files (e.g., 20240101\_InitialCreate.cs, 20240102\_AddOrderTable.cs)
  * Tenant migrations (e.g., Tenant\_20240101\_InitialCreate.cs)
* **Dependencies**: Domain models, Entity Framework

### Framework Layer (Infrastructure Abstractions)

#### YourProject.CoreBridge

* **Purpose**: Core framework abstractions
* **DDD Role**: Infrastructure Layer - Framework abstractions
* **Key Components**:
  * Service bus bridges (e.g., IFlexServiceBusBridge.cs, FlexServiceBusContextBridge.cs)
  * Repository abstractions (e.g., IFlexRepositoryBridge.cs, IFlexQueryRepositoryBridge.cs)
  * Domain model bridges (e.g., DomainModelBridge.cs, DtoBridge.cs)
  * Query abstractions (e.g., FlexiQueryBridge.cs, FlexiQueryPagedListBridge.cs)
* **Dependencies**: FlexBase Core framework

#### YourProject.EFCoreBridge

* **Purpose**: Entity Framework specific implementations
* **DDD Role**: Infrastructure Layer - EF implementations
* **Key Components**:
  * EF repository implementations (e.g., FlexEFRepositoryBridge.cs, FlexEFQueryRepositoryBridge.cs)
* **Dependencies**: Core bridge, Entity Framework

#### YourProject.AspNetCoreBridge

* **Purpose**: ASP.NET Core specific implementations
* **DDD Role**: Infrastructure Layer - Web framework implementations
* **Key Components**:
  * Controller bridges (e.g., FlexControllerBridge.cs, ControllerExtensionMethods.cs)
  * HTTP context accessors (e.g., FlexDefaultHttpContextAccessorBridge.cs)
* **Dependencies**: Core bridge, ASP.NET Core

#### YourProject.HandlerInterfaces

* **Purpose**: Handler interface definitions
* **DDD Role**: Application Layer - Handler contracts
* **Key Components**:
  * **Entity Handler Interfaces** - Contracts for entity operations (e.g., `IAddEntityHandler.cs`, `IUpdateEntityHandler.cs`, `IDeleteEntityHandler.cs`)
  * **Process Handler Interfaces** - Contracts for business processes (e.g., `IProcessEntityHandler.cs`, `IExecuteWorkflowHandler.cs`)
  * **Query Handler Interfaces** - Contracts for data retrieval (e.g., `IGetEntityHandler.cs`, `ISearchEntityHandler.cs`)
* **Dependencies**: Messages and DTOs

> **Example**: In an e-commerce system, you might have `IAddOrderHandler.cs`, `IUpdateOrderHandler.cs`, `IProcessPaymentHandler.cs`, and `IAddProductHandler.cs`.

#### YourProject.Handlers.Default.Nsb

* **Purpose**: Default NServiceBus handler implementations
* **DDD Role**: Infrastructure Layer - Message handling
* **Key Components**:
  * **Entity Handlers** - Concrete implementations for entity operations (e.g., `AddEntityHandler.cs`, `UpdateEntityHandler.cs`, `DeleteEntityHandler.cs`)
  * **Process Handlers** - Concrete implementations for business processes (e.g., `ProcessEntityHandler.cs`, `ExecuteWorkflowHandler.cs`)
  * **Query Handlers** - Concrete implementations for data retrieval (e.g., `GetEntityHandler.cs`, `SearchEntityHandler.cs`)
* **Dependencies**: Handler interfaces, NServiceBus

> **Example**: In an e-commerce system, you might have `AddOrderHandler.cs`, `UpdateOrderHandler.cs`, `ProcessPaymentHandler.cs`, and `AddProductHandler.cs`.

#### YourProject.Subscribers.Default.Nsb

* **Purpose**: Default NServiceBus subscriber implementations
* **DDD Role**: Infrastructure Layer - Event handling
* **Key Components**:
  * **Entity Event Subscribers** - Handle entity-related events (e.g., `EntityAddedSubscriber.cs`, `EntityUpdatedSubscriber.cs`)
  * **Process Event Subscribers** - Handle business process events (e.g., `ProcessCompletedSubscriber.cs`, `WorkflowFinishedSubscriber.cs`)
  * **Integration Event Subscribers** - Handle cross-system events (e.g., `ExternalSystemNotificationSubscriber.cs`)
* **Dependencies**: Handler interfaces, NServiceBus

> **Example**: In an e-commerce system, you might have `OrderAddedSubscriber.cs`, `OrderUpdatedSubscriber.cs`, and `PaymentProcessedSubscriber.cs`.

## Key Architectural Patterns

### 1. Domain-Driven Design (DDD)

* **Rich Domain Models**: Main business entities with behavior that control access to their children
* **Value Objects**: Immutable objects defined by their attributes
* **Entities**: Objects with distinct identity and lifecycle
* **Domain Services**: Business logic that doesn't belong to a specific entity
* **Repositories**: Data access abstraction

> **Example**: In an e-commerce system, `Order` might be a rich domain model with behavior, `OrderItem` as value objects, `Payment` as a separate rich domain model, and `Product` as a catalog entity.

### 2. Clean Architecture

* **Dependency Inversion**: All dependencies point inward
* **Separation of Concerns**: Clear layer boundaries
* **Testability**: Each layer can be tested independently
* **Independence**: Business logic independent of frameworks

### 3. CQRS (Command Query Responsibility Segregation)

* **Commands**: Instructions that change system state (e.g., AddEntity, UpdateEntity, DeleteEntity)
* **Queries**: Instructions that retrieve data (e.g., GetEntities, GetEntityById, SearchEntities)
* **Handlers**: Separate command and query handlers for different responsibilities
* **Read Models**: Optimized data structures for querying

> **Example**: In an e-commerce system, you might have `AddOrder`, `UpdateOrder`, `DeleteOrder` commands and `GetOrders`, `GetOrderById`, `GetProducts` queries.

### 4. Event-Driven Architecture

* **Commands**: Trigger business operations
* **Events**: Notify of state changes
* **Subscribers**: React to events
* **Message Bus**: NServiceBus for reliable messaging

### 5. Multi-Tenant Architecture

* **Tenant Isolation**: Separate databases per tenant
* **Tenant Context**: Passed through all layers
* **Tenant-Specific Migrations**: Database versioning per tenant

## Technology Stack

* **.NET 8.0**: Latest .NET framework
* **FlexBase Framework**: Custom enterprise framework
* **Entity Framework Core**: ORM for data access
* **NServiceBus**: Message bus and service bus
* **ASP.NET Core**: Web API framework
* **AutoMapper**: Object mapping
* **Multi-Database Support**: SQL Server, MySQL, PostgreSQL

## Usage and Deployment

### Development

1. **Web API**: Run `YourProject.EndPoint.WebAPI` for REST API
2. **Message Processing**: Run `YourProject.EndPoint.Handlers.Default` for command processing
3. **Event Processing**: Run `YourProject.EndPoint.Subscribers.Default` for event processing
4. **Background Jobs**: Run `YourProject.EndPoint.CronJob` for scheduled tasks

### Database Setup

1. Run appropriate migration project based on your database choice
2. Configure connection strings in appsettings
3. Apply migrations using Entity Framework tools

### Configuration

* **Multi-Environment**: Development, Staging, Production configurations
* **Database Providers**: Support for multiple database engines
* **Message Transports**: Configurable message bus transports
* **Logging**: Structured logging with different levels

This solution demonstrates a production-ready, enterprise-grade architecture that follows industry best practices for maintainability, scalability, and testability.


# Common Configurations

## Overview

Welcome to the comprehensive configuration guide for YourProject! This document is your roadmap to understanding and implementing the powerful configuration system that makes FlexBase applications both robust and easy to manage.

**Why Configuration Matters?** 🎯

* **Zero Downtime Deployments**: Change settings without code changes
* **Environment Consistency**: Same code, different behaviors per environment
* **Security by Design**: Sensitive data protection across all environments
* **Developer Productivity**: One configuration system for all endpoints
* **Operational Excellence**: Centralized logging, monitoring, and troubleshooting

**What You'll Learn** 📚

* How to set up configurations that scale from development to production
* Best practices that save you hours of debugging and maintenance
* Security patterns that protect your application and data
* Performance optimizations that make your app lightning-fast
* Troubleshooting techniques that solve 90% of common issues

## Configuration Architecture

### The Power of Layered Configuration 🏗️

FlexBase uses a sophisticated **3-tier configuration system** that gives you the perfect balance of consistency and flexibility:

#### 1. **Common Configurations** - Your Foundation Layer

**Value**: Eliminates configuration duplication and ensures consistency

* **What it does**: Shared settings across ALL endpoints
* **Why it matters**: Change once, apply everywhere
* **Real benefit**: No more hunting through 10+ files to update a database connection

#### 2. **Environment-Specific Configurations** - Your Environment Layer

**Value**: Same code, different behavior per environment

* **What it does**: Overrides common settings for specific environments
* **Why it matters**: Development logs everything, Production logs only errors
* **Real benefit**: Zero code changes needed when promoting from Dev → Staging → Production

#### 3. **Endpoint-Specific Configurations** - Your Customization Layer

**Value**: Fine-tuned control for unique endpoint requirements

* **What it does**: Additional settings for individual endpoints
* **Why it matters**: Web API might need CORS, but Message Handlers don't
* **Real benefit**: Each endpoint optimized for its specific role

### Configuration Files Structure 📁

```
YourProject.Application/
├── EndPoints/
│   ├── YourProject.EndPoint.CommonConfigs/     ← 🎯 THE CONTROL CENTER
│   │   └── AppSettings/
│   │       ├── appsettings.Common.Development.json  ← Dev settings for ALL
│   │       ├── appsettings.Common.Production.json   ← Prod settings for ALL
│   │       └── appsettings.Common.Staging.json      ← Staging settings for ALL
│   └── YourProject.EndPoint.WebAPI/           ← 🚀 INDIVIDUAL ENDPOINTS
│       ├── appsettings.json                   ← Base settings
│       ├── appsettings.Development.json       ← Dev overrides
│       └── appsettings.Production.json        ← Prod overrides
```

**💡 Pro Tip**: The magic happens in the **CommonConfigs** folder - this is where you make changes that affect your entire application ecosystem!

## Common Configuration Sections

### 1. Serilog Configuration - Your Application's Eyes and Ears 👁️

**Why Serilog is a Game-Changer** 🚀

* **Structured Logging**: Search and filter logs like a database
* **Performance**: 10x faster than traditional logging
* **Flexibility**: Log to console, files, databases, or cloud services
* **Debugging Superpowers**: Trace requests across multiple services
* **Production Ready**: Built-in log rotation and retention

**What This Configuration Gives You** 💪

* **Instant Problem Detection**: See issues before users do
* **Request Tracing**: Follow a user's journey through your entire system
* **Performance Monitoring**: Identify slow operations automatically
* **Audit Trail**: Complete record of all system activities
* **Zero-Downtime Logging**: Change log levels without restarting

```json
{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "YourLogLevel",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "YourLogPath\\log.txt",
          "rollingInterval": "Day",
          "retainedFileCountLimit": 7,
          "retainedFileDuration": "7.00:00:00"
        }
      }
    ],
    "Properties": {
      "Application": "YourProjectName"
    }
  }
}
```

#### **Configuration Deep Dive** 🔍

**MinimumLevel - Your Logging Intelligence** 🧠

* **Verbose**: "I want to see EVERYTHING" (Development)
* **Debug**: "Show me detailed flow" (Development/Staging)
* **Information**: "Tell me what's happening" (Production)
* **Warning**: "Something might be wrong" (Production)
* **Error**: "Something IS wrong" (Production)
* **Fatal**: "System is crashing" (Production)

**WriteTo - Your Logging Destinations** 📍

* **Console**: Perfect for development and debugging
* **File**: Reliable storage with automatic rotation
* **Database**: Searchable logs with SQL queries
* **Cloud**: Centralized logging across multiple servers

**Enrich - Your Context Superpowers** ⚡

* **FromLogContext**: Adds custom properties to every log
* **WithMachineName**: Know which server logged the message
* **WithProcessId**: Track logs from specific processes
* **WithThreadId**: Debug multi-threading issues

> **Real-World Example**: In an e-commerce system, you might set `"Application": "ECommerce"` and configure different log levels for Development (Verbose) and Production (Information). This means developers see every detail during development, but production only logs what matters for monitoring and troubleshooting.

### 2. FlexBase Configuration - The Heart of Your Application ❤️

**Why FlexBase Configuration is Revolutionary** 🌟

* **Multi-Database Support**: SQL Server, MySQL, PostgreSQL - choose your weapon
* **CQRS Built-In**: Separate read/write databases for maximum performance
* **Multi-Tenant Ready**: One codebase, multiple customers
* **Message Bus Flexibility**: RabbitMQ, Azure Service Bus, AWS SQS - all supported
* **Zero Configuration Changes**: Switch between transports with one setting

**What This Configuration Unlocks** 🚀

* **Massive Performance**: Read/write separation = 10x faster queries
* **Infinite Scalability**: Add databases and message brokers as you grow
* **Enterprise Security**: Multi-tenant isolation and secure connections
* **Cloud Native**: Deploy anywhere - on-premises, Azure, AWS, or hybrid
* **Disaster Recovery**: Built-in redundancy and failover capabilities

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=YourServer;Initial Catalog=YourDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "AppReadDbConnection": "Data Source=YourServer;Initial Catalog=YourReadDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "AzureStorageConnectionString": "YourAzureStorageConnectionString",
    "SqlTransportConnectionString": "Data Source=YourServer;Initial Catalog=YourTransportDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "RabbitMqConnectionString": "amqp://YourUser:YourPassword@YourRabbitMqHost:YourPort",
    "AzureServiceBusConnectionString": "YourAzureServiceBusConnectionString",
    "AmazonSQSTransportBucketName": "YourS3BucketName",
    "AmazonSQSTransportKeyPrefix": "YourKeyPrefix",
    "TenantMasterDbConnection": "Data Source=YourServer;Initial Catalog=YourTenantMasterDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True"
  }
}
```

#### **Database Connections - Your Data Powerhouse** 💾

**AppDbConnection - The Write Master** ✍️

* **What it does**: Handles all CREATE, UPDATE, DELETE operations
* **Why separate**: Write operations are slower and can block reads
* **Performance gain**: 5-10x faster read operations
* **Real benefit**: Your users get instant search results while data is being saved

**AppReadDbConnection - The Read Rocket** 🚀

* **What it does**: Handles all SELECT queries and reports
* **Why separate**: Read operations are 90% of your traffic
* **Performance gain**: Optimized indexes, no write locks
* **Real benefit**: Sub-second response times even with millions of records

**TenantMasterDbConnection - The Multi-Tenant Brain** 🧠

* **What it does**: Manages multiple customer databases
* **Why separate**: Complete data isolation between customers
* **Security gain**: One customer can never see another's data
* **Real benefit**: Enterprise-grade security with simple configuration

#### **Message Bus Connections - Your Communication Network** 📡

**RabbitMqConnectionString - The Reliable Messenger** 🐰

* **What it does**: Handles all inter-service communication
* **Why RabbitMQ**: Battle-tested, reliable, and fast
* **Performance gain**: 100,000+ messages per second
* **Real benefit**: Your services talk to each other instantly and reliably

**AzureServiceBusConnectionString - The Cloud Native** ☁️

* **What it does**: Managed message service in Azure
* **Why Azure Service Bus**: Fully managed, auto-scaling
* **Performance gain**: No infrastructure management needed
* **Real benefit**: Focus on business logic, not message infrastructure

**SQL Transport - The Database Native** 🗄️

* **What it does**: Uses your existing SQL Server for messaging
* **Why SQL Transport**: No additional infrastructure needed
* **Performance gain**: Leverages existing database investments
* **Real benefit**: Use what you already have, get enterprise messaging

> **Real-World Example**: For a multi-tenant e-commerce system, you might have separate databases for each tenant and use RabbitMQ for inter-service communication. This means each customer's data is completely isolated, but all services can communicate seamlessly for features like inventory updates, order processing, and notifications.

### 3. REST Client Services Configuration - Your Dependency Injection Powerhouse 🔌

**Why REST Client Configuration is Revolutionary** 🚀

* **Dependency Injection Ready**: Services automatically registered and injectable
* **Configuration-Driven**: No hardcoded service implementations
* **Testable by Design**: Easy to mock and unit test
* **Environment Flexible**: Different implementations per environment
* **Type-Safe**: Strongly typed service contracts and configurations

**What This Configuration Architecture Delivers** ⚡

* **Service Provider Pattern**: Create configurable service providers for any external API
* **Automatic Registration**: Services registered in DI container based on configuration
* **Interface-Based Design**: Program against interfaces, not concrete implementations
* **Easy Testing**: Mock services for unit and integration tests
* **Environment Switching**: Different service implementations for Dev/Staging/Production

```json
{
  "RESTClientServices": {
    "YourExternalService": {
      "BaseUrl": "https://api.yourexternalservice.com",
      "ApiKey": "YourApiKey",
      "Timeout": "00:00:30"
    },
    "YourPaymentGateway": {
      "BaseUrl": "https://api.paymentgateway.com",
      "MerchantId": "YourMerchantId",
      "SecretKey": "YourSecretKey"
    }
  }
}
```

#### **Service Provider Architecture Deep Dive** 🔍

**Configuration-Driven Service Creation** 🏗️

* **What it does**: Creates service providers based on configuration settings
* **Why powerful**: No need to manually register each service
* **Real benefit**: Add new external services by just adding configuration

**Dependency Injection Integration** 🔌

* **What it does**: Automatically registers services in the DI container
* **Why essential**: Services become injectable throughout your application
* **Real benefit**: Clean, testable, and maintainable code

**Interface-Based Design** 🎯

* **What it does**: Services implement well-defined interfaces
* **Why important**: Loose coupling and easy testing
* **Real benefit**: Switch implementations without changing consuming code

#### **How to Create Your Own Service Providers** 🛠️

**Step 1: Define Your Service Interface**

```csharp
public interface IYourExternalService
{
    Task<YourResponse> GetDataAsync(string id);
    Task<YourResponse> PostDataAsync(YourRequest request);
}
```

**Step 2: Create Your Service Implementation**

```csharp
public class YourExternalService : IYourExternalService
{
    private readonly HttpClient _httpClient;
    private readonly YourServiceConfig _config;
    
    public YourExternalService(HttpClient httpClient, IOptions<YourServiceConfig> config)
    {
        _httpClient = httpClient;
        _config = config.Value;
    }
    
    public async Task<YourResponse> GetDataAsync(string id)
    {
        // Implementation using _httpClient and _config
    }
}
```

**Step 3: Register in DI Container**

```csharp
// In your Program.cs or Startup.cs
builder.Services.Configure<YourServiceConfig>(
    builder.Configuration.GetSection("RESTClientServices:YourExternalService"));

builder.Services.AddHttpClient<IYourExternalService, YourExternalService>();
```

**Step 4: Inject and Use**

```csharp
public class YourBusinessService
{
    private readonly IYourExternalService _externalService;
    
    public YourBusinessService(IYourExternalService externalService)
    {
        _externalService = externalService;
    }
    
    public async Task ProcessData()
    {
        var data = await _externalService.GetDataAsync("some-id");
        // Process the data
    }
}
```

#### **Configuration Deep Dive** 🔍

**BaseUrl - Your Service Endpoint** 🎯

* **What it does**: Defines where your external service lives
* **Why important**: Different URLs for different environments
* **Real benefit**: Same code works in Dev (sandbox) and Production (live)

**ApiKey/SecretKey - Your Security Credentials** 🔐

* **What it does**: Authenticates your application with external services
* **Why secure**: Never hardcode these in your application
* **Real benefit**: Rotate keys without code changes

**Timeout - Your Performance Guardian** ⏱️

* **What it does**: Prevents your app from hanging on slow external calls
* **Why important**: External services can be slow or unresponsive
* **Real benefit**: Your users never wait more than 30 seconds for anything

#### **Real-World Service Provider Examples** 🌟

**Payment Service Provider**

```csharp
public interface IPaymentService
{
    Task<PaymentResult> ProcessPaymentAsync(PaymentRequest request);
    Task<RefundResult> ProcessRefundAsync(RefundRequest request);
}

// Configuration automatically injects Stripe, PayPal, or Square implementations
```

**Email Service Provider**

```csharp
public interface IEmailService
{
    Task SendEmailAsync(EmailMessage message);
    Task SendBulkEmailAsync(List<EmailMessage> messages);
}

// Configuration automatically injects SendGrid, Mailgun, or AWS SES implementations
```

**Storage Service Provider**

```csharp
public interface IStorageService
{
    Task<string> UploadFileAsync(Stream file, string fileName);
    Task<Stream> DownloadFileAsync(string fileName);
}

// Configuration automatically injects AWS S3, Azure Blob, or Google Cloud implementations
```

> **Pro Tip**: This configuration pattern makes it incredibly easy to add new external services. Just define the interface, create the implementation, add configuration, and register in DI. The FlexBase framework handles the rest, making your services available throughout your application via dependency injection!

## Environment-Specific Configurations - Your Deployment Strategy 🚀

### Development Environment - The Debugging Paradise 🛠️

**Why Development Configuration is Your Best Friend** 💚

* **See Everything**: Every log, every detail, every step
* **Local Everything**: No external dependencies to slow you down
* **Instant Feedback**: Changes reflect immediately
* **Safe Testing**: Can't break production from your dev machine
* **Learning Mode**: Understand exactly how your app works

```json
{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Verbose"
    }
  },
  "FlexBase": {
    "AppDbConnection": "Data Source=localhost;Initial Catalog=YourProject_Dev;Integrated Security=true;TrustServerCertificate=True",
    "RabbitMqConnectionString": "amqp://guest:guest@localhost:5672"
  }
}
```

**Development Superpowers** ⚡

* **Verbose Logging**: See every single operation your app performs
* **Local Database**: No network latency, instant responses
* **Integrated Security**: No password management headaches
* **Local Message Broker**: Test messaging without cloud dependencies
* **Detailed Errors**: Stack traces, variable values, execution paths

**Real Developer Benefits** 🎯

* **Faster Debugging**: Find issues in seconds, not hours
* **Confident Changes**: Test everything locally before deploying
* **Learning Experience**: Understand your application's behavior
* **Zero Risk**: Can't accidentally affect production data
* **Instant Gratification**: See results immediately

### Production Environment - The Performance Beast 🏭

**Why Production Configuration is Mission-Critical** 🎯

* **User Experience**: Every millisecond matters to your users
* **Security First**: Protect your data and your customers
* **Reliability**: Your app must work 24/7 without fail
* **Performance**: Handle thousands of users simultaneously
* **Monitoring**: Know what's happening when you're not watching

```json
{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information"
    },
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "/var/log/yourproject/log.txt"
        }
      }
    ]
  },
  "FlexBase": {
    "AppDbConnection": "Data Source=YourProductionServer;Initial Catalog=YourProject_Prod;User ID=YourProdUser;Password=YourProdPassword;TrustServerCertificate=True",
    "RabbitMqConnectionString": "amqp://YourProdUser:YourProdPassword@YourProductionRabbitMq:5672"
  }
}
```

**Production Superpowers** 🚀

* **Information Logging**: Only log what matters for monitoring
* **Production Database**: Optimized for performance and reliability
* **Secure Credentials**: Encrypted passwords and connection strings
* **High Availability**: Redundant systems and failover capabilities
* **Performance Monitoring**: Track response times and resource usage

**Real Business Benefits** 💰

* **Happy Customers**: Fast, reliable application experience
* **Lower Costs**: Efficient resource usage saves money
* **Security Compliance**: Meet industry standards and regulations
* **Scalability**: Handle growth without major changes
* **Peace of Mind**: Know your app is running smoothly

### Staging Environment - The Production Rehearsal 🎭

**Why Staging is Your Safety Net** 🛡️

* **Production Mirror**: Same configuration as production
* **Safe Testing**: Test with real data without affecting users
* **Performance Validation**: Ensure your app can handle the load
* **Integration Testing**: Test with real external services
* **Deployment Practice**: Perfect your deployment process

**Staging Configuration Strategy** 📋

* **Same as Production**: Identical settings and performance
* **Test Data**: Safe to experiment with real data
* **External Services**: Use sandbox/test endpoints
* **Monitoring**: Full monitoring and alerting setup
* **Backup Strategy**: Test your disaster recovery procedures

> **Pro Tip**: Your staging environment should be a perfect copy of production. This is where you catch issues before they reach your users. The small cost of maintaining staging saves you from expensive production incidents!

## Endpoint Configuration Patterns - Your Application's Command Centers 🎛️

### 1. Web API Endpoint Configuration - The Public Face of Your Application 🌐

**Why Web API Configuration is Critical** 🎯

* **First Impression**: This is what your users interact with
* **Performance**: Every millisecond counts for user experience
* **Security**: Protect your API from attacks and misuse
* **Scalability**: Handle traffic spikes without breaking
* **Developer Experience**: Make it easy for other developers to use

**What This Configuration Delivers** ⚡

* **Lightning-Fast APIs**: Optimized for speed and efficiency
* **Bulletproof Security**: Authentication, authorization, and protection
* **Auto-Documentation**: Swagger/OpenAPI docs generated automatically
* **CORS Support**: Work seamlessly with web applications
* **Error Handling**: Graceful error responses with proper HTTP codes

**Program.cs Structure - The Heart of Your API**:

```csharp
var builder = WebApplication.CreateBuilder(args);

// 🎯 STEP 1: Configure FlexBase Host - The Foundation
builder.Host.ConfigureCommonHost(
    new ConfigureEndPointHostParams
    {
        HostName = "YourProject.EndPoint.WebAPI",    // ← Your API's identity
        Routes = YourNsbRouteConfig.GetRoute(),      // ← Message routing rules
        SearchPattern = "YourProject*.dll"           // ← Auto-discover your assemblies
    }
);

// 🚀 STEP 2: Add FlexBase Services - The Power Pack
builder.Services.AddFlexBaseAspNetCoreServices();

// 🛡️ STEP 3: Configure Controllers - The Security Layer
builder.Services.AddControllers(config =>
{
    config.Filters.Add<FlexStandardResponseFilter>();    // ← Consistent responses
    config.Filters.Add<FlexStandardExceptionFilter>();   // ← Graceful error handling
});

// 📚 STEP 4: Configure Swagger - The Documentation Magic
builder.Services.AddSwaggerGen(c =>
{
    c.SchemaFilter<FlexSwaggerSchemaFilter>();           // ← Auto-generate schemas
    c.OperationFilter<FlexSwaggerStandardOperationFilter>(); // ← Standard operations
});

// 🌐 STEP 5: Configure CORS - The Cross-Origin Bridge
builder.Services.AddCors(options =>
{
    options.AddPolicy("YourCorsPolicy", builder =>
    {
        builder.AllowAnyOrigin()                          // ← Allow all origins
               .AllowAnyHeader()                          // ← Allow all headers
               .AllowAnyMethod()                          // ← Allow all HTTP methods
               .WithExposedHeaders("X-Pagination");      // ← Expose pagination headers
    });
});

var app = builder.Build();

// 🔗 STEP 6: Register FlexBase Service Provider - The Connection Hub
var serviceScope = app.Services.CreateScope();
var serviceProvider = serviceScope.ServiceProvider;
var flexHost = serviceProvider.GetRequiredService<IFlexHost>();
flexHost.SetServiceProvider(serviceProvider);

// 🎭 STEP 7: Configure Middleware Pipeline - The Request Journey
app.UseCors("YourCorsPolicy");           // ← Handle cross-origin requests
app.UseSwagger();                        // ← Serve API documentation
app.UseSwaggerUI();                      // ← Interactive API explorer
app.UseSerilogRequestLogging();          // ← Log every request
app.UseHttpsRedirection();               // ← Force HTTPS for security
app.UseAuthorization();                  // ← Check user permissions
app.MapControllers();                    // ← Route requests to controllers

app.Run();                               // ← Start the magic! ✨
```

#### **Configuration Breakdown - What Each Step Does** 🔍

**Step 1: FlexBase Host Configuration** 🏗️

* **HostName**: Identifies your API in logs and monitoring
* **Routes**: Tells the system how to route messages between services
* **SearchPattern**: Automatically finds and loads your project assemblies

**Step 2: FlexBase Services** ⚡

* **AddFlexBaseAspNetCoreServices()**: Registers all FlexBase services
* **What you get**: Dependency injection, logging, configuration, and more
* **Why it matters**: One line gives you enterprise-grade functionality

**Step 3: Controller Configuration** 🛡️

* **FlexStandardResponseFilter**: Ensures all responses follow the same format
* **FlexStandardExceptionFilter**: Catches exceptions and returns proper HTTP codes
* **Why it matters**: Consistent API behavior and better error handling

**Step 4: Swagger Configuration** 📚

* **Auto-generated documentation**: Your API documents itself
* **Interactive testing**: Developers can test your API in the browser
* **Why it matters**: Saves hours of manual documentation work

**Step 5: CORS Configuration** 🌐

* **Cross-Origin Resource Sharing**: Allows web apps to call your API
* **Security**: Only allows requests from approved origins
* **Why it matters**: Essential for modern web applications

**Step 6: Service Provider Registration** 🔗

* **Dependency Injection**: Makes services available throughout your app
* **FlexBase Integration**: Connects your app to the FlexBase ecosystem
* **Why it matters**: Enables all the FlexBase magic to work

**Step 7: Middleware Pipeline** 🎭

* **Request Processing**: Each request goes through this pipeline
* **Order matters**: Middleware executes in the order you add it
* **Why it matters**: Controls how requests are processed and responses are sent

> **Pro Tip**: This configuration gives you a production-ready API in minutes. The FlexBase framework handles all the complex stuff, so you can focus on your business logic!

### 2. Message Handler Endpoint Configuration - The Command Processing Engine ⚙️

**Why Message Handlers are Game-Changers** 🚀

* **Asynchronous Processing**: Handle commands without blocking your API
* **Reliability**: Messages are persisted and retried if they fail
* **Scalability**: Process thousands of commands per second
* **Decoupling**: Services communicate without knowing about each other
* **Resilience**: System continues working even if some handlers fail

**What This Configuration Enables** ⚡

* **Command Processing**: Handle Create, Update, Delete operations
* **Background Tasks**: Process long-running operations
* **Event Sourcing**: Track all changes to your data
* **Microservices**: Break your app into independent services
* **Eventual Consistency**: Data becomes consistent over time

**Program.cs Structure - The Command Center**:

```csharp
Console.Title = "YourProject.EndPoint.Handlers.Default";

// 🏗️ STEP 1: Create Host Builder - The Foundation
IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureCommonHost(
        new ConfigureEndPointHostParams
        {
            HostName = "YourProject.EndPoint.Handlers.Default",  // ← Handler identity
            Routes = YourNsbRouteConfig.GetRoute(),              // ← Message routing
            SearchPattern = "YourProject*.dll"                   // ← Auto-discovery
        }
    )
    .ConfigureServices((hostingContext, services) =>
    {
        services.AddHostedService<YourWorker>();                 // ← Background worker
    })
    .Build();

// 🔗 STEP 2: Register FlexBase Services - The Power Connection
var serviceScope = host.Services.CreateScope();
var serviceProvider = serviceScope.ServiceProvider;
var flexHost = serviceProvider.GetRequiredService<IFlexHost>();
flexHost.SetServiceProvider(serviceProvider);

// 🚀 STEP 3: Start Processing - The Magic Begins
await host.RunAsync();
```

#### **Message Handler Deep Dive** 🔍

**What Happens Behind the Scenes** 🎭

1. **Message Arrives**: Command comes in via message bus
2. **Handler Activates**: Your handler processes the command
3. **Business Logic**: Execute your domain logic
4. **Database Update**: Save changes to database
5. **Event Published**: Notify other services of changes
6. **Success Confirmed**: Message marked as processed

**Real-World Benefits** 💰

* **User Experience**: API responds instantly, processing happens in background
* **Reliability**: If processing fails, message is retried automatically
* **Scalability**: Add more handlers to handle more load
* **Maintainability**: Each handler has one responsibility

### 3. Event Subscriber Endpoint Configuration - The Event Processing Powerhouse 📡

**Why Event Subscribers are Essential** 🎯

* **Real-Time Updates**: React to changes as they happen
* **System Integration**: Connect different parts of your system
* **Audit Trail**: Track every change for compliance
* **Notifications**: Send emails, SMS, push notifications
* **Data Synchronization**: Keep different systems in sync

**What This Configuration Delivers** ⚡

* **Event Processing**: Handle OrderCreated, UserRegistered, PaymentProcessed events
* **Cross-Service Communication**: Services talk to each other via events
* **Business Workflows**: Implement complex business processes
* **Integration Points**: Connect with external systems
* **Analytics**: Track user behavior and system performance

**Program.cs Structure - The Event Hub**:

```csharp
Console.Title = "YourProject.EndPoint.Subscribers.Default";

// 🏗️ STEP 1: Create Host Builder - The Event Foundation
IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureCommonHost(
        new ConfigureEndPointHostParams
        {
            HostName = "YourProject.EndPoint.Subscribers.Default",  // ← Subscriber identity
            Routes = YourNsbRouteConfig.GetRoute(),                 // ← Event routing
            SearchPattern = "YourProject*.dll"                      // ← Auto-discovery
        }
    )
    .ConfigureServices((hostingContext, services) =>
    {
        services.AddHostedService<YourEventWorker>();               // ← Event worker
    })
    .Build();

// 🔗 STEP 2: Register FlexBase Services - The Event Connection
var serviceScope = host.Services.CreateScope();
var serviceProvider = serviceScope.ServiceProvider;
var flexHost = serviceProvider.GetRequiredService<IFlexHost>();
flexHost.SetServiceProvider(serviceProvider);

// 🚀 STEP 3: Start Listening - The Event Magic Begins
await host.RunAsync();
```

#### **Event Subscriber Deep Dive** 🔍

**What Happens When Events Occur** 🎭

1. **Event Published**: Something changes in your system
2. **Event Routed**: Message bus routes event to subscribers
3. **Subscriber Activates**: Your subscriber processes the event
4. **Business Logic**: Execute your event handling logic
5. **Side Effects**: Send emails, update other systems, etc.
6. **Event Acknowledged**: Event marked as processed

**Real-World Examples** 🌟

* **OrderCreated** → Send confirmation email, reserve inventory
* **UserRegistered** → Send welcome email, create user profile
* **PaymentProcessed** → Update order status, send receipt
* **InventoryLow** → Send alert to warehouse, reorder stock

> **Pro Tip**: Event subscribers are perfect for implementing the "fire and forget" pattern. Your API can publish an event and continue processing, while subscribers handle the side effects asynchronously. This makes your system more responsive and resilient!

## Configuration Best Practices - Your Path to Excellence 🏆

### 1. Security Considerations - Protect What Matters Most 🛡️

**Why Security is Non-Negotiable** 🔐

* **Data Breaches Cost Millions**: Average cost is $4.45 million per incident
* **Regulatory Compliance**: GDPR, HIPAA, SOX require proper data protection
* **Customer Trust**: One breach can destroy years of trust
* **Legal Liability**: Improper security can lead to lawsuits
* **Business Continuity**: Security incidents can shut down your business

**Security Best Practices** ⚡

* **Never commit sensitive data** to source control
  * **Why**: Source control is not secure for secrets
  * **How**: Use .gitignore and environment variables
  * **Benefit**: Prevents accidental exposure of credentials
* **Use User Secrets** for development
  * **Why**: Keep secrets out of your code
  * **How**: `dotnet user-secrets set "ConnectionStrings:Default" "your-connection"`
  * **Benefit**: Secure development without configuration files
* **Use Azure Key Vault** or similar for production
  * **Why**: Enterprise-grade secret management
  * **How**: Store all secrets in Key Vault, reference by name
  * **Benefit**: Centralized, auditable, and secure secret management
* **Rotate credentials** regularly
  * **Why**: Compromised credentials become useless
  * **How**: Set up automatic rotation policies
  * **Benefit**: Minimize impact of credential compromise

### 2. Environment Management - Scale with Confidence 📈

**Why Environment Management is Critical** 🎯

* **Consistency**: Same behavior across all environments
* **Predictability**: Know what will happen in production
* **Efficiency**: Deploy faster with fewer surprises
* **Quality**: Catch issues before they reach users
* **Compliance**: Meet audit and regulatory requirements

**Environment Management Best Practices** ⚡

* **Separate configurations** for each environment
  * **Why**: Different environments have different needs
  * **How**: Use environment-specific configuration files
  * **Benefit**: Optimize each environment for its purpose
* **Use environment variables** for sensitive settings
  * **Why**: More secure than configuration files
  * **How**: Override configuration with environment variables
  * **Benefit**: Secrets never touch the file system
* **Validate configurations** at startup
  * **Why**: Catch configuration errors early
  * **How**: Add validation logic to your startup code
  * **Benefit**: Fail fast with clear error messages
* **Document configuration requirements**
  * **Why**: Help team members understand what's needed
  * **How**: Create configuration documentation and examples
  * **Benefit**: Faster onboarding and fewer configuration errors

### 3. Performance Optimization - Speed That Sells 🚀

**Why Performance Matters** 💰

* **User Experience**: 1 second delay = 7% reduction in conversions
* **Search Rankings**: Google uses page speed as a ranking factor
* **Server Costs**: Efficient code uses fewer resources
* **Scalability**: Fast code handles more users
* **Competitive Advantage**: Speed is a differentiator

**Performance Best Practices** ⚡

* **Connection pooling** for database connections
  * **Why**: Reusing connections is much faster
  * **How**: Configure connection pool settings
  * **Benefit**: 10x faster database operations
* **Appropriate log levels** for each environment
  * **Why**: Logging impacts performance
  * **How**: Verbose in dev, Information in production
  * **Benefit**: Better performance without losing visibility
* **Caching strategies** for frequently accessed data
  * **Why**: Memory is faster than database
  * **How**: Use Redis, in-memory cache, or CDN
  * **Benefit**: Sub-millisecond response times
* **Resource monitoring** and alerting
  * **Why**: Know when performance degrades
  * **How**: Set up performance counters and alerts
  * **Benefit**: Proactive performance management

### 4. Maintenance - Keep Your System Healthy 🏥

**Why Maintenance is Essential** 🔧

* **Prevent Issues**: Fix problems before they become critical
* **Improve Performance**: Continuous optimization
* **Stay Current**: Keep up with framework updates
* **Reduce Technical Debt**: Clean up over time
* **Team Productivity**: Well-maintained systems are easier to work with

**Maintenance Best Practices** ⚡

* **Version control** configuration changes
  * **Why**: Track what changed and when
  * **How**: Use Git for all configuration files
  * **Benefit**: Easy rollback and change tracking
* **Backup configurations** before changes
  * **Why**: Quick recovery if something goes wrong
  * **How**: Create backups before major changes
  * **Benefit**: Peace of mind during updates
* **Test configurations** in non-production environments
  * **Why**: Catch issues before they affect users
  * **How**: Deploy to staging first
  * **Benefit**: Confident production deployments
* **Document configuration dependencies**
  * **Why**: Help team members understand relationships
  * **How**: Create dependency diagrams and documentation
  * **Benefit**: Easier troubleshooting and maintenance

## Common Configuration Issues - Your Troubleshooting Guide 🔧

### 1. Connection String Issues - The Database Connection Blues 💾

**Why Connection Issues Happen** 🤔

* **Typos**: One wrong character breaks everything
* **Network Issues**: Firewalls, DNS, routing problems
* **Authentication**: Wrong username, password, or permissions
* **SSL/TLS**: Certificate and encryption problems

**Connection String Troubleshooting** 🔍

* **Invalid credentials** - Verify username and password
  * **Symptom**: "Login failed" or "Authentication failed"
  * **Solution**: Double-check username and password
  * **Prevention**: Use connection string testing tools
* **Network connectivity** - Check firewall and network settings
  * **Symptom**: "Connection timeout" or "Network unreachable"
  * **Solution**: Check firewall rules and network connectivity
  * **Prevention**: Document network requirements
* **Database permissions** - Ensure user has required permissions
  * **Symptom**: "Access denied" or "Permission denied"
  * **Solution**: Grant appropriate database permissions
  * **Prevention**: Use least-privilege principle
* **SSL/TLS settings** - Configure TrustServerCertificate appropriately
  * **Symptom**: "SSL connection error" or "Certificate validation failed"
  * **Solution**: Set TrustServerCertificate=True for development
  * **Prevention**: Use proper certificates in production

### 2. Message Bus Configuration - The Communication Breakdown 📡

**Why Message Bus Issues Occur** 🤔

* **Service Unavailable**: Message broker is down or unreachable
* **Configuration Mismatch**: Wrong routing or endpoint settings
* **Serialization Problems**: Messages can't be serialized/deserialized
* **Permission Issues**: Insufficient access to message broker

**Message Bus Troubleshooting** 🔍

* **Transport connectivity** - Verify message broker is running
  * **Symptom**: "Connection refused" or "Service unavailable"
  * **Solution**: Check if RabbitMQ, SQL Server, or Azure Service Bus is running
  * **Prevention**: Set up health checks and monitoring
* **Routing configuration** - Check NsbRouteConfig settings
  * **Symptom**: Messages not reaching handlers
  * **Solution**: Verify routing configuration and endpoint names
  * **Prevention**: Use configuration validation
* **Persistence settings** - Ensure persistence database is accessible
  * **Symptom**: "Database connection failed" in message processing
  * **Solution**: Check persistence database connection string
  * **Prevention**: Test persistence database connectivity
* **Serialization issues** - Verify message serialization settings
  * **Symptom**: "Serialization error" or "Type not found"
  * **Solution**: Check message contracts and serialization settings
  * **Prevention**: Use version-tolerant serialization

### 3. Logging Configuration - The Silent System Problem 🔇

**Why Logging Issues Matter** 🤔

* **Debugging Nightmare**: Can't see what's happening
* **Performance Impact**: Too much logging slows down the system
* **Storage Issues**: Log files filling up disk space
* **Security Concerns**: Sensitive data in logs

**Logging Troubleshooting** 🔍

* **File permissions** - Ensure log directory is writable
  * **Symptom**: "Access denied" when writing logs
  * **Solution**: Check directory permissions and ownership
  * **Prevention**: Set up proper directory permissions
* **Disk space** - Monitor log file sizes and retention
  * **Symptom**: "No space left on device" or slow performance
  * **Solution**: Implement log rotation and retention policies
  * **Prevention**: Monitor disk usage and set up alerts
* **Performance impact** - Balance logging detail with performance
  * **Symptom**: Slow application performance
  * **Solution**: Reduce log level or optimize logging configuration
  * **Prevention**: Test performance impact of logging changes
* **Log aggregation** - Configure centralized logging if needed
  * **Symptom**: Difficult to correlate logs across services
  * **Solution**: Use centralized logging like ELK stack or Azure Monitor
  * **Prevention**: Plan for log aggregation from the start

## Conclusion - Your Configuration Success Story 🎉

**What You've Accomplished** 🏆

* **Mastered FlexBase Configuration**: You now understand the power of centralized configuration
* **Learned Security Best Practices**: Your applications will be secure and compliant
* **Optimized for Performance**: Your applications will be fast and scalable
* **Built for Maintenance**: Your configurations will be easy to manage and update

**The Value You've Gained** 💎

* **Developer Productivity**: Spend less time on configuration, more on business logic
* **System Reliability**: Robust configurations that work in all environments
* **Security Confidence**: Know your data and systems are protected
* **Performance Excellence**: Applications that scale and perform beautifully
* **Operational Peace of Mind**: Systems that are easy to monitor and maintain

**Your Next Steps** 🚀

1. **Apply These Patterns**: Use this guide to configure your FlexBase applications
2. **Customize for Your Domain**: Adapt the examples to your specific business needs
3. **Share with Your Team**: Help your colleagues benefit from these best practices
4. **Keep Learning**: Stay updated with FlexBase framework improvements
5. **Contribute Back**: Share your own configuration discoveries with the community

**Remember**: Great configuration is the foundation of great applications. With the patterns and practices in this guide, you're well-equipped to build robust, scalable, and maintainable FlexBase applications that will serve your business for years to come! 🌟


# Default Bus Configuration

## Overview

This document explains the **NServiceBus configuration system** in FlexBase applications, using the EBusiness sample as a reference. The bus configuration provides a flexible, environment-aware messaging system that supports multiple transport and persistence options.

## Architecture Overview

The NServiceBus configuration in FlexBase follows a **strategy pattern** where different configurations are selected based on the environment and requirements. This allows for seamless transitions between development, staging, and production environments.

### **Configuration Flow**

```
Environment Detection → Configuration Selection → Transport Setup → Persistence Setup → Routing Configuration
```

## Project Structure

### **EBusiness.Nsb Project**

The `EBusiness.Nsb` project contains all NServiceBus configuration implementations:

```
EBusiness.Nsb/
├── EBusiness.Nsb.csproj                    # Project file with NServiceBus packages
├── LearningNsbConfiguration.cs             # Development/Testing transport
├── RabbitMqNsbConfiguration.cs             # Production RabbitMQ transport
├── SqlNsbConfiguration.cs                  # SQL Server transport
├── AzureServiceNsbConfiguration.cs         # Azure Service Bus transport
├── AzureStorageQueueNsbConfiguration.cs    # Azure Storage Queue transport
├── AmazonSQSNsbConfiguration.cs            # Amazon SQS transport
└── MyCustomNsbConfiguration.cs             # Template for custom configurations
```

### **Dependencies**

The project references multiple FlexBase NServiceBus packages:

```xml
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Azure.Storage" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Learning" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.OnPremises.Rabbit" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Amazon.SQS" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.Azure.ServiceBus" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.SqlTransport" Version="9.2.0" />
<PackageReference Include="Sumeru.Flex.ServiceBus.Nsb.SqlPersistence" Version="9.2.0" />
```

## Configuration Selection Logic

### **BusEndPointConfig.cs - Environment-Based Selection**

The `BusEndPointConfig.cs` file contains the logic for selecting the appropriate NServiceBus configuration based on the environment:

```csharp
public static EndpointConfiguration GetEndpoint(IConfiguration configuration, IHostEnvironment env, List<BusRouteConfig> routes)
{
    string endPointName = configuration.GetSection("EndPoint")["Name"];
    
    NsbDefaultEndpointConfiguration endPointConfig;
    
    if (env.IsDevelopment())
    {
        endPointConfig = new LearningNsbConfiguration(endPointName, routes, configuration, env);
    }
    else if (env.IsStaging())
    {
        endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
    }
    else if (env.IsProduction())
    {
        endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
    }
    else
    {
        endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
    }
    
    return endPointConfig;
}
```

### **Environment Mapping**

| Environment     | Configuration              | Transport          | Persistence          | Use Case                    |
| --------------- | -------------------------- | ------------------ | -------------------- | --------------------------- |
| **Development** | `LearningNsbConfiguration` | Learning Transport | Learning Persistence | Local development, testing  |
| **Staging**     | `RabbitMqNsbConfiguration` | RabbitMQ           | SQL Server           | Pre-production testing      |
| **Production**  | `RabbitMqNsbConfiguration` | RabbitMQ           | SQL Server           | Live production environment |
| **Default**     | `RabbitMqNsbConfiguration` | RabbitMQ           | SQL Server           | Fallback configuration      |

## Transport Configurations

### **1. Learning Transport (Development)**

**File**: `LearningNsbConfiguration.cs`

```csharp
public class LearningNsbConfiguration : NsbBaseConfiguration
{
    public LearningNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endpointName, configuration, env, errorQueueName)
    {
        // Configure persistence
        var persistence = this.UsePersistence<LearningPersistence>();
        
        // Configure transport
        var transport = this.UseTransport<LearningTransport>();
        
        // Configure routing
        var routing = transport.Routing();
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

**Characteristics:**

* **File-Based**: Stores messages in local file system
* **No Dependencies**: No external infrastructure required
* **Development Only**: Not suitable for production
* **Auto-Cleanup**: Automatically manages message storage

**Configuration Requirements:**

* No connection strings required
* Creates `.learningtransport` directory automatically
* Perfect for local development and testing

### **2. RabbitMQ Transport (Production)**

**File**: `RabbitMqNsbConfiguration.cs`

```csharp
public class RabbitMqNsbConfiguration : NsbBaseConfiguration
{
    public RabbitMqNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endPointName, configuration, env, errorQueueName)
    {
        string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
        string rabbitMqConnectionString = configuration.GetSection("FlexBase")["RabbitMqConnectionString"];
        
        // Configure persistence
        var persistence = this.UsePersistence<SqlPersistence>();
        persistence.SqlDialect<SqlDialect.MsSqlServer>();
        persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
        
        // Configure transport
        var transport = this.UseTransport<RabbitMQTransport>();
        transport.ConnectionString(rabbitMqConnectionString);
        transport.UseConventionalRoutingTopology(QueueType.Classic);
        
        // Configure routing
        var routing = transport.Routing();
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

**Characteristics:**

* **High Performance**: Excellent for high-throughput scenarios
* **Reliable**: Message durability and delivery guarantees
* **Scalable**: Horizontal scaling capabilities
* **Production Ready**: Suitable for enterprise environments

**Configuration Requirements:**

```json
{
  "FlexBase": {
    "SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
    "RabbitMqConnectionString": "amqp://YourUser:YourPassword@YourRabbitMqHost:YourPort"
  }
}
```

### **3. SQL Server Transport**

**File**: `SqlNsbConfiguration.cs`

```csharp
public class SqlNsbConfiguration : NsbBaseConfiguration
{
    public SqlNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endPointName, configuration, env, errorQueueName)
    {
        string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
        string sqlTransportConnectionString = configuration.GetSection("FlexBase")["SqlTransportConnectionString"];
        
        // Configure persistence
        var persistence = this.UsePersistence<SqlPersistence>();
        persistence.SqlDialect<SqlDialect.MsSqlServer>();
        persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
        
        // Configure transport
        var transport = new SqlServerTransport(sqlTransportConnectionString);
        this.UseTransport(transport);
        
        // Configure routing
        var routing = this.UseTransport(transport);
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

**Characteristics:**

* **Database-Based**: Uses SQL Server for message transport
* **Transactional**: Leverages SQL Server transactions
* **Familiar**: Easy to monitor and debug
* **Reliable**: ACID compliance for message delivery

**Configuration Requirements:**

```json
{
  "FlexBase": {
    "SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
    "SqlTransportConnectionString": "Data Source=YourServer;Initial Catalog=YourTransportDb;..."
  }
}
```

### **4. Azure Service Bus Transport**

**File**: `AzureServiceNsbConfiguration.cs`

```csharp
public class AzureServiceNsbConfiguration : NsbBaseConfiguration
{
    public AzureServiceNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endPointName, configuration, env, errorQueueName)
    {
        string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
        string azureServiceBusConnectionString = configuration.GetSection("FlexBase")["AzureServiceBusConnectionString"];
        
        // Configure persistence
        var persistence = this.UsePersistence<SqlPersistence>();
        persistence.SqlDialect<SqlDialect.MsSqlServer>();
        persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
        
        // Configure transport
        var transport = new AzureServiceBusTransport(azureServiceBusConnectionString);
        this.UseTransport(transport);
        
        // Configure routing
        var routing = this.UseTransport(transport);
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

**Characteristics:**

* **Cloud-Native**: Fully managed Azure service
* **Scalable**: Auto-scaling capabilities
* **Reliable**: 99.9% SLA guarantee
* **Integrated**: Works seamlessly with other Azure services

**Configuration Requirements:**

```json
{
  "FlexBase": {
    "SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
    "AzureServiceBusConnectionString": "Endpoint=sb://YourNamespace.servicebus.windows.net/;SharedAccessKeyName=YourKeyName;SharedAccessKey=YourKey"
  }
}
```

### **5. Azure Storage Queue Transport**

**File**: `AzureStorageQueueNsbConfiguration.cs`

```csharp
public class AzureStorageQueueNsbConfiguration : NsbBaseConfiguration
{
    public AzureStorageQueueNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endPointName, configuration, env, errorQueueName)
    {
        string azureConnectionString = configuration.GetSection("FlexBase")["AzureStorageConnectionString"];
        
        // Configure persistence
        var persistence = this.UsePersistence<AzureTablePersistence>();
        persistence.ConnectionString(azureConnectionString);
        
        // Configure transport
        var queueServiceClient = new QueueServiceClient(azureConnectionString, new QueueClientOptions());
        var blobServiceClient = new BlobServiceClient(azureConnectionString, new BlobClientOptions());
        var tableServiceClient = new TableServiceClient(azureConnectionString, new TableClientOptions());
        
        var transport = new AzureStorageQueueTransport(queueServiceClient, blobServiceClient, tableServiceClient)
        {
            ReceiverBatchSize = 20,
            MaximumWaitTimeWhenIdle = TimeSpan.FromSeconds(1),
            DegreeOfReceiveParallelism = 16,
            PeekInterval = TimeSpan.FromMilliseconds(100),
            MessageInvisibleTime = TimeSpan.FromSeconds(30)
        };
        
        // Configure routing
        var routing = this.UseTransport(transport);
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
            routing.RegisterPublisher(route.Assembly, route.Destination);
        }
    }
}
```

**Characteristics:**

* **Cost-Effective**: Lower cost than Service Bus
* **Simple**: Easy to set up and manage
* **Scalable**: Handles high message volumes
* **Azure-Native**: Integrated with Azure ecosystem

**Configuration Requirements:**

```json
{
  "FlexBase": {
    "AzureStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=YourAccount;AccountKey=YourKey;EndpointSuffix=core.windows.net"
  }
}
```

### **6. Amazon SQS Transport**

**File**: `AmazonSQSNsbConfiguration.cs`

```csharp
public class AmazonSQSNsbConfiguration : NsbBaseConfiguration
{
    public AmazonSQSNsbConfiguration(string endpointName, IEnumerable<BusRouteConfig> routes, IConfiguration configuration, IHostEnvironment env, string errorQueueName = "error") 
        : base(endPointName, configuration, env, errorQueueName)
    {
        string sqlPersistenceConnectionString = configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"];
        string s3BucketName = configuration.GetSection("FlexBase")["AmazonSQSTransportBucketName"];
        string s3KeyPrefix = configuration.GetSection("FlexBase")["AmazonSQSTransportKeyPrefix"];
        
        // Configure persistence
        var persistence = this.UsePersistence<SqlPersistence>();
        persistence.SqlDialect<SqlDialect.MsSqlServer>();
        persistence.ConnectionBuilder(() => new SqlConnection(sqlPersistenceConnectionString));
        
        // Configure transport
        var transport = new SqsTransport
        {
            S3 = new S3Settings(
                bucketForLargeMessages: s3BucketName,
                keyPrefix: s3KeyPrefix,
                s3Client: new AmazonS3Client())
        };
        
        // Configure routing
        var routing = this.UseTransport(transport);
        foreach (var route in routes)
        {
            routing.RouteToEndpoint(route.Assembly, route.Destination);
        }
    }
}
```

**Characteristics:**

* **AWS-Native**: Fully integrated with AWS services
* **Scalable**: Auto-scaling message queues
* **Reliable**: High availability and durability
* **Cost-Effective**: Pay-per-use pricing model

**Configuration Requirements:**

```json
{
  "FlexBase": {
    "SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
    "AmazonSQSTransportBucketName": "YourS3BucketName",
    "AmazonSQSTransportKeyPrefix": "YourKeyPrefix"
  }
}
```

## Service Registration

### **BusEndPointConfig.cs - Service Registration**

The `BusEndPointConfig.cs` file also handles service registration for dependency injection:

```csharp
public static void AddFlexBaseBusServices(this IServiceCollection services)
{
    services.AddSingleton<IFlexServiceBusBridge, NsbServiceBusBridge>();
    services.AddTransient<FlexBusSendOptions, NsbSendOptions>();
}
```

**What This Does:**

* **Service Bus Bridge**: Registers the NServiceBus bridge as a singleton
* **Send Options**: Registers send options for message publishing
* **Dependency Injection**: Makes bus services available throughout the application

## Configuration Best Practices

### **1. Environment-Specific Configuration**

```csharp
// Development
if (env.IsDevelopment())
{
    endPointConfig = new LearningNsbConfiguration(endPointName, routes, configuration, env);
}

// Staging
else if (env.IsStaging())
{
    endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}

// Production
else if (env.IsProduction())
{
    endPointConfig = new RabbitMqNsbConfiguration(endPointName, routes, configuration, env);
}
```

### **2. Connection String Management**

```json
{
  "FlexBase": {
    "SqlPersistenceConnectionString": "Data Source=YourServer;Initial Catalog=YourPersistenceDb;...",
    "RabbitMqConnectionString": "amqp://YourUser:YourPassword@YourRabbitMqHost:YourPort",
    "AzureServiceBusConnectionString": "Endpoint=sb://YourNamespace.servicebus.windows.net/;...",
    "AzureStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=YourAccount;...",
    "AmazonSQSTransportBucketName": "YourS3BucketName",
    "AmazonSQSTransportKeyPrefix": "YourKeyPrefix"
  }
}
```

### **3. Error Handling**

```csharp
Guard.AgainstNullAndEmpty("SqlPersistenceConnectionString for connection string cannot be empty", 
    configuration.GetSection("FlexBase")["SqlPersistenceConnectionString"]);
```

### **4. Routing Configuration**

```csharp
var routing = transport.Routing();
foreach (var route in routes)
{
    routing.RouteToEndpoint(route.Assembly, route.Destination);
}
```

## Custom Configuration Template

### **MyCustomNsbConfiguration.cs**

```csharp
public class MyCustomNsbConfiguration : EndpointConfiguration
{
    public MyCustomNsbConfiguration(string endpointName, string errorQueueName = "error") : base(endpointName)
    {
        this.SendFailedMessagesTo(errorQueueName);
        
        // Add all other NSB Configuration here
        // - Transport configuration
        // - Persistence configuration
        // - Routing configuration
        // - Serialization settings
        // - Error handling
        // - Performance tuning
    }
}
```

**Use Cases:**

* **Custom Requirements**: Specific business needs not covered by standard configurations
* **Performance Tuning**: Optimized settings for specific scenarios
* **Integration**: Custom transport or persistence providers
* **Testing**: Specialized configurations for testing scenarios

## Performance Considerations

### **Transport Selection Guidelines**

| Scenario            | Recommended Transport | Reason                               |
| ------------------- | --------------------- | ------------------------------------ |
| **Development**     | Learning Transport    | No external dependencies, easy setup |
| **Small Scale**     | SQL Server Transport  | Familiar, easy to monitor            |
| **High Throughput** | RabbitMQ Transport    | Excellent performance, reliable      |
| **Cloud-Native**    | Azure Service Bus     | Fully managed, integrated            |
| **Cost-Sensitive**  | Azure Storage Queue   | Lower cost, good performance         |
| **AWS Environment** | Amazon SQS            | Native AWS integration               |

### **Persistence Selection Guidelines**

| Scenario        | Recommended Persistence | Reason                              |
| --------------- | ----------------------- | ----------------------------------- |
| **Development** | Learning Persistence    | No external dependencies            |
| **Production**  | SQL Server Persistence  | Reliable, familiar, ACID compliance |
| **Azure**       | Azure Table Persistence | Native Azure integration            |

## Troubleshooting

### **Common Issues**

1. **Connection String Errors**
   * Verify connection strings in configuration
   * Check network connectivity
   * Validate credentials
2. **Transport Failures**
   * Ensure transport service is running
   * Check firewall settings
   * Verify endpoint configuration
3. **Routing Issues**
   * Verify route configuration
   * Check assembly references
   * Validate destination endpoints
4. **Performance Problems**
   * Monitor message throughput
   * Check resource utilization
   * Consider transport scaling

### **Debugging Tips**

1. **Enable Logging**: Use structured logging to track message flow
2. **Monitor Queues**: Check queue depths and processing rates
3. **Health Checks**: Implement health checks for transport and persistence
4. **Metrics**: Use application insights or similar tools for monitoring

## Key Benefits

* **Environment Awareness**: Automatic configuration based on environment
* **Multiple Transports**: Support for various messaging technologies
* **Flexible Persistence**: Multiple persistence options
* **Easy Configuration**: Simple configuration management
* **Production Ready**: Battle-tested configurations
* **Scalable**: Supports high-throughput scenarios
* **Reliable**: Built-in error handling and retry mechanisms
* **Maintainable**: Clear separation of concerns
* **Testable**: Easy to test with different configurations

***

**This NServiceBus configuration system provides a robust, scalable, and maintainable messaging infrastructure that adapts to different environments and requirements!** 🚀


# EFCore Configuration

## Overview

This document explains the **Entity Framework Core configuration system** in FlexBase applications, using the EBusiness sample as a reference. The EF Core configuration provides a flexible, multi-database, multi-tenant data access layer that supports SQL Server, MySQL, and PostgreSQL with both single-tenant and multi-tenant architectures.

## Architecture Overview

The EF Core configuration in FlexBase follows a **layered architecture** with separate projects for different database providers and tenant configurations. This allows for seamless transitions between different database systems and tenant models.

### **Configuration Flow**

```
Database Selection → Tenant Model Selection → Connection Provider Setup → DbContext Configuration → Repository Registration
```

## Project Structure

### **Database Infrastructure Projects**

The `EBusiness.Application/Infrastructure/Db/` folder contains all EF Core configuration implementations:

```
EBusiness.Application/Infrastructure/Db/
├── EBusiness.BaseEF/                          # Core EF configuration
│   ├── ApplicationEFDbContext.cs              # Single-tenant DbContext
│   ├── ApplicationTenantEFDbContext.cs        # Multi-tenant DbContext
│   ├── ConnectionProviders/                   # Connection provider implementations
│   │   ├── AppSettingsReadDbConnectionProvider.cs
│   │   ├── AppSettingsWriteDbConnectionProvider.cs
│   │   ├── NativeReadDbTenantConnectionProvider.cs
│   │   └── NativeWriteDbTenantConnectionProvider.cs
│   └── EBusiness.BaseEF.csproj
├── EBusiness.BaseEF.SqlServer/                # SQL Server implementation
│   ├── ApplicationEFSqlServerDbContext.cs
│   ├── FlexEFTenantMasterSqlServerContext.cs
│   ├── FlexReadDbRepositoryEFSQLServer.cs
│   ├── FlexWriteDbRepositoryEFSQLServer.cs
│   ├── FlexTenantMasterRepositoryEFSQLServer.cs
│   └── EBusiness.BaseEF.SqlServer.csproj
├── EBusiness.BaseEF.MySql/                    # MySQL implementation
│   ├── ApplicationEFMySqlDbContext.cs
│   ├── FlexEFTenantMasterMySqlContext.cs
│   ├── FlexReadDbRepositoryEFMySql.cs
│   ├── FlexWriteDbRepositoryEFMySql.cs
│   ├── FlexTenantMasterRepositoryEFMySql.cs
│   └── EBusiness.BaseEF.MySql.csproj
└── EBusiness.BaseEF.PostgreSql/               # PostgreSQL implementation
    ├── ApplicationEFPostgreSqlDbContext.cs
    ├── FlexEFTenantMasterPostgreSqlContext.cs
    ├── FlexReadDbRepositoryEFPostgreSql.cs
    ├── FlexWriteDbRepositoryEFPostgreSql.cs
    ├── FlexTenantMasterRepositoryEFPostgreSql.cs
    └── EBusiness.BaseEF.PostgreSql.csproj
└── EBusiness.BaseEF.Oracle/                   # Oracle implementation (example)
    ├── ApplicationEFOracleDbContext.cs
    ├── FlexEFTenantMasterOracleContext.cs
    ├── FlexReadDbRepositoryEFOracle.cs
    ├── FlexWriteDbRepositoryEFOracle.cs
    ├── FlexTenantMasterRepositoryEFOracle.cs
    └── EBusiness.BaseEF.Oracle.csproj
```

### **Dependencies**

Each project references specific FlexBase EF Core packages:

```xml
<!-- Core EF Package -->
<PackageReference Include="Sumeru.Flex.Data.EntityFramework" Version="9.0.0" />

<!-- Database-Specific Packages -->
<PackageReference Include="Sumeru.Flex.Data.EntityFramework.SqlServer" Version="9.0.0" />
<PackageReference Include="Sumeru.Flex.Data.EntityFramework.MySql" Version="9.0.0" />
<PackageReference Include="Sumeru.Flex.Data.EntityFramework.PostgreSql" Version="9.0.0" />
<PackageReference Include="Sumeru.Flex.Data.EntityFramework.Oracle" Version="9.0.0" />
```

## Configuration Selection Logic

### **DbEndPointConfig.cs - Database and Tenant Configuration**

The `DbEndPointConfig.cs` file contains the logic for selecting the appropriate database configuration:

```csharp
public static class DbEndPointConfig
{
    public static void AddFlexBaseDbServices(this IServiceCollection services)
    {
        //Configuration for Single Tenant Database
        EnableSingleTenant(services);

        //Configuration for Multi Tenant Database
        //EnableMultitenant(services);
    }

    private static void EnableSingleTenant(IServiceCollection services)
    {
        ConfigureSingleTenantDb(services);
        ConfigureFlexDb.ForRepositoryForSqlServer(services);
    }

    private static void EnableMultitenant(IServiceCollection services)
    {
        ConfigureMultiTenantMasterDb(services);

        //Either 
        //If you want to use the same sql server for all instances for multitenant application
        //You may do this if you want MySql Or PostgreSql respectively
        ConfigureFlexDb.ForMultitenantMasterDbForSqlServer(services);
        ConfigureFlexDb.ForRepositoryForSqlServer(services);
        

        //Or 
        //ConfigureFlexDb.ForRepositoryForMultiDb(services); //If you want to use different database type for each tenant
    }
}
```

## Single Tenant vs Multi-Tenant Architecture

### **Single Tenant Architecture**

**Definition**: A single tenant architecture means that each customer (tenant) has their own dedicated database instance. All data for a tenant is completely isolated from other tenants.

#### **Characteristics:**

* **Data Isolation**: Complete physical separation of tenant data
* **Performance**: No cross-tenant performance impact
* **Security**: Highest level of data security and isolation
* **Scalability**: Each tenant can scale independently
* **Cost**: Higher cost due to dedicated resources per tenant

#### **Configuration:**

```csharp
private static void EnableSingleTenant(IServiceCollection services)
{
    ConfigureSingleTenantDb(services);
    ConfigureFlexDb.ForRepositoryForSqlServer(services);
}

private static void ConfigureSingleTenantDb(IServiceCollection services)
{
    //Default Settings for connection provider which gives you a simple single tenant application
    services.AddTransient<IWriteDbConnectionProviderBridge, AppSettingsWriteDbConnectionProvider>();
    services.AddTransient<IReadDbConnectionProviderBridge, AppSettingsReadDbConnectionProvider>();
}
```

#### **Connection Providers:**

* **AppSettingsWriteDbConnectionProvider**: Reads write database connection from appsettings
* **AppSettingsReadDbConnectionProvider**: Reads read database connection from appsettings

#### **Use Cases:**

* **Enterprise Applications**: Large organizations with strict data isolation requirements
* **Compliance Requirements**: Industries requiring complete data separation
* **High-Value Customers**: Premium customers requiring dedicated resources
* **Regulatory Compliance**: GDPR, HIPAA, SOX compliance scenarios

### **Multi-Tenant Architecture**

**Definition**: A multi-tenant architecture means that multiple customers (tenants) have their own independent database instances, with complete data isolation and independent scaling capabilities. FlexBase's default implementation provides each tenant with their own dedicated database.

#### **Characteristics:**

* **Independent Databases**: Each tenant has their own dedicated database instance
* **Complete Data Isolation**: Physical separation ensures maximum security and confidentiality
* **Independent Scaling**: Each tenant can scale based on their specific usage patterns
* **Cost Optimization**: Cloud databases can be scaled independently per tenant usage
* **Security**: Highest level of data security with no cross-tenant data access
* **Performance**: No cross-tenant performance impact or resource contention

#### **Configuration:**

```csharp
private static void EnableMultitenant(IServiceCollection services)
{
    ConfigureMultiTenantMasterDb(services);

    //Option 1: Same database type for all tenants
    ConfigureFlexDb.ForMultitenantMasterDbForSqlServer(services);
    ConfigureFlexDb.ForRepositoryForSqlServer(services);
    
    //Option 2: Different database types for different tenants
    //ConfigureFlexDb.ForRepositoryForMultiDb(services);
}

private static void ConfigureMultiTenantMasterDb(IServiceCollection services)
{
    //Default Settings for connection provider which gives you a simple multi tenant application
    services.AddTransient<IWriteDbConnectionProviderBridge, NativeWriteDbTenantConnectionProvider>();
    services.AddTransient<IReadDbConnectionProviderBridge, NativeReadDbTenantConnectionProvider>();
}
```

#### **Connection Providers:**

* **NativeWriteDbTenantConnectionProvider**: Dynamically determines write database based on tenant
* **NativeReadDbTenantConnectionProvider**: Dynamically determines read database based on tenant

#### **FlexBase Multi-Tenant Advantages:**

**1. Independent Database Scaling 🚀**

```csharp
// Each tenant gets their own database instance
Tenant A: Database_A (Small instance - 2 vCores, 8GB RAM)
Tenant B: Database_B (Large instance - 16 vCores, 64GB RAM)
Tenant C: Database_C (Medium instance - 8 vCores, 32GB RAM)
```

**Benefits:**

* **Usage-Based Scaling**: Each tenant scales based on their actual usage
* **Cost Optimization**: Tenants pay only for resources they consume
* **Performance Isolation**: Heavy usage by one tenant doesn't affect others
* **Cloud-Native**: Leverages cloud database auto-scaling features

**2. Enhanced Security & Compliance 🔒**

```csharp
// Complete data isolation per tenant
Tenant A Data: Completely isolated in Database_A
Tenant B Data: Completely isolated in Database_B
Tenant C Data: Completely isolated in Database_C
```

**Benefits:**

* **Physical Data Separation**: No shared tables or cross-tenant data access
* **Regulatory Compliance**: Meets strict compliance requirements (GDPR, HIPAA, SOX)
* **Data Sovereignty**: Tenants can be deployed in specific regions
* **Audit Trail**: Complete isolation makes auditing easier

**3. Independent Database Types 🗄️**

```csharp
// Different tenants can use different database types
Tenant A: SQL Server (Enterprise features)
Tenant B: MySQL (Cost-effective)
Tenant C: PostgreSQL (Advanced features)
Tenant D: Oracle (High-performance analytics)
```

**Benefits:**

* **Technology Choice**: Each tenant can choose their preferred database
* **Migration Flexibility**: Easy to migrate tenants between database types
* **Feature Optimization**: Match database features to tenant requirements
* **Cost Optimization**: Use cost-effective databases for appropriate workloads

**4. Cloud Database Integration ☁️**

```csharp
// Cloud-native database scaling per tenant
Azure SQL Database: Auto-scaling based on tenant usage
AWS RDS: Independent scaling per tenant
Google Cloud SQL: Per-tenant resource allocation
```

**Benefits:**

* **Auto-Scaling**: Cloud databases automatically scale based on tenant usage
* **Pay-Per-Use**: Only pay for actual database usage per tenant
* **Global Distribution**: Tenants can be deployed in different regions
* **Disaster Recovery**: Independent backup and recovery per tenant

#### **Use Cases:**

* **SaaS Applications**: Software-as-a-Service applications serving multiple customers with independent scaling
* **Enterprise SaaS**: Large enterprise customers requiring dedicated database resources
* **Compliance-Critical Applications**: Applications requiring strict data isolation and confidentiality
* **Cloud-Native Applications**: Applications leveraging cloud database auto-scaling per tenant
* **Multi-Region Deployments**: Tenants can be deployed in different regions for data sovereignty
* **Cost-Optimized Scaling**: Each tenant pays only for their actual usage and scales independently

## Database Provider Configurations

### **1. SQL Server Configuration**

**Project**: `EBusiness.BaseEF.SqlServer`

#### **DbContext Implementation:**

```csharp
public class ApplicationEFSqlServerDbContext : ApplicationEFDbContext
{
    public ApplicationEFSqlServerDbContext()
    {
        //this constructor goes only with the migrations
    }

    public ApplicationEFSqlServerDbContext(DbContextOptions<ApplicationEFSqlServerDbContext> options) : base(options)
    {
        //this constructor is being used by the repos to initialize the context with various options including multitenancy
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}
```

#### **Tenant Master Context:**

```csharp
public class FlexEFTenantMasterSqlServerContext : ApplicationTenantEFDbContext
{
    public FlexEFTenantMasterSqlServerContext() : base()
    {
    }

    public FlexEFTenantMasterSqlServerContext(DbContextOptions options): base(options)
    {
    }
}
```

#### **Characteristics:**

* **Enterprise Grade**: Full-featured enterprise database
* **ACID Compliance**: Complete transactional support
* **High Performance**: Optimized for complex queries
* **Rich Features**: Advanced indexing, partitioning, etc.
* **Windows Integration**: Native Windows authentication support

#### **Configuration Requirements:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=YourServer;Initial Catalog=YourDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "AppReadDbConnection": "Data Source=YourServer;Initial Catalog=YourReadDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True"
  }
}
```

### **2. MySQL Configuration**

**Project**: `EBusiness.BaseEF.MySql`

#### **Characteristics:**

* **Open Source**: Free and open-source database
* **Cross-Platform**: Runs on multiple operating systems
* **High Performance**: Optimized for read-heavy workloads
* **Easy Setup**: Simple installation and configuration
* **Cost Effective**: No licensing costs

#### **Configuration Requirements:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Server=YourServer;Database=YourDatabase;Uid=YourUser;Pwd=YourPassword;",
    "AppReadDbConnection": "Server=YourServer;Database=YourReadDatabase;Uid=YourUser;Pwd=YourPassword;"
  }
}
```

### **3. PostgreSQL Configuration**

**Project**: `EBusiness.BaseEF.PostgreSql`

#### **Characteristics:**

* **Advanced Features**: Rich set of data types and functions
* **ACID Compliance**: Full transactional support
* **Extensible**: Custom data types and functions
* **JSON Support**: Native JSON and JSONB support
* **Open Source**: Free and open-source

#### **Configuration Requirements:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Host=YourServer;Database=YourDatabase;Username=YourUser;Password=YourPassword;",
    "AppReadDbConnection": "Host=YourServer;Database=YourReadDatabase;Username=YourUser;Password=YourPassword;"
  }
}
```

### **4. Oracle Configuration**

**Project**: `EBusiness.BaseEF.Oracle`

#### **DbContext Implementation:**

```csharp
public class ApplicationEFOracleDbContext : ApplicationEFDbContext
{
    public ApplicationEFOracleDbContext()
    {
        //this constructor goes only with the migrations
    }

    public ApplicationEFOracleDbContext(DbContextOptions<ApplicationEFOracleDbContext> options) : base(options)
    {
        //this constructor is being used by the repos to initialize the context with various options including multitenancy
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}
```

#### **Tenant Master Context:**

```csharp
public class FlexEFTenantMasterOracleContext : ApplicationTenantEFDbContext
{
    public FlexEFTenantMasterOracleContext() : base()
    {
    }

    public FlexEFTenantMasterOracleContext(DbContextOptions options): base(options)
    {
    }
}
```

#### **Characteristics:**

* **Enterprise Grade**: Full-featured enterprise database
* **ACID Compliance**: Complete transactional support
* **High Performance**: Optimized for complex enterprise workloads
* **Advanced Features**: Partitioning, advanced analytics, machine learning
* **Scalability**: Handles large-scale enterprise applications
* **Security**: Advanced security features and compliance

#### **Configuration Requirements:**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=YourServer:1521/YourServiceName;User Id=YourUser;Password=YourPassword;",
    "AppReadDbConnection": "Data Source=YourServer:1521/YourReadServiceName;User Id=YourUser;Password=YourPassword;"
  }
}
```

#### **Oracle-Specific Features:**

* **Partitioning**: Advanced table partitioning support
* **JSON Support**: Native JSON data type support
* **Spatial Data**: Geographic and spatial data support
* **Machine Learning**: Built-in machine learning algorithms
* **Advanced Analytics**: OLAP and data warehousing features
* **Real Application Clusters (RAC)**: High availability and scalability

## Core EF Configuration

### **ApplicationEFDbContext.cs - Single Tenant Context**

```csharp
public class ApplicationEFDbContext : FlexEFDbContext
{
    public ApplicationEFDbContext()
    {
        //this constructor goes only with the migrations
    }

    public ApplicationEFDbContext(DbContextOptions options) : base(options)
    {
        //this constructor is being used by the repos to initialize the context with various options including multitenancy

        //Uncomment below code to enable audit trail for your CUD transactions
        //this.EnableAuditTrail();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //Use this for adding indexes or other customizations to tables pertaining to EF implementation
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        ILogger _logger = FlexContainer.ServiceProvider.GetRequiredService<ILogger<ApplicationEFDbContext>>();

        base.OnConfiguring(optionsBuilder);

        optionsBuilder
            .EnableSensitiveDataLogging() 
            .LogTo(message => _logger.LogDebug(message)) //This is to log the EF queries to the logger
            .AddInterceptors(new DefaultCreationTimeInterceptor()); //This is to set the creation time for the entities
    }
}
```

**Key Features:**

* **Migration Support**: Constructor for EF migrations
* **Repository Integration**: Constructor for repository initialization
* **Audit Trail**: Optional audit trail for CUD operations
* **Query Logging**: Automatic query logging to logger
* **Creation Time**: Automatic creation time setting for entities

### **ApplicationTenantEFDbContext.cs - Multi-Tenant Context**

```csharp
public class ApplicationTenantEFDbContext : FlexEFTenantContext<FlexTenantBridge>
{
    public ApplicationTenantEFDbContext() : base()
    {
    }

    public ApplicationTenantEFDbContext(DbContextOptions options) :base(options)
    {
    }
}
```

**Key Features:**

* **Tenant Awareness**: Built-in tenant context support
* **Tenant Isolation**: Automatic tenant-based data filtering
* **Flexible Configuration**: Supports various tenant models

## Connection Providers

### **Single Tenant Connection Providers**

#### **AppSettingsWriteDbConnectionProvider.cs**

```csharp
public class AppSettingsWriteDbConnectionProvider : FlexAppSettingsWriteDbConnectionProvider<FlexAppContextBridge>, IWriteDbConnectionProviderBridge
{
    public AppSettingsWriteDbConnectionProvider(IConfiguration configuration) : base(configuration)
    {
    }
}
```

#### **AppSettingsReadDbConnectionProvider.cs**

```csharp
public class AppSettingsReadDbConnectionProvider : FlexAppSettingsReadDbConnectionProvider<FlexAppContextBridge>, IReadDbConnectionProviderBridge
{
    public AppSettingsReadDbConnectionProvider(IConfiguration configuration) : base(configuration)
    {
    }
}
```

**Characteristics:**

* **Configuration-Based**: Reads connection strings from appsettings
* **Static**: Same connection for all operations
* **Simple**: Easy to configure and maintain

### **Multi-Tenant Connection Providers**

#### **NativeWriteDbTenantConnectionProvider.cs**

```csharp
public class NativeWriteDbTenantConnectionProvider : FlexNativeWriteDbTenantConnectionProvider<FlexTenantBridge, FlexAppContextBridge>, IWriteDbConnectionProviderBridge
{
    public NativeWriteDbTenantConnectionProvider(IFlexNativeHostTenantProviderBridge flexTenantProvider) : base(flexTenantProvider)
    {
    }
}
```

#### **NativeReadDbTenantConnectionProvider.cs**

```csharp
public class NativeReadDbTenantConnectionProvider : FlexNativeReadDbTenantConnectionProvider<FlexTenantBridge, FlexAppContextBridge>, IReadDbConnectionProviderBridge
{
    public NativeReadDbTenantConnectionProvider(IFlexNativeHostTenantProviderBridge flexTenantProvider) : base(flexTenantProvider)
    {
    }
}
```

**Characteristics:**

* **Dynamic**: Connection determined at runtime based on tenant
* **Tenant-Aware**: Automatically switches between tenant databases
* **Flexible**: Supports different database types per tenant

## Repository Implementations

### **SQL Server Repositories**

#### **FlexWriteDbRepositoryEFSQLServer.cs**

* **Write Operations**: Handles all database write operations
* **SQL Server Specific**: Optimized for SQL Server features
* **Transaction Support**: Full transactional support

#### **FlexReadDbRepositoryEFSQLServer.cs**

* **Read Operations**: Handles all database read operations
* **Query Optimization**: Optimized for read performance
* **Connection Pooling**: Efficient connection management

#### **FlexTenantMasterRepositoryEFSQLServer.cs**

* **Tenant Management**: Handles tenant-specific operations
* **Master Data**: Manages tenant master data
* **Tenant Resolution**: Resolves tenant information

### **MySQL Repositories**

#### **FlexWriteDbRepositoryEFMySql.cs**

* **MySQL Optimized**: Optimized for MySQL features
* **Performance Tuned**: Tuned for MySQL performance characteristics
* **MySQL Specific**: Leverages MySQL-specific features

#### **FlexReadDbRepositoryEFMySql.cs**

* **Read Optimization**: Optimized for MySQL read operations
* **Query Tuning**: Tuned for MySQL query patterns
* **Connection Management**: Efficient MySQL connection handling

### **PostgreSQL Repositories**

#### **FlexWriteDbRepositoryEFPostgreSql.cs**

* **PostgreSQL Features**: Leverages PostgreSQL advanced features
* **JSON Support**: Native JSON and JSONB support
* **Advanced Types**: Support for custom data types

#### **FlexReadDbRepositoryEFPostgreSql.cs**

* **Query Optimization**: Optimized for PostgreSQL query patterns
* **Index Support**: Advanced indexing support
* **Performance Tuning**: Tuned for PostgreSQL performance

### **Oracle Repositories**

#### **FlexWriteDbRepositoryEFOracle.cs**

* **Oracle Optimized**: Optimized for Oracle features
* **Performance Tuned**: Tuned for Oracle performance characteristics
* **Oracle Specific**: Leverages Oracle-specific features
* **Partitioning Support**: Advanced partitioning capabilities

#### **FlexReadDbRepositoryEFOracle.cs**

* **Read Optimization**: Optimized for Oracle read operations
* **Query Tuning**: Tuned for Oracle query patterns
* **Connection Management**: Efficient Oracle connection handling
* **Analytics Support**: Advanced analytics query support

#### **FlexTenantMasterRepositoryEFOracle.cs**

* **Tenant Management**: Handles tenant-specific operations
* **Master Data**: Manages tenant master data
* **Tenant Resolution**: Resolves tenant information
* **Oracle RAC Support**: High availability and scalability

## Configuration Best Practices

### **1. Environment-Specific Configuration**

```csharp
// Development
if (env.IsDevelopment())
{
    EnableSingleTenant(services);
}

// Production
else if (env.IsProduction())
{
    EnableMultitenant(services);
}
```

### **2. Connection String Management**

```json
{
  "FlexBase": {
    "AppDbConnection": "Data Source=YourServer;Initial Catalog=YourDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "AppReadDbConnection": "Data Source=YourServer;Initial Catalog=YourReadDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True",
    "TenantMasterDbConnection": "Data Source=YourServer;Initial Catalog=YourTenantMasterDatabase;User ID=YourUser;Password=YourPassword;TrustServerCertificate=True"
  }
}
```

### **3. Database Selection Guidelines**

| Scenario                   | Recommended Database    | Reason                                     |
| -------------------------- | ----------------------- | ------------------------------------------ |
| **Enterprise**             | SQL Server/Oracle       | Full features, enterprise support          |
| **Cost-Sensitive**         | MySQL                   | Open source, no licensing costs            |
| **Advanced Features**      | PostgreSQL              | Rich feature set, extensibility            |
| **Large Scale Enterprise** | Oracle                  | Advanced analytics, partitioning, RAC      |
| **Windows Environment**    | SQL Server              | Native integration                         |
| **Linux Environment**      | MySQL/PostgreSQL/Oracle | Cross-platform support                     |
| **High Availability**      | Oracle                  | RAC, advanced clustering                   |
| **Analytics & ML**         | Oracle                  | Built-in ML algorithms, advanced analytics |

### **4. Tenant Model Selection**

| Scenario              | Recommended Model       | Reason                                                 |
| --------------------- | ----------------------- | ------------------------------------------------------ |
| **High Security**     | Single Tenant           | Complete data isolation                                |
| **Cost Optimization** | Multi-Tenant (FlexBase) | Independent scaling per tenant usage                   |
| **Rapid Scaling**     | Multi-Tenant (FlexBase) | Easy tenant onboarding with independent databases      |
| **Compliance**        | Multi-Tenant (FlexBase) | Physical data separation meets regulatory requirements |
| **SaaS Application**  | Multi-Tenant (FlexBase) | Independent scaling and cost optimization              |
| **Enterprise SaaS**   | Multi-Tenant (FlexBase) | Dedicated resources per tenant with cloud scaling      |
| **Multi-Region**      | Multi-Tenant (FlexBase) | Independent deployment per region                      |
| **Cloud-Native**      | Multi-Tenant (FlexBase) | Leverages cloud database auto-scaling                  |

## Performance Considerations

### **1. Connection Pooling**

**File**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF/ApplicationEFDbContext.cs`

```csharp
// Configure connection pooling
services.AddDbContext<ApplicationEFDbContext>(options =>
{
    options.UseSqlServer(connectionString, sqlOptions =>
    {
        sqlOptions.EnableRetryOnFailure(maxRetryCount: 3);
        sqlOptions.CommandTimeout(30);
    });
});
```

**Configuration Location**: `YourApplication.Application/EndPoints/YourApplication.EndPoint.WebAPI/Program.cs`

### **2. Query Optimization**

**File**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF/ApplicationEFDbContext.cs`

```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // Add indexes for performance
    modelBuilder.Entity<Order>()
        .HasIndex(o => o.CustomerId)
        .HasDatabaseName("IX_Orders_CustomerId");

    modelBuilder.Entity<Order>()
        .HasIndex(o => new { o.CustomerId, o.OrderDate })
        .HasDatabaseName("IX_Orders_CustomerId_OrderDate");
}
```

**Alternative Database-Specific Files**:

* **SQL Server**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF.SqlServer/ApplicationEFSqlServerDbContext.cs`
* **MySQL**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF.MySql/ApplicationEFMySqlDbContext.cs`
* **PostgreSQL**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF.PostgreSql/ApplicationEFPostgreSqlDbContext.cs`
* **Oracle**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF.Oracle/ApplicationEFOracleDbContext.cs`

### **3. Read/Write Separation**

**File**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF/DbEndPointConfig.cs`

```csharp
// Write database for CUD operations
services.AddTransient<IWriteDbConnectionProviderBridge, AppSettingsWriteDbConnectionProvider>();

// Read database for query operations
services.AddTransient<IReadDbConnectionProviderBridge, AppSettingsReadDbConnectionProvider>();
```

**Connection Provider Files**:

* **Write Provider**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF/ConnectionProviders/AppSettingsWriteDbConnectionProvider.cs`
* **Read Provider**: `YourApplication.Application/Infrastructure/Db/YourApplication.BaseEF/ConnectionProviders/AppSettingsReadDbConnectionProvider.cs`

## Troubleshooting

### **Common Issues**

1. **Connection String Errors**
   * Verify connection strings in configuration
   * Check database server accessibility
   * Validate credentials and permissions
2. **Migration Issues**
   * Ensure migration context is properly configured
   * Check database schema compatibility
   * Verify migration history
3. **Tenant Resolution Issues**
   * Verify tenant provider configuration
   * Check tenant context setup
   * Validate tenant identification logic
4. **Performance Problems**
   * Monitor query execution times
   * Check connection pool utilization
   * Review database indexes

### **Debugging Tips**

1. **Enable Query Logging**: Use `EnableSensitiveDataLogging()` for detailed query information
2. **Monitor Connections**: Track connection pool usage and performance
3. **Query Analysis**: Use database query analysis tools
4. **Health Checks**: Implement database health checks

## Key Benefits

* **Multi-Database Support**: SQL Server, MySQL, PostgreSQL, Oracle
* **Advanced Multi-Tenant Architecture**: Independent databases per tenant with complete data isolation
* **Cloud-Native Scaling**: Independent database scaling per tenant usage and cost optimization
* **Enhanced Security**: Physical data separation ensures maximum security and confidentiality
* **Read/Write Separation**: Optimized for different operation types
* **Connection Management**: Efficient connection pooling and management
* **Migration Support**: Full EF Core migration support
* **Audit Trail**: Optional audit trail for data changes
* **Query Logging**: Built-in query logging and monitoring
* **Performance Optimized**: Tuned for different database systems
* **Flexible Configuration**: Easy to switch between database providers
* **Enterprise Features**: Oracle RAC, partitioning, advanced analytics
* **Compliance Ready**: Meets strict regulatory requirements (GDPR, HIPAA, SOX)
* **Production Ready**: Battle-tested for enterprise applications

***

**This Entity Framework Core configuration system provides a robust, scalable, and maintainable data access layer that adapts to different database systems and tenant models!** 🚀


# Idempotency for Subscribers

## Overview

**Idempotency** ensures that event subscribers process each message **exactly once**, even when the message bus redelivers the same message multiple times. This is critical for maintaining data integrity in distributed systems.

### Why Do Messages Get Redelivered?

Message buses like NServiceBus, RabbitMQ, and Azure Service Bus may redeliver messages due to:

| Scenario                   | Description                                             |
| -------------------------- | ------------------------------------------------------- |
| **Transient Failures**     | Network timeouts, database connection issues            |
| **Process Crashes**        | Application crashes before acknowledging the message    |
| **Retry Policies**         | Automatic retries on failed message processing          |
| **Infrastructure Issues**  | Message broker restarts, failovers                      |
| **At-Least-Once Delivery** | Most message buses guarantee delivery but may duplicate |

### What Problems Can Duplicate Processing Cause?

Without idempotency, duplicate message processing can lead to:

* 📧 **Multiple emails sent** to the same user
* 💳 **Duplicate financial transactions**
* 📦 **Duplicate orders or shipments**
* 🔢 **Incorrect counters or statistics**
* 💾 **Duplicate database records**
* 🔗 **Inconsistent data across systems**

***

## Quick Start

FlexBase provides **automatic idempotency** for subscribers using the Decorator Pattern. No changes are required to your existing subscriber code.

### Step 1: Add Configuration to appsettings.json

```json
{
  "FlexIdempotency": {
    "Enabled": true,
    "StoreType": "Cache",
    "DefaultTimeToLiveDays": 7,
    "KeyPrefix": "flex:idempotency"
  },
  "FlexCache": {
    "MaxPayloadBytes": 1048576,
    "DefaultExpirationMinutes": 60
  }
}
```

### Step 2: Register Idempotency Services

In your `CommonHostConfig.cs` or startup configuration:

```csharp
services.AddFlexIdempotency(configuration);
```

That's it! All your subscribers now have automatic idempotency protection.

***

## Configuration Options

### FlexIdempotency Section

| Setting                 | Default              | Description                                        |
| ----------------------- | -------------------- | -------------------------------------------------- |
| `Enabled`               | `true`               | Enable/disable idempotency checking globally       |
| `StoreType`             | `"Cache"`            | Storage backend: `"Cache"` or `"Database"`         |
| `DefaultTimeToLiveDays` | `7`                  | How long to remember processed events              |
| `KeyPrefix`             | `"flex:idempotency"` | Prefix for cache keys (Cache store only)           |
| `EnableAutoCleanup`     | `false`              | Auto-cleanup expired records (Database store only) |
| `CleanupBatchSize`      | `1000`               | Records per cleanup batch (Database store only)    |

### FlexCache Section (for Cache Store)

| Setting                    | Default         | Description                    |
| -------------------------- | --------------- | ------------------------------ |
| `MaxPayloadBytes`          | `1048576` (1MB) | Maximum cache entry size       |
| `DefaultExpirationMinutes` | `60`            | Default cache entry expiration |

***

## Store Types

FlexBase offers two storage backends for tracking processed events:

### Option 1: Cache Store (Default)

Uses **FlexHybridCache** with L1 (in-memory) + L2 (distributed) architecture.

```json
{
  "FlexIdempotency": {
    "StoreType": "Cache"
  }
}
```

**Advantages:**

* ✅ High performance (in-memory L1 cache)
* ✅ Scales across multiple instances (with distributed L2)
* ✅ Simple setup for development

**Cache Backend Options:**

| Backend        | Use Case                       | Setup Complexity      |
| -------------- | ------------------------------ | --------------------- |
| In-Memory Only | Development, single instance   | None                  |
| Redis          | Production, high performance   | Requires Redis server |
| SQL Server     | Production, no Redis available | Requires cache table  |

### Option 2: Database Store (EF Core)

Uses your application's **Entity Framework Core DbContext** to store processed events.

```json
{
  "FlexIdempotency": {
    "StoreType": "Database"
  }
}
```

**Advantages:**

* ✅ Data persists across application restarts
* ✅ Queryable (you can analyze processed events)
* ✅ Uses existing database infrastructure
* ✅ No additional cache infrastructure needed

**Disadvantages:**

* ⚠️ Slower than cache-based storage
* ⚠️ Increases database load
* ⚠️ Requires EF Core migration

***

## Cache Store Configuration

### Development: In-Memory Only

For local development, no additional configuration is needed. FlexHybridCache uses in-memory storage by default.

```csharp
// Just register idempotency - cache is in-memory by default
services.AddFlexIdempotency(configuration);
```

> ⚠️ **Warning:** In-memory cache is lost on application restart and not shared across instances. Use distributed cache for production.

***

### Production: Redis Backend

Redis provides the best performance for distributed caching.

#### Step 1: Install NuGet Package

```bash
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
```

#### Step 2: Configure Redis

```csharp
// In your ConfigureServices or Program.cs
services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = configuration.GetConnectionString("Redis");
    options.InstanceName = "YourApp:";
});

// Then add idempotency (uses Redis as L2 cache automatically)
services.AddFlexIdempotency(configuration);
```

#### Step 3: Add Connection String

```json
{
  "ConnectionStrings": {
    "Redis": "localhost:6379,abortConnect=false"
  }
}
```

***

### Production: SQL Server Distributed Cache

If you don't have Redis, you can use SQL Server as a distributed cache backend.

#### Step 1: Install NuGet Package

```bash
dotnet add package Microsoft.Extensions.Caching.SqlServer
```

#### Step 2: Create the Cache Table

**Option A: Using dotnet tool**

```bash
dotnet tool install --global dotnet-sql-cache
dotnet sql-cache create "YourConnectionString" dbo DistributedCache
```

**Option B: Using SQL Script**

```sql
CREATE TABLE [dbo].[DistributedCache] (
    [Id] NVARCHAR(449) NOT NULL PRIMARY KEY,
    [Value] VARBINARY(MAX) NOT NULL,
    [ExpiresAtTime] DATETIMEOFFSET NOT NULL,
    [SlidingExpirationInSeconds] BIGINT NULL,
    [AbsoluteExpiration] DATETIMEOFFSET NULL
);

CREATE NONCLUSTERED INDEX [IX_DistributedCache_ExpiresAtTime]
    ON [dbo].[DistributedCache]([ExpiresAtTime]);
```

#### Step 3: Configure SQL Server Distributed Cache

```csharp
// In your ConfigureServices or Program.cs
services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = configuration.GetConnectionString("CacheDb");
    options.SchemaName = "dbo";
    options.TableName = "DistributedCache";
    options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30);
});

// Then add idempotency (uses SQL Server as L2 cache automatically)
services.AddFlexIdempotency(configuration);
```

#### Step 4: Add Connection String

```json
{
  "ConnectionStrings": {
    "CacheDb": "Server=.;Database=YourDb;Trusted_Connection=True;TrustServerCertificate=True"
  }
}
```

***

## Database Store Configuration (EF Core)

For full database persistence with a typed entity, use the EF Core store.

### Step 1: Configure Store Type

```json
{
  "FlexIdempotency": {
    "StoreType": "Database",
    "DefaultTimeToLiveDays": 7,
    "EnableAutoCleanup": false,
    "CleanupBatchSize": 1000
  }
}
```

### Step 2: Choose Your DbContext Approach

FlexBase provides two options for the Database store:

| Approach              | Description                                               | Best For                            |
| --------------------- | --------------------------------------------------------- | ----------------------------------- |
| **Dedicated Context** | Uses `FlexProcessedEventDbContext` (provided by FlexBase) | Isolation, separate migrations      |
| **Shared Context**    | Add entity to your `ApplicationEFDbContext`               | Simplicity, single migration stream |

***

#### Option A: Dedicated Context (Recommended for Isolation)

Use the built-in `FlexProcessedEventDbContext`. No changes to your application DbContext required.

**Register in IdempotencyConfig.cs:**

```csharp
using Sumeru.Flex.Data.EntityFramework.Idempotency;

// For dedicated context with same connection string as app database
services.AddFlexProcessedEventStoreEfCore(
    options => options.UseSqlServer(configuration.GetConnectionString("AppDbConnection")),
    storeOptions => 
    {
        storeOptions.DefaultTimeToLive = TimeSpan.FromDays(7);
        storeOptions.EnableAutoCleanup = false;
    });
```

**Create migrations:**

```bash
# From your Migrations project
cd YourApp.Migrations.SqlServer

dotnet ef migrations add AddFlexProcessedEventsTable \
    --context FlexProcessedEventDbContext \
    --output-dir Idempotency \
    --startup-project ../YourApp.EndPoint.WebAPI

dotnet ef database update \
    --context FlexProcessedEventDbContext \
    --startup-project ../YourApp.EndPoint.WebAPI
```

> 💡 **Tip:** Using `--output-dir Idempotency` keeps idempotency migrations separate from your main application migrations.

***

#### Option B: Shared Context (Simpler Setup)

Add the `FlexProcessedEventEntity` to your existing `ApplicationEFDbContext`. This keeps all entities and migrations together.

**Step B1: Modify your ApplicationEFDbContext:**

```csharp
using Sumeru.Flex.Data.EntityFramework.Idempotency;

public class ApplicationEFDbContext : FlexEFDbContext
{
    // Add this DbSet alongside your other entities
    public DbSet<FlexProcessedEventEntity> FlexProcessedEvents { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        
        // Add this configuration
        FlexProcessedEventDbContext.ConfigureProcessedEventEntity(modelBuilder);
        
        // ... your other entity configurations ...
    }
}
```

**Step B2: Register in IdempotencyConfig.cs:**

```csharp
using Sumeru.Flex.Data.EntityFramework.Idempotency;

// For shared context - uses your existing ApplicationEFDbContext
services.AddFlexProcessedEventStoreEfCore<ApplicationEFDbContext>(
    storeOptions => 
    {
        storeOptions.DefaultTimeToLive = TimeSpan.FromDays(7);
        storeOptions.EnableAutoCleanup = false;
    });
```

**Step B3: Create migrations:**

```bash
# From your Migrations project
cd YourApp.Migrations.SqlServer

dotnet ef migrations add AddFlexProcessedEventsTable \
    --context ApplicationEFDbContext \
    --startup-project ../YourApp.EndPoint.WebAPI

dotnet ef database update \
    --context ApplicationEFDbContext \
    --startup-project ../YourApp.EndPoint.WebAPI
```

***

### Which Approach Should I Choose?

| Consideration            | Dedicated Context     | Shared Context                        |
| ------------------------ | --------------------- | ------------------------------------- |
| **Setup complexity**     | More configuration    | Simpler                               |
| **Migration management** | Separate migrations   | Single migration stream               |
| **Transaction scope**    | Separate transactions | Same transaction as business entities |
| **Connection pooling**   | Uses separate pool    | Shares connection pool                |
| **Schema isolation**     | Fully isolated        | Mixed with app entities               |

**Recommendation:**

* Use **Shared Context** for most applications (simpler, fewer moving parts)
* Use **Dedicated Context** if you need schema isolation or want separate database

### Database Table Structure

The migration creates a `FlexProcessedEvents` table:

| Column           | Type            | Description                          |
| ---------------- | --------------- | ------------------------------------ |
| `Id`             | `bigint`        | Auto-increment primary key           |
| `EventId`        | `nvarchar(450)` | Unique event identifier              |
| `SubscriberType` | `nvarchar(450)` | Fully qualified subscriber type name |
| `CorrelationId`  | `nvarchar(450)` | Optional correlation ID for tracing  |
| `ProcessedAtUtc` | `datetime2`     | When the event was processed         |
| `ExpiresAtUtc`   | `datetime2`     | When the record can be cleaned up    |

**Indexes:**

* Composite unique index on `(EventId, SubscriberType)`
* Index on `ExpiresAtUtc` for cleanup queries

### Cleanup of Expired Records

**For Cache Store:** Expired records are automatically cleaned up by the cache infrastructure (Redis, HybridCache). No action needed.

**For Database Store:** Records have an `ExpiresAtUtc` column and **expired records are automatically ignored** during idempotency checks. However, you need to periodically clean up expired records to prevent table growth.

FlexBase provides a `CleanupExpiredAsync()` method you can call from your own scheduled job:

```csharp
// Example: Hangfire recurring job
public class ProcessedEventCleanupJob
{
    private readonly EfCoreProcessedEventStore _store;

    public ProcessedEventCleanupJob(EfCoreProcessedEventStore store)
    {
        _store = store;
    }

    public async Task Execute()
    {
        int totalCleaned = 0;
        int cleaned;
        
        // Process in batches until all expired records are deleted
        do
        {
            cleaned = await _store.CleanupExpiredAsync();
            totalCleaned += cleaned;
        } while (cleaned > 0);
        
        // Log result
        Console.WriteLine($"Cleaned up {totalCleaned} expired idempotency records");
    }
}

// Register with Hangfire (or your preferred scheduler)
RecurringJob.AddOrUpdate<ProcessedEventCleanupJob>(
    "cleanup-expired-idempotency-records",
    job => job.Execute(),
    Cron.Daily);  // Run daily
```

**Alternative: Direct SQL cleanup**

If you prefer, you can also clean up using a SQL Agent job or scheduled query:

```sql
-- Delete expired records older than 7 days
DELETE FROM FlexProcessedEvents 
WHERE ExpiresAtUtc <= GETUTCDATE();
```

> **Note:** Even without cleanup, expired records don't affect correctness - they are ignored during idempotency checks. Cleanup is only needed to manage table size.

***

## Opting Out of Idempotency

Some subscribers should always run, even on retries (e.g., logging, metrics, notifications). Use the `[SkipIdempotency]` attribute:

```csharp
using Sumeru.Flex;

[SkipIdempotency]
public class AuditLogSubscriber : IAuditLogSubscriber
{
    public async Task Execute(UserLoggedInEvent @event, IFlexServiceBusContext context)
    {
        // This will run on EVERY message, including duplicates
        await LogUserActivity(@event);
    }
}
```

***

## How It Works

FlexBase automatically adds a "gatekeeper" in front of your subscribers. This gatekeeper checks if an event has already been processed before allowing it through to your code.

**The key point:** Your existing subscriber code doesn't change at all. FlexBase handles everything behind the scenes when you register your services.

### What Happens When a Message Arrives

```
    ┌─────────────────────────────────────────────────────────────┐
    │                    MESSAGE ARRIVES                          │
    │              (might be first time or a retry)               │
    └─────────────────────────────────────────────────────────────┘
                                │
                                ▼
    ┌─────────────────────────────────────────────────────────────┐
    │              IDEMPOTENCY CHECK (Automatic)                  │
    │                                                             │
    │   "Have I seen this EventId + Subscriber before?"           │
    │                                                             │
    │          YES (duplicate)  │  NO (first time)                │
    │               │           │        │                        │
    │               ▼           │        ▼                        │
    │         ┌─────────┐       │   ┌──────────────┐              │
    │         │  SKIP   │       │   │ Mark as      │              │
    │         │  (done) │       │   │ "processed"  │              │
    │         └─────────┘       │   └──────────────┘              │
    │                           │        │                        │
    └───────────────────────────│────────│────────────────────────┘
                                         │
                                         ▼
    ┌─────────────────────────────────────────────────────────────┐
    │               YOUR SUBSCRIBER RUNS                          │
    │                                                             │
    │   - Your business logic executes                            │
    │   - Database operations happen                              │
    │   - Emails get sent, etc.                                   │
    │                                                             │
    │   (This only runs ONCE per unique message)                  │
    └─────────────────────────────────────────────────────────────┘
```

### Why Your Code Doesn't Need to Change

When you call `AddFlexIdempotency()`, FlexBase automatically:

1. **Intercepts** all calls to your subscribers
2. **Checks** if the `EventId` has been seen before
3. **Blocks duplicates** from reaching your code
4. **Passes through** new messages to your subscriber

Your subscriber just receives messages and processes them - it doesn't know (or care) that there's a gatekeeper in front of it.

### Key Points

1. **No code changes required** - Your subscribers work exactly as before
2. **EventId-based deduplication** - Each event has a unique `EventId` (auto-generated)
3. **Per-subscriber tracking** - The same event can be processed by different subscribers
4. **TTL-based cleanup** - Old records are automatically expired after the configured time

***

## Troubleshooting

### Events Being Skipped Unexpectedly

1. **Check EventId generation** - Events should have unique `EventId` values
2. **Verify TTL settings** - If TTL is too long, old events may still be "remembered"
3. **Check cache connectivity** - Ensure Redis/SQL Server is reachable

### Duplicate Processing Still Occurring

1. **Verify registration** - Ensure `AddFlexIdempotency()` is called
2. **Check store type** - Verify the configured store is working
3. **Check for `[SkipIdempotency]`** - Subscriber may be opted out

### Debug Logging

Enable debug logging to see idempotency decisions:

```json
{
  "Serilog": {
    "MinimumLevel": {
      "Override": {
        "Sumeru.Flex": "Debug"
      }
    }
  }
}
```

Log messages:

* `"Event {EventId} already processed by {Subscriber}; skipping"` - Duplicate blocked
* `"Successfully processed event {EventId} by {Subscriber}"` - First-time processing

***

## Best Practices

### 1. Choose the Right Store Type

| Scenario                        | Recommended Store  |
| ------------------------------- | ------------------ |
| Development                     | Cache (in-memory)  |
| Single instance, simple app     | Cache (in-memory)  |
| Multi-instance, high throughput | Cache + Redis      |
| Multi-instance, no Redis        | Cache + SQL Server |
| Need queryable history          | Database (EF Core) |
| Regulatory/audit requirements   | Database (EF Core) |

### 2. Set Appropriate TTL

* **Too short:** Events may be reprocessed if redelivered after TTL expires
* **Too long:** Storage grows unnecessarily, cleanup slower

Recommended: **7 days** (default) for most scenarios

### 3. Monitor Storage Growth

For Database store, periodically review the `FlexProcessedEvents` table size and enable `EnableAutoCleanup` if needed.

### 4. Use SkipIdempotency Sparingly

Only use `[SkipIdempotency]` for:

* Logging/auditing subscribers
* Metrics/telemetry collectors
* Notification dispatchers (where duplicates are acceptable)

***

## Complete Example

### appsettings.json

```json
{
  "ConnectionStrings": {
    "Redis": "localhost:6379,abortConnect=false"
  },
  "FlexIdempotency": {
    "Enabled": true,
    "StoreType": "Cache",
    "DefaultTimeToLiveDays": 7,
    "KeyPrefix": "flex:idempotency"
  },
  "FlexCache": {
    "MaxPayloadBytes": 1048576,
    "DefaultExpirationMinutes": 60
  }
}
```

### IdempotencyConfig.cs

```csharp
using Microsoft.Extensions.Caching.Hybrid;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Sumeru.Flex;

public static class IdempotencyConfig
{
    public static IServiceCollection AddFlexIdempotency(
        this IServiceCollection services, 
        IConfiguration configuration)
    {
        var section = configuration.GetSection("FlexIdempotency");
        var enabled = section.GetValue<bool>("Enabled", true);

        if (!enabled)
            return services;

        // Configure cache
        services.AddFlexHybridCache(options =>
        {
            var cacheSection = configuration.GetSection("FlexCache");
            options.MaximumPayloadBytes = cacheSection.GetValue<int>("MaxPayloadBytes", 1024 * 1024);
            options.DefaultEntryOptions = new HybridCacheEntryOptions
            {
                Expiration = TimeSpan.FromMinutes(
                    cacheSection.GetValue<int>("DefaultExpirationMinutes", 60))
            };
        });

        // Configure idempotency store
        var options = new FlexProcessedEventStoreOptions
        {
            DefaultTimeToLive = TimeSpan.FromDays(
                section.GetValue<int>("DefaultTimeToLiveDays", 7)),
            KeyPrefix = section.GetValue<string>("KeyPrefix", "flex:idempotency")!
        };

        services.AddSingleton(options);
        services.AddSingleton<IFlexProcessedEventStore, FlexCacheProcessedEventStore>();

        return services;
    }
}
```

### CommonHostConfig.cs

```csharp
.ConfigureServices((hostingContext, services) =>
{
    // ... other services ...

    // Add Redis distributed cache (for production)
    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = hostingContext.Configuration.GetConnectionString("Redis");
        options.InstanceName = "MyApp:";
    });

    // Add idempotency
    services.AddFlexIdempotency(hostingContext.Configuration);
});
```

***

## Summary

| Feature                   | Description                                   |
| ------------------------- | --------------------------------------------- |
| **Purpose**               | Prevent duplicate event processing            |
| **Default Store**         | Cache (FlexHybridCache)                       |
| **Alternative Store**     | Database (EF Core)                            |
| **Cache Backends**        | In-memory, Redis, SQL Server                  |
| **Opt-out**               | `[SkipIdempotency]` attribute                 |
| **Configuration**         | `FlexIdempotency` section in appsettings.json |
| **Code Changes Required** | None (Decorator Pattern)                      |


# Features

## Overview

Features represent the **actions** that users can perform in your application. Each feature is a complete, self-contained unit that handles a specific business operation from start to finish.

## What are Features?

Features are the building blocks of your application's functionality:

* **User Actions** - Every button click, form submission, or user interaction
* **Business Operations** - Complete workflows that deliver business value
* **API Endpoints** - RESTful operations that external systems can call
* **Data Operations** - Create, Read, Update, Delete (CRUD) operations

## Common Feature Types

* **Insert Features** - Add new data (e.g., Create Order, Add Product)
* **Query Features** - Retrieve data (e.g., Get Orders, Search Products)
* **Update Features** - Modify existing data (e.g., Update Order, Edit Product)
* **Delete Features** - Remove data (e.g., Cancel Order, Remove Product)
* **Process Features** - Complex business workflows (e.g., Process Payment, Send Notification)

## Why Features Matter

* **User-Focused** - Directly map to what users want to accomplish
* **Testable** - Each feature can be tested independently
* **Maintainable** - Clear boundaries make code easier to understand and modify
* **Scalable** - Add new features without affecting existing ones

***

**Ready to learn more?** Explore the feature-specific documentation to see how to implement, test, and deploy features in your FlexBase applications! 🚀


# Understanding Feature

## Overview

Features in FlexBase are organized around **CRUD operations** (Create, Read, Update, Delete) with two distinct patterns: **Command-based operations** for data modification and **Query-based operations** for data retrieval.

## Feature Categories

### 1. Command-Based Features (Data Modification)

These features use **Controllers** and **Handlers** to modify data:

#### **Insert Features** - Create New Data

* **Purpose**: Add new entities to the system
* **Flow**: `Controller → Service → Command Handler → Domain Model → Database`
* **Example**: `AddOrder`, `CreateProduct`, `RegisterUser`
* **HTTP Method**: `POST`

#### **Update Features** - Modify Existing Data

* **Purpose**: Update existing entities
* **Flow**: `Controller → Service → Command Handler → Domain Model → Database`
* **Example**: `UpdateOrder`, `EditProduct`, `ModifyUser`
* **HTTP Method**: `PUT`

#### **Delete Features** - Remove Data

* **Purpose**: Permanently remove entities
* **Flow**: `Controller → Service → Command Handler → Domain Model → Database`
* **Example**: `DeleteOrder`, `RemoveProduct`, `DeactivateUser`
* **HTTP Method**: `DELETE`

#### **Soft Delete Features** - Mark as Deleted

* **Purpose**: Mark entities as deleted without removing them
* **Flow**: `Controller → Service → Command Handler → Domain Model → Database`
* **Example**: `SoftDeleteOrder`, `ArchiveProduct`, `DeactivateUser`
* **HTTP Method**: `PUT`

### 2. Query-Based Features (Data Retrieval)

These features use **Controllers** and **Query projects** to retrieve data:

#### **GetById Features** - Retrieve Single Entity by ID

* **Purpose**: Get one specific entity by its unique identifier
* **Flow**: `Controller → Service → Query Handler → Database → Response`
* **Example**: `GetOrderById`, `GetProductById`, `GetUserById`
* **HTTP Method**: `GET`

#### **GetSingle Features** - Retrieve Single Entity by Criteria

* **Purpose**: Get one entity based on specific criteria
* **Flow**: `Controller → Service → Query Handler → Database → Response`
* **Example**: `GetOrderByNumber`, `GetProductBySku`, `GetUserByEmail`
* **HTTP Method**: `GET`

#### **GetList Features** - Retrieve Multiple Entities

* **Purpose**: Get a collection of entities
* **Flow**: `Controller → Service → Query Handler → Database → Response`
* **Example**: `GetOrders`, `GetProducts`, `GetUsers`
* **HTTP Method**: `GET`

#### **GetPagedList Features** - Retrieve Paginated Results

* **Purpose**: Get entities with pagination support
* **Flow**: `Controller → Service → Query Handler → Database → Response`
* **Example**: `GetOrdersPaged`, `GetProductsPaged`, `GetUsersPaged`
* **HTTP Method**: `GET`

## Control Flow Comparison

### Command Flow (Insert/Update/Delete/SoftDelete)

```
API Request → Controller → Service → Command Handler → Domain Model → Database → Event Publishing → Response
```

**Key Characteristics:**

* **Modifies data** in the system
* **Uses Command Handlers** for business logic
* **Publishes events** after successful operations
* **Returns success/failure** status

#### **Eventual vs Non-Eventual Provision**

**Non-Eventual (Synchronous) Flow:**

```
API Request → Controller → Service → Command Handler → Domain Model → Database → Response
```

* **Immediate Response**: User gets response after data is saved
* **Synchronous Processing**: All operations complete before response
* **Use Case**: Critical operations requiring immediate confirmation
* **Example**: Payment processing, user registration

**Eventual (Asynchronous) Flow:**

```
API Request → Controller → Service → Command Handler → Domain Model → Database → Event Publishing → Response
```

* **Immediate Acknowledgment**: User gets acknowledgment, processing continues in background
* **Asynchronous Processing**: Events trigger additional processing
* **Use Case**: Operations that can be processed later
* **Example**: Email notifications, report generation, data synchronization

### Query Flow (GetById/GetSingle/GetList/GetPagedList)

```
API Request → Controller → Service → Query Handler → Database → Response
```

**Key Characteristics:**

* **Reads data** from the system
* **Uses Query Handlers** for data retrieval
* **No events published** (read-only operations)
* **Returns data** or empty results

## Implementation Pattern

### Command Features

* **Controller**: `YourEntityController_Add.cs`, `YourEntityController_Update.cs`
* **Handler**: `AddYourEntityHandler.cs`, `UpdateYourEntityHandler.cs`
* **Message**: `AddYourEntityCommand.cs`, `UpdateYourEntityCommand.cs`
* **DTO**: `AddYourEntityDto.cs`, `UpdateYourEntityDto.cs`

### Query Features

* **Controller**: `YourEntityController_GetById.cs`, `YourEntityController_GetList.cs`
* **Query**: `GetYourEntityByIdQuery.cs`, `GetYourEntityListQuery.cs`
* **DTO**: `GetYourEntityDto.cs`, `YourEntityListDto.cs`

## Benefits of This Approach

* **Clear Separation**: Commands modify data, Queries retrieve data
* **Scalability**: Can scale read and write operations independently
* **Maintainability**: Each feature has a single responsibility
* **Testability**: Easy to test each component in isolation
* **Performance**: Optimized for different operation types

***

**Next Steps**: Learn how to implement these features in your FlexBase applications by exploring the specific feature implementation guides! 🚀


# Use Case

## Overview

The **EBusiness** application is a comprehensive e-commerce solution built using FlexBase Framework, demonstrating real-world implementation of enterprise features. This application showcases how to build scalable, maintainable business applications following Domain-Driven Design (DDD) principles and Clean Architecture patterns.

## Application Architecture

### **Domain Focus**

* **E-Commerce Business**: Complete online shopping platform
* **Multi-Tenant Support**: Serve multiple customers with isolated data
* **Event-Driven Architecture**: Asynchronous processing for scalability
* **CQRS Pattern**: Separate read and write operations for performance

### **Key Business Capabilities**

* **Order Management**: Complete order lifecycle from creation to fulfillment
* **Product Catalog**: Product management with inventory tracking
* **Customer Management**: User registration, authentication, and profile management
* **Payment Processing**: Secure payment handling and transaction management
* **Inventory Management**: Stock tracking and low inventory alerts
* **Reporting & Analytics**: Business intelligence and reporting capabilities

## Feature Implementation List

### 1. **Order Management Features**

#### **Command Features (Data Modification)**

* **AddOrder** - Create new customer orders
  * **Flow**: `POST /api/Orders/AddOrder`
  * **Handler**: `AddOrderHandler.cs`
  * **Event**: `OrderCreatedEvent` (Eventual)
  * **Use Case**: Customer places order, inventory reserved, confirmation sent
* **UpdateOrder** - Modify existing orders
  * **Flow**: `PUT /api/Orders/UpdateOrder`
  * **Handler**: `UpdateOrderHandler.cs`
  * **Event**: `OrderUpdatedEvent` (Eventual)
  * **Use Case**: Update order details, change shipping address
* **CancelOrder** - Cancel pending orders
  * **Flow**: `PUT /api/Orders/CancelOrder`
  * **Handler**: `CancelOrderHandler.cs`
  * **Event**: `OrderCancelledEvent` (Eventual)
  * **Use Case**: Customer cancels order, inventory released
* **ProcessOrder** - Process order for fulfillment
  * **Flow**: `PUT /api/Orders/ProcessOrder`
  * **Handler**: `ProcessOrderHandler.cs`
  * **Event**: `OrderProcessedEvent` (Eventual)
  * **Use Case**: Warehouse processes order, shipping label generated

#### **Query Features (Data Retrieval)**

* **GetOrderById** - Retrieve specific order details
  * **Flow**: `GET /api/Orders/GetOrderById/{id}`
  * **Query**: `GetOrderByIdQuery.cs`
  * **Use Case**: Customer views order details, admin order lookup
* **GetOrders** - List all orders with filtering
  * **Flow**: `GET /api/Orders/GetOrders`
  * **Query**: `GetOrdersQuery.cs`
  * **Use Case**: Admin order management, customer order history
* **GetOrdersPaged** - Paginated order list
  * **Flow**: `GET /api/Orders/GetOrdersPaged`
  * **Query**: `GetOrdersPagedQuery.cs`
  * **Use Case**: Large order lists with pagination support
* **GetCustomerOrders** - Orders for specific customer
  * **Flow**: `GET /api/Orders/GetCustomerOrders/{customerId}`
  * **Query**: `GetCustomerOrdersQuery.cs`
  * **Use Case**: Customer order history, account management

### 2. **Product Management Features**

#### **Command Features (Data Modification)**

* **AddProduct** - Create new products
  * **Flow**: `POST /api/Products/AddProduct`
  * **Handler**: `AddProductHandler.cs`
  * **Event**: `ProductCreatedEvent` (Eventual)
  * **Use Case**: Admin adds new product to catalog
* **UpdateProduct** - Modify product information
  * **Flow**: `PUT /api/Products/UpdateProduct`
  * **Handler**: `UpdateProductHandler.cs`
  * **Event**: `ProductUpdatedEvent` (Eventual)
  * **Use Case**: Update product details, pricing, descriptions
* **UpdateInventory** - Adjust product stock levels
  * **Flow**: `PUT /api/Products/UpdateInventory`
  * **Handler**: `UpdateInventoryHandler.cs`
  * **Event**: `InventoryUpdatedEvent` (Eventual)
  * **Use Case**: Stock adjustments, receiving shipments
* **DeactivateProduct** - Soft delete products
  * **Flow**: `PUT /api/Products/DeactivateProduct`
  * **Handler**: `DeactivateProductHandler.cs`
  * **Event**: `ProductDeactivatedEvent` (Eventual)
  * **Use Case**: Discontinue products, seasonal items

#### **Query Features (Data Retrieval)**

* **GetProductById** - Retrieve specific product
  * **Flow**: `GET /api/Products/GetProductById/{id}`
  * **Query**: `GetProductByIdQuery.cs`
  * **Use Case**: Product detail pages, admin product management
* **GetProducts** - List products with filtering
  * **Flow**: `GET /api/Products/GetProducts`
  * **Query**: `GetProductsQuery.cs`
  * **Use Case**: Product catalog browsing, search results
* **GetProductsPaged** - Paginated product list
  * **Flow**: `GET /api/Products/GetProductsPaged`
  * **Query**: `GetProductsPagedQuery.cs`
  * **Use Case**: Large product catalogs with pagination
* **SearchProducts** - Product search functionality
  * **Flow**: `GET /api/Products/SearchProducts`
  * **Query**: `SearchProductsQuery.cs`
  * **Use Case**: Customer product search, admin product lookup

### 3. **Customer Management Features**

#### **Command Features (Data Modification)**

* **RegisterCustomer** - Create new customer accounts
  * **Flow**: `POST /api/Customers/RegisterCustomer`
  * **Handler**: `RegisterCustomerHandler.cs`
  * **Event**: `CustomerRegisteredEvent` (Eventual)
  * **Use Case**: New customer registration, welcome email sent
* **UpdateCustomer** - Modify customer information
  * **Flow**: `PUT /api/Customers/UpdateCustomer`
  * **Handler**: `UpdateCustomerHandler.cs`
  * **Event**: `CustomerUpdatedEvent` (Eventual)
  * **Use Case**: Profile updates, address changes
* **DeactivateCustomer** - Soft delete customer accounts
  * **Flow**: `PUT /api/Customers/DeactivateCustomer`
  * **Handler**: `DeactivateCustomerHandler.cs`
  * **Event**: `CustomerDeactivatedEvent` (Eventual)
  * **Use Case**: Account closure, compliance requirements

#### **Query Features (Data Retrieval)**

* **GetCustomerById** - Retrieve specific customer
  * **Flow**: `GET /api/Customers/GetCustomerById/{id}`
  * **Query**: `GetCustomerByIdQuery.cs`
  * **Use Case**: Customer profile pages, admin customer lookup
* **GetCustomers** - List customers with filtering
  * **Flow**: `GET /api/Customers/GetCustomers`
  * **Query**: `GetCustomersQuery.cs`
  * **Use Case**: Admin customer management, customer support
* **GetCustomersPaged** - Paginated customer list
  * **Flow**: `GET /api/Customers/GetCustomersPaged`
  * **Query**: `GetCustomersPagedQuery.cs`
  * **Use Case**: Large customer databases with pagination

### 4. **Payment Processing Features**

#### **Command Features (Data Modification)**

* **ProcessPayment** - Handle payment transactions
  * **Flow**: `POST /api/Payments/ProcessPayment`
  * **Handler**: `ProcessPaymentHandler.cs`
  * **Event**: `PaymentProcessedEvent` (Eventual)
  * **Use Case**: Credit card processing, order payment
* **RefundPayment** - Process payment refunds
  * **Flow**: `POST /api/Payments/RefundPayment`
  * **Handler**: `RefundPaymentHandler.cs`
  * **Event**: `PaymentRefundedEvent` (Eventual)
  * **Use Case**: Order cancellations, returns processing

#### **Query Features (Data Retrieval)**

* **GetPaymentById** - Retrieve payment details
  * **Flow**: `GET /api/Payments/GetPaymentById/{id}`
  * **Query**: `GetPaymentByIdQuery.cs`
  * **Use Case**: Payment verification, transaction lookup
* **GetPayments** - List payments with filtering
  * **Flow**: `GET /api/Payments/GetPayments`
  * **Query**: `GetPaymentsQuery.cs`
  * **Use Case**: Financial reporting, transaction history

### 5. **Inventory Management Features**

#### **Command Features (Data Modification)**

* **AdjustInventory** - Modify stock levels
  * **Flow**: `PUT /api/Inventory/AdjustInventory`
  * **Handler**: `AdjustInventoryHandler.cs`
  * **Event**: `InventoryAdjustedEvent` (Eventual)
  * **Use Case**: Stock adjustments, receiving shipments
* **ReserveInventory** - Reserve stock for orders
  * **Flow**: `PUT /api/Inventory/ReserveInventory`
  * **Handler**: `ReserveInventoryHandler.cs`
  * **Event**: `InventoryReservedEvent` (Eventual)
  * **Use Case**: Order processing, stock allocation

#### **Query Features (Data Retrieval)**

* **GetInventoryLevels** - Check stock levels
  * **Flow**: `GET /api/Inventory/GetInventoryLevels`
  * **Query**: `GetInventoryLevelsQuery.cs`
  * **Use Case**: Stock monitoring, low inventory alerts
* **GetLowStockItems** - Identify items needing restocking
  * **Flow**: `GET /api/Inventory/GetLowStockItems`
  * **Query**: `GetLowStockItemsQuery.cs`
  * **Use Case**: Purchasing decisions, inventory alerts

## Event-Driven Processing

### **Event Subscribers**

* **OrderCreatedSubscriber** - Handles order creation events
  * **Actions**: Send confirmation email, reserve inventory, update analytics
* **PaymentProcessedSubscriber** - Handles payment events
  * **Actions**: Update order status, send receipt, trigger fulfillment
* **InventoryLowSubscriber** - Handles low inventory events
  * **Actions**: Send alerts to purchasing, update product status
* **CustomerRegisteredSubscriber** - Handles customer registration
  * **Actions**: Send welcome email, create customer profile, update marketing

## Technology Implementation

### **Framework Components**

* **FlexBase Framework**: Core enterprise framework
* **Entity Framework Core**: Data access and ORM
* **NServiceBus**: Message bus and event handling
* **ASP.NET Core**: Web API and controllers
* **AutoMapper**: Object mapping and DTOs

### **Database Support**

* **SQL Server**: Primary database
* **MySQL**: Alternative database option
* **PostgreSQL**: Cross-platform database support
* **Multi-Tenant**: Isolated data per customer

### **Message Bus Options**

* **RabbitMQ**: High-performance messaging
* **Azure Service Bus**: Cloud-native messaging
* **SQL Server Transport**: Database-based messaging
* **Learning Transport**: Development and testing

## Business Value

### **Scalability**

* **Horizontal Scaling**: Add more instances as needed
* **Database Scaling**: Separate read/write databases
* **Message Bus Scaling**: Handle high message volumes

### **Maintainability**

* **Clear Separation**: Commands vs Queries
* **Domain Focus**: Business logic in domain layer
* **Testability**: Each component can be tested independently

### **Performance**

* **CQRS**: Optimized read and write operations
* **Event Sourcing**: Track all changes for audit
* **Caching**: Fast data retrieval for frequently accessed data

***

**This EBusiness application demonstrates how FlexBase Framework enables rapid development of enterprise-grade applications with clean architecture, scalable design, and maintainable code!** 🚀


# CRUD


# Insert Example

## Overview

This document demonstrates the complete **Insert flow** using the **AddOrder** feature from the EBusiness application. The flow starts with a POST request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
POST Request → Controller → Service → PreBus Plugins → Command Handler → Domain Model → Database → Event Publishing → Subscribers
```

### **Detailed Flow Breakdown**

```
1. POST Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── AddOrderSequence (Plugin Registration)
   ├── AddOrderDataPacket (Validation Context)
   └── ValidateCustomer Plugin (Business Rules)
   ↓
5. Command Handler (Data Processing)
   ↓
6. Domain Model (Business Logic)
   ↓
7. Database (Data Persistence)
   ↓
8. Event Publishing (Asynchronous Processing)
   ↓
9. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `OrdersController_AddOrder.cs`

```csharp
[HttpPost]
[Route("AddOrder")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 201)]
public async Task<IActionResult> AddOrder([FromBody]AddOrderDto dto)
{
    return await RunService(201, dto, _processOrdersService.AddOrder);
}
```

**What Happens:**

* **HTTP Method**: `POST /api/Orders/AddOrder`
* **Input**: `AddOrderDto` from request body
* **Action**: Calls the service layer to process the order
* **Response**: HTTP 201 Created with order ID

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessOrdersService_AddOrder.cs`

```csharp
public async Task<CommandResult> AddOrder(AddOrderDto dto)
{
    var packet = await ProcessBusinessRuleSequence<AddOrderDataPacket, AddOrderSequence, AddOrderDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        AddOrderCommand cmd = new AddOrderCommand
        {
             Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        AddOrderResultModel outputResult = new AddOrderResultModel();
        outputResult.Id = dto.GetGeneratedId();
        cmdResult.result = outputResult;

        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique order ID
* **Command Creation**: Creates `AddOrderCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success with generated order ID

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `AddOrderSequence.cs`

```csharp
public class AddOrderSequence : FlexiBusinessRuleSequenceBase<AddOrderDataPacket>
{
    public AddOrderSequence()
    {
        this.Add<ValidateCustomer>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `AddOrderDataPacket.cs`

```csharp
public partial class AddOrderDataPacket : FlexiFlowDataPacketWithDtoBridge<AddOrderDto, FlexAppContextBridge>
{
    protected readonly ILogger<AddOrderDataPacket> _logger;

    public AddOrderDataPacket(ILogger<AddOrderDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `ValidateCustomer.cs`

```csharp
public partial class ValidateCustomer : FlexiBusinessRuleBase, IFlexiBusinessRule<AddOrderDataPacket>
{
    public override string Id { get; set; } = "3a1cd0401f931dd4a01587e229b720dc";
    public override string FriendlyName { get; set; } = "ValidateCustomer";

    protected readonly ILogger<ValidateCustomer> _logger;
    protected readonly RepoFactory _repoFactory;

    public ValidateCustomer(ILogger<ValidateCustomer> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(AddOrderDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 2.4. **PreBus Plugin Benefits**

* **Modular Validation**: Each plugin handles one validation concern
* **Reusable Rules**: Plugins can be reused across different features
* **Testable**: Each plugin can be unit tested independently
* **Configurable**: Plugins can be enabled/disabled per feature
* **Extensible**: Easy to add new validation rules
* **Ordered Execution**: Plugins execute in defined sequence

### 3. **Command Handler** - Data Processing

**File**: `AddOrderHandler.cs`

```csharp
public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    _flexAppContext = cmd.Dto.GetAppContext();
    _repoFactory.Init(cmd.Dto);

    _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
    _repoFactory.GetRepo().InsertOrUpdate(_model);
    int records = await _repoFactory.GetRepo().SaveAsync();
    
    if (records > 0)
    {
        _logger.LogDebug("{Entity} with {EntityId} inserted into Database: ", typeof(Order).Name, _model.Id);
    }
    else
    {
        _logger.LogWarning("No records inserted for {Entity} with {EntityId}", typeof(Order).Name, _model.Id);
    }
    
    await this.Fire(EventCondition, serviceBusContext);
}
```

**What Happens:**

* **Context Setup**: Initializes application context and repository
* **Domain Logic**: Calls domain model to process business rules
* **Database Save**: Inserts/updates the order in database
* **Logging**: Logs success/failure of database operation
* **Event Publishing**: Fires events for subscribers

### 4. **Domain Model** - Business Logic

**File**: `Order/AddOrder.cs`

```csharp
public virtual Order AddOrder(AddOrderCommand cmd)
{
    Guard.AgainstNull("Order command cannot be empty", cmd);

    this.Convert(cmd.Dto);
    this.CreatedBy = cmd.Dto.GetAppContext()?.UserId;
    this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;

    this.SetAdded(cmd.Dto.GetGeneratedId());

    //Set your appropriate SetAdded for the inner object here
    this.OrderState = new OrderIsCreated().SetTFlexId(this.Id).SetStateChangedBy("");
    this.TotalAmount = this.OrderItems.Select(s => s.SellingPrice).Sum();
    this.TotalQty = this.OrderItems.Select(s => s.Qty).Sum();

    this.OrderItems.SetAddedOrModified();

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **Data Mapping**: Converts DTO to domain model
* **Audit Fields**: Sets created/modified by user
* **ID Assignment**: Sets the generated ID
* **Business Rules**: Calculates totals, sets order state
* **Child Objects**: Processes order items

### 5. **NServiceBus Handler** - Message Processing

**File**: `AddOrderNsbHandler.cs`

```csharp
public class AddOrderNsbHandler : NsbCommandHandler<AddOrderCommand>
{
    readonly ILogger<AddOrderNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IAddOrderHandler _handler;

    public AddOrderNsbHandler(ILogger<AddOrderNsbHandler> logger, IFlexHost flexHost, IAddOrderHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(AddOrderCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(AddOrderNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `AddOrderCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `OrderAddedEvent`

```csharp
public class OrderAddedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with order data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `NotifyAccountsOnOrderAdded.cs`

```csharp
public partial class NotifyAccountsOnOrderAdded : INotifyAccountsOnOrderAdded
{
    protected readonly ILogger<NotifyAccountsOnOrderAdded> _logger;
    protected string EventCondition = "";

    public NotifyAccountsOnOrderAdded(ILogger<NotifyAccountsOnOrderAdded> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(OrderAddedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Send confirmation email
        // - Update inventory
        // - Notify accounting system
        // - Update analytics

        await this.Fire<NotifyAccountsOnOrderAdded>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `OrderAddedEvent` from message bus
* **Side Effects**: Executes business logic (emails, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `AddOrderDto`

```csharp
public partial class AddOrderDto : DtoBridge 
{
    [StringLength(100)]
    public string CustomerId { get; set; }

    public ICollection<AddOrderDto_OrderItem> OrderItems { get; set; }
}
```

### **Command**: `AddOrderCommand`

```csharp
public class AddOrderCommand : FlexCommandBridge<AddOrderDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **POST Request** → Controller receives request
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Data processing and database save
5. **Domain Logic** → Business rules and calculations
6. **Response** → HTTP 201 with order ID

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → OrderAddedEvent published to message bus
2. **Subscriber Processing** → NotifyAccountsOnOrderAdded executes
3. **Side Effects** → Emails, notifications, inventory updates
4. **Additional Events** → Can trigger more business processes

## Key Benefits

* **Separation of Concerns**: Each layer has a single responsibility
* **Testability**: Each component can be tested independently
* **Scalability**: Asynchronous processing handles high loads
* **Maintainability**: Clear, readable code structure
* **Event-Driven**: Loose coupling between components

***

**This AddOrder example demonstrates how FlexBase enables clean, maintainable, and scalable insert operations with proper separation of concerns and event-driven architecture!** 🚀


# Update Example

## Overview

This document demonstrates the complete **Update flow** using the **UpdateOrder** feature from the EBusiness application. The flow starts with a PUT request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
PUT Request → Controller → Service → PreBus Plugins → Command Handler → Domain Model → Database → Event Publishing → Subscribers
```

### **Detailed Flow Breakdown**

```
1. PUT Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── UpdateOrderSequence (Plugin Registration)
   ├── UpdateOrderDataPacket (Validation Context)
   └── IsValidOrder Plugin (Business Rules)
   ↓
5. Command Handler (Data Processing)
   ↓
6. Domain Model (Business Logic)
   ↓
7. Database (Data Persistence)
   ↓
8. Event Publishing (Asynchronous Processing)
   ↓
9. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `OrdersController_UpdateOrder.cs`

```csharp
[HttpPut]
[Route("UpdateOrder")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 200)]
public async Task<IActionResult> UpdateOrder([FromBody]UpdateOrderDto dto)
{
    return await RunService(200, dto, _processOrdersService.UpdateOrder);
}
```

**What Happens:**

* **HTTP Method**: `PUT /api/Orders/UpdateOrder`
* **Input**: `UpdateOrderDto` from request body
* **Action**: Calls the service layer to process the order update
* **Response**: HTTP 200 OK with success status

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessOrdersService_UpdateOrder.cs`

```csharp
public async Task<CommandResult> UpdateOrder(UpdateOrderDto dto)
{
    var packet = await ProcessBusinessRuleSequence<UpdateOrderDataPacket, UpdateOrderSequence, UpdateOrderDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        UpdateOrderCommand cmd = new UpdateOrderCommand
        {
            Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        UpdateOrderResultModel outputResult = new UpdateOrderResultModel();
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `UpdateOrderCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success status

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `UpdateOrderSequence.cs`

```csharp
public class UpdateOrderSequence : FlexiBusinessRuleSequenceBase<UpdateOrderDataPacket>
{
    public UpdateOrderSequence()
    {
        this.Add<IsValidOrder>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `UpdateOrderDataPacket.cs`

```csharp
public partial class UpdateOrderDataPacket : FlexiFlowDataPacketWithDtoBridge<UpdateOrderDto, FlexAppContextBridge>
{
    protected readonly ILogger<UpdateOrderDataPacket> _logger;

    public UpdateOrderDataPacket(ILogger<UpdateOrderDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `IsValidOrder.cs`

```csharp
public partial class IsValidOrder : FlexiBusinessRuleBase, IFlexiBusinessRule<UpdateOrderDataPacket>
{
    public override string Id { get; set; } = "3a1cd500a49d178e88f75ed6bccaed88";
    public override string FriendlyName { get; set; } = "IsValidOrder";

    protected readonly ILogger<IsValidOrder> _logger;
    protected readonly RepoFactory _repoFactory;

    public IsValidOrder(ILogger<IsValidOrder> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(UpdateOrderDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 3. **Command Handler** - Data Processing

**File**: `UpdateOrderHandler.cs`

```csharp
public virtual async Task Execute(UpdateOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    _flexAppContext = cmd.Dto.GetAppContext();
    _repoFactory.Init(cmd.Dto);

    _model = _repoFactory.GetRepo().FindAll<Order>().Where(m=>m.Id == cmd.Dto.Id).FirstOrDefault();
    
    if (_model != null)
    {
        _model.UpdateOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);

        int records = await _repoFactory.GetRepo().SaveAsync();
        if (records > 0)
        {
            _logger.LogDebug("{} with {} updated into Database: ", typeof(Order).Name, _model.Id);
        }
        else
        {
            _logger.LogWarning("No records updated for {} with {}", typeof(Order).Name, _model.Id);
        }

        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Context Setup**: Initializes application context and repository
* **Entity Lookup**: Finds existing order by ID
* **Null Check**: Ensures order exists before updating
* **Domain Logic**: Calls domain model to process business rules
* **Database Save**: Updates the order in database
* **Logging**: Logs success/failure of database operation
* **Event Publishing**: Fires events for subscribers

### 4. **Domain Model** - Business Logic

**File**: `Order/UpdateOrder.cs`

```csharp
public virtual Order UpdateOrder(UpdateOrderCommand cmd)
{
    Guard.AgainstNull("Order model cannot be empty", cmd);

    this.Convert(cmd.Dto);
    this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;

    //Map any other field not handled by Automapper config

    this.SetModified();

    //Set your appropriate SetModified for the inner object here

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **Data Mapping**: Converts DTO to domain model
* **Audit Fields**: Sets last modified by user
* **State Management**: Marks entity as modified
* **Child Objects**: Processes child object updates

### 5. **NServiceBus Handler** - Message Processing

**File**: `UpdateOrderNsbHandler.cs`

```csharp
public class UpdateOrderNsbHandler : NsbCommandHandler<UpdateOrderCommand>
{
    readonly ILogger<UpdateOrderNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IUpdateOrderHandler _handler;

    public UpdateOrderNsbHandler(ILogger<UpdateOrderNsbHandler> logger, IFlexHost flexHost, IUpdateOrderHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(UpdateOrderCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(UpdateOrderNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `UpdateOrderCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `OrderUpdatedEvent`

```csharp
public class OrderUpdatedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with order data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `UpdateManagerOnUpdateOrder.cs`

```csharp
public partial class UpdateManagerOnUpdateOrder : IUpdateManagerOnUpdateOrder
{
    protected readonly ILogger<UpdateManagerOnUpdateOrder> _logger;
    protected string EventCondition = "";

    public UpdateManagerOnUpdateOrder(ILogger<UpdateManagerOnUpdateOrder> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(OrderUpdatedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Notify managers of order changes
        // - Update inventory levels
        // - Send update notifications
        // - Update analytics

        await this.Fire<UpdateManagerOnUpdateOrder>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `OrderUpdatedEvent` from message bus
* **Side Effects**: Executes business logic (notifications, inventory updates, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `UpdateOrderDto`

```csharp
public partial class UpdateOrderDto : DtoBridge 
{
    public string Id { get; set; }
    
}
```

### **Command**: `UpdateOrderCommand`

```csharp
public class UpdateOrderCommand : FlexCommandBridge<UpdateOrderDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Key Differences from Insert Flow

### **Update-Specific Characteristics**

1. **Entity Lookup**: Must find existing entity before updating
2. **Null Check**: Validates entity exists before processing
3. **State Management**: Uses `SetModified()` instead of `SetAdded()`
4. **Audit Fields**: Updates `LastModifiedBy` instead of `CreatedBy`
5. **HTTP Method**: Uses `PUT` instead of `POST`
6. **Response Code**: Returns `200 OK` instead of `201 Created`

### **PreBus Validation Focus**

* **IsValidOrder**: Validates order exists and is in updatable state
* **Business Rules**: Ensures order can be modified (not shipped, not cancelled)
* **Data Integrity**: Validates update doesn't violate business constraints

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **PUT Request** → Controller receives request
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Entity lookup and data processing
5. **Domain Logic** → Business rules and state management
6. **Response** → HTTP 200 OK with success status

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → OrderUpdatedEvent published to message bus
2. **Subscriber Processing** → UpdateManagerOnUpdateOrder executes
3. **Side Effects** → Manager notifications, inventory updates, analytics

## Key Benefits

* **Data Integrity**: Ensures entity exists before updating
* **Audit Trail**: Tracks who made changes and when
* **Business Rules**: Validates update is allowed
* **Event-Driven**: Notifies other systems of changes
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This UpdateOrder example demonstrates how FlexBase enables clean, maintainable, and scalable update operations with proper validation, audit trails, and event-driven architecture!** 🚀


# Delete Example

## Overview

This document demonstrates the complete **Delete flow** using the **DeleteProduct** feature from the EBusiness application. The flow starts with a DELETE request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
DELETE Request → Controller → Service → PreBus Plugins → Command Handler → Domain Model → Database → Event Publishing → Subscribers
```

### **Detailed Flow Breakdown**

```
1. DELETE Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── DeleteProductSequence (Plugin Registration)
   ├── DeleteProductDataPacket (Validation Context)
   └── IsValidProduct Plugin (Business Rules)
   ↓
5. Command Handler (Data Processing)
   ↓
6. Domain Model (Business Logic)
   ↓
7. Database (Data Persistence)
   ↓
8. Event Publishing (Asynchronous Processing)
   ↓
9. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ProductsController_DeleteProduct.cs`

```csharp
[HttpDelete()]
[Route("DeleteProduct/{id}")]
public async Task<IActionResult> DeleteProduct(string id)
{
    DeleteProductDto dto = new DeleteProductDto();
    dto.Id = id;
    return await RunService(200, dto, _processProductsService.DeleteProduct);
}
```

**What Happens:**

* **HTTP Method**: `DELETE /api/Products/DeleteProduct/{id}`
* **Input**: Product ID from URL parameter
* **DTO Creation**: Creates `DeleteProductDto` with the ID
* **Action**: Calls the service layer to process the product deletion
* **Response**: HTTP 200 OK with success status

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessProductsService_DeleteProduct.cs`

```csharp
public async Task<CommandResult> DeleteProduct(DeleteProductDto dto)
{
    var packet = await ProcessBusinessRuleSequence<DeleteProductDataPacket, DeleteProductSequence, DeleteProductDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        DeleteProductCommand cmd = new DeleteProductCommand
        {
            Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        YourOutputResultModel outputResult = new YourOutputResultModel();
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `DeleteProductCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success status

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `DeleteProductSequence.cs`

```csharp
public class DeleteProductSequence : FlexiBusinessRuleSequenceBase<DeleteProductDataPacket>
{
    public DeleteProductSequence()
    {
        this.Add<IsValidProduct>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `DeleteProductDataPacket.cs`

```csharp
public partial class DeleteProductDataPacket : FlexiFlowDataPacketWithDtoBridge<DeleteProductDto, FlexAppContextBridge>
{
    protected readonly ILogger<DeleteProductDataPacket> _logger;

    public DeleteProductDataPacket(ILogger<DeleteProductDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `IsValidProduct.cs`

```csharp
public partial class IsValidProduct : FlexiBusinessRuleBase, IFlexiBusinessRule<DeleteProductDataPacket>
{
    public override string Id { get; set; } = "3a1cd5b1fa98b4c63378de9607706082";
    public override string FriendlyName { get; set; } = "IsValidProduct";

    protected readonly ILogger<IsValidProduct> _logger;
    protected readonly RepoFactory _repoFactory;

    public IsValidProduct(ILogger<IsValidProduct> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(DeleteProductDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 3. **Command Handler** - Data Processing

**File**: `DeleteProductHandler.cs`

```csharp
public virtual async Task Execute(DeleteProductCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    _flexAppContext = cmd.Dto.GetAppContext();
    _repoFactory.Init(cmd.Dto);

    _model = _flexHost.GetDomainModel<Product>().DeleteProduct(cmd);

    if (_model != null)
    {
        _repoFactory.GetRepo().InsertOrUpdate(_model);

        int records = await _repoFactory.GetRepo().SaveAsync();
        if (records > 0)
        {
            _logger.LogDebug("{} with {} deleted from Database: ", typeof(Product).Name, _model.Id);
        }
        else
        {
            _logger.LogWarning("No records deleted for {} with {}", typeof(Product).Name, _model.Id);
        }

        //EventCondition = CONDITION_ONSUCCESS;
    }
    else
    {
        //you may raise an event here to notify about the error
        //EventCondition = CONDITION_ONFAILED;
    }
    await this.Fire(EventCondition, serviceBusContext);
}
```

**What Happens:**

* **Context Setup**: Initializes application context and repository
* **Domain Logic**: Calls domain model to process business rules
* **Null Check**: Handles case where product doesn't exist
* **Database Save**: Updates the product in database (soft delete)
* **Logging**: Logs success/failure of database operation
* **Event Publishing**: Fires events for subscribers

### 4. **Domain Model** - Business Logic

**File**: `Product/DeleteProduct.cs`

```csharp
public virtual Product DeleteProduct(DeleteProductCommand cmd)
{
    Guard.AgainstNull("Product model cannot be empty", cmd);

    this.Id = cmd.Dto.Id;
    this.SetDeleted();

    //Set your appropriate SetDeleted for the inner object here

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **ID Assignment**: Sets the product ID from DTO
* **State Management**: Marks entity as deleted (soft delete)
* **Child Objects**: Processes child object deletions

### 5. **NServiceBus Handler** - Message Processing

**File**: `DeleteProductNsbHandler.cs`

```csharp
public class DeleteProductNsbHandler : NsbCommandHandler<DeleteProductCommand>
{
    readonly ILogger<DeleteProductNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IDeleteProductHandler _handler;

    public DeleteProductNsbHandler(ILogger<DeleteProductNsbHandler> logger, IFlexHost flexHost, IDeleteProductHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(DeleteProductCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(DeleteProductNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `DeleteProductCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ProductDeletedEvent` (if implemented)

```csharp
public class ProductDeletedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with product data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `NotifyInventoryOnProductDeleted.cs` (if implemented)

```csharp
public partial class NotifyInventoryOnProductDeleted : INotifyInventoryOnProductDeleted
{
    protected readonly ILogger<NotifyInventoryOnProductDeleted> _logger;
    protected string EventCondition = "";

    public NotifyInventoryOnProductDeleted(ILogger<NotifyInventoryOnProductDeleted> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ProductDeletedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Update inventory levels
        // - Notify suppliers
        // - Update analytics
        // - Archive related data

        await this.Fire<NotifyInventoryOnProductDeleted>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ProductDeletedEvent` from message bus
* **Side Effects**: Executes business logic (inventory updates, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `DeleteProductDto`

```csharp
public partial class DeleteProductDto : DtoBridge 
{
    public string Id { get; set; }
}
```

### **Command**: `DeleteProductCommand`

```csharp
public class DeleteProductCommand : FlexCommandBridge<DeleteProductDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Key Differences from Insert/Update Flow

### **Delete-Specific Characteristics**

1. **URL Parameter**: ID comes from URL path instead of request body
2. **DTO Creation**: Controller creates DTO with ID from URL
3. **Soft Delete**: Uses `SetDeleted()` instead of `SetAdded()` or `SetModified()`
4. **State Management**: Marks entity as deleted (soft delete pattern)
5. **HTTP Method**: Uses `DELETE` instead of `POST` or `PUT`
6. **Minimal Data**: Only requires ID for deletion

### **PreBus Validation Focus**

* **IsValidProduct**: Validates product exists and can be deleted
* **Business Rules**: Ensures product can be removed (not in use, not referenced)
* **Data Integrity**: Validates deletion doesn't violate business constraints

### **Soft Delete Pattern**

* **Database**: Entity is marked as deleted, not physically removed
* **Queries**: Soft-deleted entities are filtered out of normal queries
* **Recovery**: Deleted entities can be restored if needed
* **Audit Trail**: Maintains complete history of deletions

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **DELETE Request** → Controller receives request with ID
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Data processing and soft delete
5. **Domain Logic** → Business rules and state management
6. **Response** → HTTP 200 OK with success status

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ProductDeletedEvent published to message bus
2. **Subscriber Processing** → NotifyInventoryOnProductDeleted executes
3. **Side Effects** → Inventory updates, supplier notifications, analytics

## Key Benefits

* **Data Safety**: Soft delete preserves data for recovery
* **Business Rules**: Validates deletion is allowed
* **Audit Trail**: Tracks who deleted what and when
* **Event-Driven**: Notifies other systems of deletions
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This DeleteProduct example demonstrates how FlexBase enables clean, maintainable, and scalable delete operations with proper validation, soft delete patterns, and event-driven architecture!** 🚀


# Soft Delete Example

## Overview

This document demonstrates the complete **Soft Delete flow** using a **SoftDeleteProduct** feature. The flow is similar to an Update operation (PUT) but uses `SetSoftDelete()` instead of `SetModified()` or `SetDeleted()`. This pattern allows for reversible deletions while maintaining data integrity.

## Complete Flow Architecture

```
PUT Request → Controller → Service → PreBus Plugins → Command Handler → Domain Model → Database → Event Publishing → Subscribers
```

### **Detailed Flow Breakdown**

```
1. PUT Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── SoftDeleteProductSequence (Plugin Registration)
   ├── SoftDeleteProductDataPacket (Validation Context)
   └── IsValidForSoftDelete Plugin (Business Rules)
   ↓
5. Command Handler (Data Processing)
   ↓
6. Domain Model (Business Logic)
   ↓
7. Database (Data Persistence)
   ↓
8. Event Publishing (Asynchronous Processing)
   ↓
9. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ProductsController_SoftDeleteProduct.cs`

```csharp
[HttpPut]
[Route("SoftDeleteProduct")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 200)]
public async Task<IActionResult> SoftDeleteProduct([FromBody]SoftDeleteProductDto dto)
{
    return await RunService(200, dto, _processProductsService.SoftDeleteProduct);
}
```

**What Happens:**

* **HTTP Method**: `PUT /api/Products/SoftDeleteProduct`
* **Input**: `SoftDeleteProductDto` from request body
* **Action**: Calls the service layer to process the soft delete
* **Response**: HTTP 200 OK with success status

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessProductsService_SoftDeleteProduct.cs`

```csharp
public async Task<CommandResult> SoftDeleteProduct(SoftDeleteProductDto dto)
{
    var packet = await ProcessBusinessRuleSequence<SoftDeleteProductDataPacket, SoftDeleteProductSequence, SoftDeleteProductDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        SoftDeleteProductCommand cmd = new SoftDeleteProductCommand
        {
            Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        SoftDeleteProductResultModel outputResult = new SoftDeleteProductResultModel();
        outputResult.Id = dto.Id;
        outputResult.IsSoftDeleted = true;
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `SoftDeleteProductCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success with soft delete status

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `SoftDeleteProductSequence.cs`

```csharp
public class SoftDeleteProductSequence : FlexiBusinessRuleSequenceBase<SoftDeleteProductDataPacket>
{
    public SoftDeleteProductSequence()
    {
        this.Add<IsValidForSoftDelete>(); 
        this.Add<CheckProductDependencies>();
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `SoftDeleteProductDataPacket.cs`

```csharp
public partial class SoftDeleteProductDataPacket : FlexiFlowDataPacketWithDtoBridge<SoftDeleteProductDto, FlexAppContextBridge>
{
    protected readonly ILogger<SoftDeleteProductDataPacket> _logger;

    public SoftDeleteProductDataPacket(ILogger<SoftDeleteProductDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    public Product Product { get; set; }
    public bool HasActiveOrders { get; set; }
    public bool HasActiveInventory { get; set; }
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `IsValidForSoftDelete.cs`

```csharp
public partial class IsValidForSoftDelete : FlexiBusinessRuleBase, IFlexiBusinessRule<SoftDeleteProductDataPacket>
{
    public override string Id { get; set; } = "3a1cd5b1fa98b4c63378de9607706083";
    public override string FriendlyName { get; set; } = "IsValidForSoftDelete";

    protected readonly ILogger<IsValidForSoftDelete> _logger;
    protected readonly RepoFactory _repoFactory;

    public IsValidForSoftDelete(ILogger<IsValidForSoftDelete> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(SoftDeleteProductDataPacket packet)
    {
        _repoFactory.Init(packet.Dto);
        
        // Check if product exists
        var product = _repoFactory.GetRepo().FindAll<Product>()
            .Where(p => p.Id == packet.Dto.Id && !p.IsSoftDeleted)
            .FirstOrDefault();
            
        if (product == null)
        {
            packet.AddError("ProductNotFound", "Product not found or already soft deleted");
            return;
        }
        
        packet.Product = product;
        
        // Check if product has active orders
        var hasActiveOrders = _repoFactory.GetRepo().FindAll<OrderItem>()
            .Any(oi => oi.ProductId == packet.Dto.Id && !oi.Order.IsSoftDeleted);
            
        if (hasActiveOrders)
        {
            packet.AddError("HasActiveOrders", "Cannot soft delete product with active orders");
        }
        
        packet.HasActiveOrders = hasActiveOrders;

        await Task.CompletedTask;
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Validates product exists and can be soft deleted
* **Dependency Checking**: Ensures no active orders reference the product
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Data Sharing**: Populates packet with validation results

### 3. **Command Handler** - Data Processing

**File**: `SoftDeleteProductHandler.cs`

```csharp
public virtual async Task Execute(SoftDeleteProductCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    _flexAppContext = cmd.Dto.GetAppContext();
    _repoFactory.Init(cmd.Dto);

    _model = _repoFactory.GetRepo().FindAll<Product>().Where(m=>m.Id == cmd.Dto.Id).FirstOrDefault();
    
    if (_model != null)
    {
        _model.SoftDeleteProduct(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);

        int records = await _repoFactory.GetRepo().SaveAsync();
        if (records > 0)
        {
            _logger.LogDebug("{} with {} soft deleted in Database: ", typeof(Product).Name, _model.Id);
        }
        else
        {
            _logger.LogWarning("No records soft deleted for {} with {}", typeof(Product).Name, _model.Id);
        }

        EventCondition = CONDITION_ONSUCCESS;
    }
    else
    {
        _logger.LogWarning("Product with ID {} not found for soft delete", cmd.Dto.Id);
        EventCondition = CONDITION_ONFAILED;
    }
    
    await this.Fire(EventCondition, serviceBusContext);
}
```

**What Happens:**

* **Context Setup**: Initializes application context and repository
* **Entity Lookup**: Finds existing product by ID
* **Null Check**: Ensures product exists before soft deleting
* **Domain Logic**: Calls domain model to process business rules
* **Database Save**: Updates the product in database (soft delete)
* **Logging**: Logs success/failure of database operation
* **Event Publishing**: Fires events for subscribers

### 4. **Domain Model** - Business Logic

**File**: `Product/SoftDeleteProduct.cs`

```csharp
public virtual Product SoftDeleteProduct(SoftDeleteProductCommand cmd)
{
    Guard.AgainstNull("Product model cannot be empty", cmd);

    this.Convert(cmd.Dto);
    this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;
    this.SoftDeletedBy = cmd.Dto.GetAppContext()?.UserId;
    this.SoftDeletedAt = DateTime.UtcNow;

    //Map any other field not handled by Automapper config

    this.SetSoftDelete();

    //Set your appropriate SetSoftDelete for the inner object here
    this.OrderItems?.SetSoftDelete();

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **Data Mapping**: Converts DTO to domain model
* **Audit Fields**: Sets last modified by and soft deleted by user
* **Timestamp**: Records when the soft delete occurred
* **State Management**: Uses `SetSoftDelete()` instead of `SetModified()` or `SetDeleted()`
* **Child Objects**: Processes child object soft deletions

### 5. **NServiceBus Handler** - Message Processing

**File**: `SoftDeleteProductNsbHandler.cs`

```csharp
public class SoftDeleteProductNsbHandler : NsbCommandHandler<SoftDeleteProductCommand>
{
    readonly ILogger<SoftDeleteProductNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly ISoftDeleteProductHandler _handler;

    public SoftDeleteProductNsbHandler(ILogger<SoftDeleteProductNsbHandler> logger, IFlexHost flexHost, ISoftDeleteProductHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(SoftDeleteProductCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(SoftDeleteProductNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `SoftDeleteProductCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ProductSoftDeletedEvent`

```csharp
public class ProductSoftDeletedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with product data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `NotifyInventoryOnProductSoftDeleted.cs`

```csharp
public partial class NotifyInventoryOnProductSoftDeleted : INotifyInventoryOnProductSoftDeleted
{
    protected readonly ILogger<NotifyInventoryOnProductSoftDeleted> _logger;
    protected string EventCondition = "";

    public NotifyInventoryOnProductSoftDeleted(ILogger<NotifyInventoryOnProductSoftDeleted> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ProductSoftDeletedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Update inventory status
        // - Notify suppliers about product unavailability
        // - Update analytics and reporting
        // - Archive related data
        // - Send notifications to stakeholders

        await this.Fire<NotifyInventoryOnProductSoftDeleted>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ProductSoftDeletedEvent` from message bus
* **Side Effects**: Executes business logic (inventory updates, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `SoftDeleteProductDto`

```csharp
public partial class SoftDeleteProductDto : DtoBridge 
{
    public string Id { get; set; }
    public string Reason { get; set; }
    public string Comments { get; set; }
}
```

### **Command**: `SoftDeleteProductCommand`

```csharp
public class SoftDeleteProductCommand : FlexCommandBridge<SoftDeleteProductDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Key Differences from Regular Delete/Update

### **Soft Delete-Specific Characteristics**

1. **Reversible Operation**: Can be undone unlike hard delete
2. **State Management**: Uses `SetSoftDelete()` instead of `SetDeleted()` or `SetModified()`
3. **Audit Trail**: Tracks who soft deleted and when
4. **Business Logic**: Includes reason and comments for soft delete
5. **Data Preservation**: Data remains in database but marked as soft deleted
6. **Query Filtering**: Soft-deleted entities are filtered out of normal queries

### **PreBus Validation Focus**

* **IsValidForSoftDelete**: Validates product exists and can be soft deleted
* **CheckProductDependencies**: Ensures no active references to the product
* **Business Rules**: Validates soft delete is allowed based on business constraints
* **Data Integrity**: Ensures soft delete doesn't violate business rules

### **Soft Delete vs Hard Delete vs Update**

| Aspect              | Soft Delete       | Hard Delete       | Update            |
| ------------------- | ----------------- | ----------------- | ----------------- |
| **Method**          | `SetSoftDelete()` | `SetDeleted()`    | `SetModified()`   |
| **Reversible**      | ✅ Yes             | ❌ No              | ✅ Yes             |
| **Data Preserved**  | ✅ Yes             | ❌ No              | ✅ Yes             |
| **Audit Trail**     | ✅ Full            | ✅ Limited         | ✅ Full            |
| **Query Filtering** | ✅ Filtered        | ❌ Removed         | ✅ Normal          |
| **Use Case**        | Temporary removal | Permanent removal | Data modification |

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **PUT Request** → Controller receives request
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Entity lookup and data processing
5. **Domain Logic** → Business rules and soft delete state management
6. **Response** → HTTP 200 OK with soft delete status

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ProductSoftDeletedEvent published to message bus
2. **Subscriber Processing** → NotifyInventoryOnProductSoftDeleted executes
3. **Side Effects** → Inventory updates, supplier notifications, analytics

## Key Benefits

* **Data Safety**: Preserves data for potential recovery
* **Business Continuity**: Maintains referential integrity
* **Audit Compliance**: Complete audit trail of soft deletions
* **Reversible Operations**: Can be undone if needed
* **Business Rules**: Validates soft delete is appropriate
* **Event-Driven**: Notifies other systems of soft deletions
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This SoftDeleteProduct example demonstrates how FlexBase enables clean, maintainable, and scalable soft delete operations with proper validation, reversible state management, and event-driven architecture!** 🚀


# Get By Id Example

## Overview

This document demonstrates the complete **Get By ID flow** using the **GetProductById** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This returns a single entity by its unique identifier.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → Database → Response
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (Data Retrieval)
   ↓
5. Database (Data Query)
   ↓
6. AutoMapper (Data Transformation)
   ↓
7. Response (Single Entity)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ProductsController_GetProductById.cs`

```csharp
[HttpGet()]
[Route("GetProductById/{id}")]
[ProducesResponseType(typeof(GetProductByIdDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetProductById(string id)
{
    GetProductByIdParams parameters = new GetProductByIdParams();
    parameters.Id = id;

    return RunQuerySingleService<GetProductByIdParams, GetProductByIdDto>(
                parameters, _processProductsService.GetProductById);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Products/GetProductById/{id}`
* **Input**: Product ID from URL parameter
* **Parameter Creation**: Creates `GetProductByIdParams` with the ID
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `GetProductByIdDto` or 404 Not Found

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessProductsService_GetProductById.cs`

```csharp
public GetProductByIdDto GetProductById(GetProductByIdParams @params)
{
    return _flexHost.GetFlexiQuery<GetProductById>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetProductById
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns single product or null if not found

### 3. **Query Handler** - Data Retrieval

**File**: `GetProductById.cs`

```csharp
public class GetProductById : FlexiQueryBridge<Product, GetProductByIdDto>
{
    protected readonly ILogger<GetProductById> _logger;
    protected GetProductByIdParams _params;
    protected readonly RepoFactory _repoFactory;

    public GetProductById(ILogger<GetProductById> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual GetProductById AssignParameters(GetProductByIdParams @params)
    {
        _params = @params;
        return this;
    }

    public override GetProductByIdDto Fetch()
    {
        var result = Build<Product>().SelectTo<GetProductByIdDto>().FirstOrDefault();

        return result;
    }

    protected override IQueryable<T> Build<T>()
    {
        _repoFactory.Init(_params);

        IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>().Where(t => t.Id == _params.Id);
        return query;
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in query building
* **Query Building**: Creates the database query with ID filtering
* **Data Projection**: Uses AutoMapper to project to DTO
* **Single Result**: Returns first matching entity or null
* **ID Filtering**: Filters by the specific ID parameter

### 4. **Query Parameters** - Input DTO

**File**: `GetProductByIdParams.cs`

```csharp
public class GetProductByIdParams : DtoBridge
{
    public string Id { get; set; }
}
```

**What Happens:**

* **ID Parameter**: Contains the unique identifier for the entity
* **Simple Structure**: Minimal parameters for single entity lookup
* **URL Binding**: ID is automatically bound from URL parameter

### 5. **Output DTO** - Data Transfer Object

**File**: `GetProductByIdDto.cs`

```csharp
public partial class GetProductByIdDto : DtoBridge 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string CategoryId { get; set; }
    public string CategoryName { get; set; }
    public string Sku { get; set; }
    public int StockQuantity { get; set; }
    public bool IsActive { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? LastModifiedDate { get; set; }
    public string CreatedBy { get; set; }
    public string LastModifiedBy { get; set; }
}
```

**What Happens:**

* **Complete Data**: Contains all relevant fields for the entity
* **Detailed Structure**: Includes all properties for full entity display
* **Related Data**: May include related entity information (CategoryName)
* **Audit Fields**: Includes creation and modification tracking

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetProductByIdMapperConfiguration.cs`

```csharp
public partial class GetProductByIdMapperConfiguration : FlexMapperProfile
{
    public GetProductByIdMapperConfiguration() : base()
    {
        CreateMap<Product, GetProductByIdDto>()
            .ForMember(d => d.CategoryName, opt => opt.MapFrom(s => s.Category.Name))
            .ForMember(d => d.IsActive, opt => opt.MapFrom(s => !s.IsSoftDeleted));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Related Data**: Maps related entity properties
* **Computed Fields**: Handles calculated properties

## Key Differences from Other Query Operations

### **Get By ID vs Other Query Characteristics**

| Aspect                | Get By ID                  | Get List                     | Get Paged List               |
| --------------------- | -------------------------- | ---------------------------- | ---------------------------- |
| **Return Type**       | `T` (single entity)        | `IEnumerable<T>`             | `FlexiPagedList<T>`          |
| **Input**             | ID from URL                | Query parameters             | Query parameters             |
| **Result Count**      | 0 or 1                     | 0 to many                    | 0 to many (paginated)        |
| **Use Case**          | Single entity details      | Dropdown/lookup              | Data grids/tables            |
| **Performance**       | Very fast (indexed lookup) | Fast for small datasets      | Optimized for large datasets |
| **Controller Method** | `RunQuerySingleService`    | `RunQueryListService`        | `RunQueryPagedService`       |
| **Query Base**        | `FlexiQueryBridge`         | `FlexiQueryEnumerableBridge` | `FlexiQueryPagedListBridge`  |
| **HTTP Status**       | 200 OK or 404 Not Found    | 200 OK                       | 200 OK                       |

### **Get By ID-Specific Features**

1. **Single Entity**: Returns one entity or null
2. **ID-Based Lookup**: Uses unique identifier for fast retrieval
3. **404 Handling**: Returns 404 when entity not found
4. **Complete Data**: Returns all entity details
5. **Fast Performance**: Optimized for indexed lookups

### **Common Use Cases**

* **Entity Details**: Display detailed information about a specific entity
* **Edit Forms**: Load entity data for editing
* **View Pages**: Show complete entity information
* **API Integration**: Retrieve specific entity for external systems
* **Validation**: Check if entity exists before operations

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with ID parameter
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Response** → HTTP 200 OK with entity or 404 Not Found

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>().Where(t => t.Id == _params.Id);
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Filter by ID
    query = query.Where(t => t.Id == _params.Id);
    
    // Exclude soft deleted items
    query = query.Where(t => !t.IsSoftDeleted);
    
    // Include related entities if needed
    // query = query.Include(t => t.Category);
    
    return query;
}
```

### **Error Handling Patterns**

```csharp
public override GetProductByIdDto Fetch()
{
    var result = Build<Product>().SelectTo<GetProductByIdDto>().FirstOrDefault();
    
    if (result == null)
    {
        _logger.LogWarning("Product with ID {ProductId} not found", _params.Id);
    }
    else
    {
        _logger.LogDebug("Product with ID {ProductId} retrieved successfully", _params.Id);
    }
    
    return result;
}
```

## Performance Considerations

### **Optimization Strategies**

1. **Database Indexing**: Ensure ID field is properly indexed
2. **Selective Fields**: Only return necessary fields in DTO
3. **Related Data**: Use Include() judiciously for related entities
4. **Caching**: Consider caching for frequently accessed entities
5. **Query Optimization**: Use FirstOrDefault() for single entity retrieval

### **When to Use Get By ID vs Other Queries**

| Scenario                | Use Get By ID | Use Get List | Use Get Paged List |
| ----------------------- | ------------- | ------------ | ------------------ |
| **Entity Details Page** | ✅ Yes         | ❌ No         | ❌ No               |
| **Edit Form Loading**   | ✅ Yes         | ❌ No         | ❌ No               |
| **API Integration**     | ✅ Yes         | ❌ No         | ❌ No               |
| **Dropdown Population** | ❌ No          | ✅ Yes        | ❌ No               |
| **Data Grids**          | ❌ No          | ❌ No         | ✅ Yes              |
| **Search Results**      | ❌ No          | ✅ Yes        | ✅ Yes              |
| **Lookup Tables**       | ❌ No          | ✅ Yes        | ❌ No               |

## Error Handling

### **HTTP Status Codes**

* **200 OK**: Entity found and returned successfully
* **404 Not Found**: Entity with specified ID does not exist
* **400 Bad Request**: Invalid ID format or missing ID parameter
* **500 Internal Server Error**: Database or server error

### **Controller Error Handling**

```csharp
[HttpGet()]
[Route("GetProductById/{id}")]
[ProducesResponseType(typeof(GetProductByIdDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetProductById(string id)
{
    if (string.IsNullOrEmpty(id))
    {
        return BadRequest("Product ID is required");
    }
    
    GetProductByIdParams parameters = new GetProductByIdParams();
    parameters.Id = id;

    return RunQuerySingleService<GetProductByIdParams, GetProductByIdDto>(
                parameters, _processProductsService.GetProductById);
}
```

## Key Benefits

* **Performance**: Very fast retrieval using indexed ID lookup
* **Simplicity**: Simple single entity retrieval
* **Complete Data**: Returns full entity details
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **Error Handling**: Built-in 404 handling for missing entities
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetProductById example demonstrates how FlexBase enables clean, maintainable, and scalable single entity retrieval operations with proper error handling and performance optimization!** 🚀


# Get List Example

## Overview

This document demonstrates the complete **Get List flow** using the **GetProductsForLookup** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This is similar to Get Paged List but returns a simple `IEnumerable<T>` without pagination.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → Database → Response
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (Data Retrieval)
   ↓
5. Database (Data Query)
   ↓
6. AutoMapper (Data Transformation)
   ↓
7. Response (Simple List)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ProductsController_GetProductsForLookup.cs`

```csharp
[HttpGet()]
[Route("GetProductsForLookup")]
[ProducesResponseType(typeof(IEnumerable<GetProductsForLookupDto>), 200)]
public async Task<IActionResult> GetProductsForLookup([FromQuery]GetProductsForLookupParams parameters)
{
    return RunQueryListService<GetProductsForLookupParams, GetProductsForLookupDto>(
                parameters, _processProductsService.GetProductsForLookup);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Products/GetProductsForLookup`
* **Input**: `GetProductsForLookupParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `IEnumerable<GetProductsForLookupDto>`

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessProductsService_GetProductsForLookup.cs`

```csharp
public IEnumerable<GetProductsForLookupDto> GetProductsForLookup(GetProductsForLookupParams @params)
{
    return _flexHost.GetFlexiQuery<GetProductsForLookup>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetProductsForLookup
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns simple list of products for lookup

### 3. **Query Handler** - Data Retrieval

**File**: `GetProductsForLookup.cs`

```csharp
public class GetProductsForLookup : FlexiQueryEnumerableBridge<Product, GetProductsForLookupDto>
{
    protected readonly ILogger<GetProductsForLookup> _logger;
    protected GetProductsForLookupParams _params;
    protected readonly RepoFactory _repoFactory;

    public GetProductsForLookup(ILogger<GetProductsForLookup> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual GetProductsForLookup AssignParameters(GetProductsForLookupParams @params)
    {
        _params = @params;
        return this;
    }

    public override IEnumerable<GetProductsForLookupDto> Fetch()
    {
        var result = Build<Product>().SelectTo<GetProductsForLookupDto>().ToList();

        return result;
    }
    
    protected override IQueryable<T> Build<T>()
    {
       _repoFactory.Init(_params);

        IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();

        //Build Your Query Here

        return query;
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in query building
* **Query Building**: Creates the database query with filtering
* **Data Projection**: Uses AutoMapper to project to DTOs
* **Result Building**: Creates the simple list output

### 4. **Query Parameters** - Input DTO

**File**: `GetProductsForLookupParams.cs`

```csharp
public class GetProductsForLookupParams : DtoBridge
{
    // Add custom filtering parameters here
    public string SearchTerm { get; set; }
    public string CategoryId { get; set; }
    public bool? IsActive { get; set; }
    public int? Limit { get; set; }
}
```

**What Happens:**

* **Custom Filters**: Allows filtering by search term, category, active status
* **Limit Support**: Optional limit for lookup results
* **Query Parameters**: Automatically bound from URL query string

### 5. **Output DTO** - Data Transfer Object

**File**: `GetProductsForLookupDto.cs`

```csharp
public partial class GetProductsForLookupDto : DtoBridge 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string CategoryName { get; set; }
    public bool IsActive { get; set; }
}
```

**What Happens:**

* **Lookup Data**: Contains essential fields for dropdown/lookup scenarios
* **Minimal Structure**: Only includes necessary fields for selection
* **Performance**: Lightweight DTO for fast loading

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetProductsForLookupMapperConfiguration.cs`

```csharp
public partial class GetProductsForLookupMapperConfiguration : FlexMapperProfile
{
    public GetProductsForLookupMapperConfiguration() : base()
    {
        CreateMap<Product, GetProductsForLookupDto>()
            .ForMember(d => d.CategoryName, opt => opt.MapFrom(s => s.Category.Name))
            .ForMember(d => d.IsActive, opt => opt.MapFrom(s => !s.IsSoftDeleted));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Lookup Optimization**: Maps only necessary fields for lookup scenarios

## Key Differences from Get Paged List

### **Get List vs Get Paged List Characteristics**

| Aspect                | Get List                       | Get Paged List                    |
| --------------------- | ------------------------------ | --------------------------------- |
| **Return Type**       | `IEnumerable<T>`               | `FlexiPagedList<T>`               |
| **Pagination**        | ❌ No pagination                | ✅ Built-in pagination             |
| **Use Case**          | Lookup/Dropdown                | Data grids/tables                 |
| **Performance**       | Fast for small datasets        | Optimized for large datasets      |
| **Memory Usage**      | Lower (no pagination metadata) | Higher (includes pagination info) |
| **Controller Method** | `RunQueryListService`          | `RunQueryPagedService`            |
| **Query Base**        | `FlexiQueryEnumerableBridge`   | `FlexiQueryPagedListBridge`       |

### **Get List-Specific Features**

1. **Simple List**: Returns basic `IEnumerable<T>` without pagination
2. **Lookup Optimized**: Designed for dropdown/lookup scenarios
3. **Lightweight**: Minimal data transfer for performance
4. **No Pagination**: All results returned in single response
5. **Fast Loading**: Optimized for quick data retrieval

### **Common Use Cases**

* **Dropdown Lists**: Populate dropdown controls
* **Lookup Tables**: Search and select scenarios
* **Reference Data**: Load reference data for forms
* **Auto-complete**: Provide suggestions for input fields
* **Quick Filters**: Fast filtering options

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with query parameters
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Response** → HTTP 200 OK with simple list

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Add filtering logic here
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        query = query.Where(p => p.Name.Contains(_params.SearchTerm) || 
                                p.Description.Contains(_params.SearchTerm));
    }
    
    if (!string.IsNullOrEmpty(_params.CategoryId))
    {
        query = query.Where(p => p.CategoryId == _params.CategoryId);
    }
    
    if (_params.IsActive.HasValue)
    {
        query = query.Where(p => p.IsSoftDeleted == !_params.IsActive.Value);
    }
    
    // Apply limit if specified
    if (_params.Limit.HasValue)
    {
        query = query.Take(_params.Limit.Value);
    }
    
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Exclude soft deleted items
    query = query.Where(p => !p.IsSoftDeleted);
    
    // Search functionality
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        var searchTerm = _params.SearchTerm.ToLower();
        query = query.Where(p => p.Name.ToLower().Contains(searchTerm) || 
                                p.Description.ToLower().Contains(searchTerm) ||
                                p.Sku.ToLower().Contains(searchTerm));
    }
    
    // Category filtering
    if (!string.IsNullOrEmpty(_params.CategoryId))
    {
        query = query.Where(p => p.CategoryId == _params.CategoryId);
    }
    
    // Active status filtering
    if (_params.IsActive.HasValue)
    {
        query = query.Where(p => p.IsActive == _params.IsActive.Value);
    }
    
    // Price range filtering (if needed)
    if (_params.MinPrice.HasValue)
    {
        query = query.Where(p => p.Price >= _params.MinPrice.Value);
    }
    
    if (_params.MaxPrice.HasValue)
    {
        query = query.Where(p => p.Price <= _params.MaxPrice.Value);
    }
    
    // Sorting for consistent results
    query = query.OrderBy(p => p.Name);
    
    // Apply limit for performance
    if (_params.Limit.HasValue)
    {
        query = query.Take(_params.Limit.Value);
    }
    else
    {
        // Default limit for lookup scenarios
        query = query.Take(100);
    }
    
    return query;
}
```

## Performance Considerations

### **Optimization Strategies**

1. **Limit Results**: Always apply reasonable limits for lookup scenarios
2. **Selective Fields**: Only return necessary fields in DTO
3. **Indexing**: Ensure proper database indexes on filter fields
4. **Caching**: Consider caching for frequently accessed lookup data
5. **Lazy Loading**: Use lazy loading for related entities when appropriate

### **When to Use Get List vs Get Paged List**

| Scenario                | Use Get List | Use Get Paged List |
| ----------------------- | ------------ | ------------------ |
| **Dropdown Population** | ✅ Yes        | ❌ No               |
| **Lookup Tables**       | ✅ Yes        | ❌ No               |
| **Auto-complete**       | ✅ Yes        | ❌ No               |
| **Data Grids**          | ❌ No         | ✅ Yes              |
| **Large Datasets**      | ❌ No         | ✅ Yes              |
| **Admin Interfaces**    | ❌ No         | ✅ Yes              |
| **Reporting**           | ❌ No         | ✅ Yes              |

## Key Benefits

* **Performance**: Fast loading for small datasets
* **Simplicity**: Simple list without pagination complexity
* **Lookup Optimized**: Perfect for dropdown/lookup scenarios
* **Lightweight**: Minimal data transfer
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetProductsForLookup example demonstrates how FlexBase enables clean, maintainable, and scalable list operations optimized for lookup and dropdown scenarios!** 🚀


# Get Single Example

## Overview

This document demonstrates the complete **Get Single flow** using the **GetProductSingle** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This returns a single entity based on specific criteria (not necessarily by ID).

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → Database → Response
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (Data Retrieval)
   ↓
5. Database (Data Query)
   ↓
6. AutoMapper (Data Transformation)
   ↓
7. Response (Single Entity)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ProductsController_GetProductSingle.cs`

```csharp
[HttpGet()]
[Route("GetProductSingle")]
[ProducesResponseType(typeof(GetProductSingleDto), 200)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetProductSingle([FromQuery]GetProductSingleParams parameters)
{
    return RunQuerySingleService<GetProductSingleParams, GetProductSingleDto>(
                parameters, _processProductsService.GetProductSingle);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Products/GetProductSingle`
* **Input**: Query parameters from URL query string
* **Parameter Binding**: Binds query parameters to `GetProductSingleParams`
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `GetProductSingleDto` or 404 Not Found

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessProductsService_GetProductSingle.cs`

```csharp
public GetProductSingleDto GetProductSingle(GetProductSingleParams @params)
{
    return _flexHost.GetFlexiQuery<GetProductSingle>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetProductSingle
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns single product or null if not found

### 3. **Query Handler** - Data Retrieval

**File**: `GetProductSingle.cs`

```csharp
public class GetProductSingle : FlexiQueryBridge<Product, GetProductSingleDto>
{
    protected readonly ILogger<GetProductSingle> _logger;
    protected GetProductSingleParams _params;
    protected readonly RepoFactory _repoFactory;

    public GetProductSingle(ILogger<GetProductSingle> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual GetProductSingle AssignParameters(GetProductSingleParams @params)
    {
        _params = @params;
        return this;
    }

    public override GetProductSingleDto Fetch()
    {
        var result = Build<Product>().SelectTo<GetProductSingleDto>().FirstOrDefault();

        return result;
    }

    protected override IQueryable<T> Build<T>()
    {
        _repoFactory.Init(_params);

        IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();

        //Build Your Query Here

        return query;
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in query building
* **Query Building**: Creates the database query with custom filtering
* **Data Projection**: Uses AutoMapper to project to DTO
* **Single Result**: Returns first matching entity or null
* **Custom Filtering**: Applies business-specific criteria

### 4. **Query Parameters** - Input DTO

**File**: `GetProductSingleParams.cs`

```csharp
public class GetProductSingleParams : DtoBridge
{
    public string Sku { get; set; }
    public string Name { get; set; }
    public string CategoryId { get; set; }
    public bool? IsActive { get; set; }
    public decimal? MinPrice { get; set; }
    public decimal? MaxPrice { get; set; }
}
```

**What Happens:**

* **Multiple Criteria**: Contains various search parameters
* **Flexible Filtering**: Allows searching by different criteria
* **Query Binding**: Parameters are bound from URL query string
* **Optional Parameters**: All parameters are optional for flexible searching

### 5. **Output DTO** - Data Transfer Object

**File**: `GetProductSingleDto.cs`

```csharp
public partial class GetProductSingleDto : DtoBridge 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Sku { get; set; }
    public string CategoryId { get; set; }
    public string CategoryName { get; set; }
    public int StockQuantity { get; set; }
    public bool IsActive { get; set; }
    public DateTime CreatedDate { get; set; }
    public string CreatedBy { get; set; }
}
```

**What Happens:**

* **Complete Data**: Contains all relevant fields for the entity
* **Search Result**: Represents the single entity found by criteria
* **Related Data**: May include related entity information (CategoryName)
* **Audit Fields**: Includes creation and modification tracking

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetProductSingleMapperConfiguration.cs`

```csharp
public partial class GetProductSingleMapperConfiguration : FlexMapperProfile
{
    public GetProductSingleMapperConfiguration() : base()
    {
        CreateMap<Product, GetProductSingleDto>()
            .ForMember(d => d.CategoryName, opt => opt.MapFrom(s => s.Category.Name))
            .ForMember(d => d.IsActive, opt => opt.MapFrom(s => !s.IsSoftDeleted));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Related Data**: Maps related entity properties
* **Computed Fields**: Handles calculated properties

## Key Differences from Get By ID

### **Get Single vs Get By ID Characteristics**

| Aspect                | Get Single                     | Get By ID             |
| --------------------- | ------------------------------ | --------------------- |
| **Input**             | Query parameters               | ID from URL           |
| **Search Criteria**   | Multiple criteria              | Single ID             |
| **Use Case**          | Search by business criteria    | Direct ID lookup      |
| **Performance**       | Depends on criteria            | Very fast (indexed)   |
| **Flexibility**       | High (multiple filters)        | Low (single ID)       |
| **URL Pattern**       | `/GetProductSingle?sku=ABC123` | `/GetProductById/123` |
| **Parameter Binding** | `[FromQuery]`                  | URL parameter         |
| **Query Complexity**  | Can be complex                 | Simple ID filter      |

### **Get Single-Specific Features**

1. **Criteria-Based Search**: Uses business criteria instead of ID
2. **Multiple Parameters**: Supports various search filters
3. **Flexible Filtering**: Can search by any combination of criteria
4. **Business Logic**: Applies business-specific search rules
5. **Query Building**: Custom query building in the `Build<T>()` method

### **Common Use Cases**

* **Search by SKU**: Find product by unique SKU code
* **Search by Name**: Find product by partial or exact name match
* **Category Search**: Find a product in a specific category
* **Price Range**: Find product within price range
* **Active Products**: Find active products only
* **Combined Criteria**: Find product matching multiple criteria

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Filter by SKU if provided
    if (!string.IsNullOrEmpty(_params.Sku))
    {
        query = query.Where(p => p.Sku == _params.Sku);
    }
    
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Filter by SKU if provided
    if (!string.IsNullOrEmpty(_params.Sku))
    {
        query = query.Where(p => p.Sku == _params.Sku);
    }
    
    // Filter by name if provided
    if (!string.IsNullOrEmpty(_params.Name))
    {
        query = query.Where(p => p.Name.Contains(_params.Name));
    }
    
    // Filter by category if provided
    if (!string.IsNullOrEmpty(_params.CategoryId))
    {
        query = query.Where(p => p.CategoryId == _params.CategoryId);
    }
    
    // Filter by active status if provided
    if (_params.IsActive.HasValue)
    {
        query = query.Where(p => p.IsActive == _params.IsActive.Value);
    }
    
    // Filter by price range if provided
    if (_params.MinPrice.HasValue)
    {
        query = query.Where(p => p.Price >= _params.MinPrice.Value);
    }
    
    if (_params.MaxPrice.HasValue)
    {
        query = query.Where(p => p.Price <= _params.MaxPrice.Value);
    }
    
    // Exclude soft deleted items
    query = query.Where(p => !p.IsSoftDeleted);
    
    // Order by name for consistent results
    query = query.OrderBy(p => p.Name);
    
    return query;
}
```

### **Error Handling Patterns**

```csharp
public override GetProductSingleDto Fetch()
{
    var result = Build<Product>().SelectTo<GetProductSingleDto>().FirstOrDefault();
    
    if (result == null)
    {
        _logger.LogWarning("No product found matching criteria: {Criteria}", 
            $"Sku: {_params.Sku}, Name: {_params.Name}, CategoryId: {_params.CategoryId}");
    }
    else
    {
        _logger.LogDebug("Product found matching criteria: {ProductId}", result.Id);
    }
    
    return result;
}
```

## Common Search Scenarios

### **1. Search by SKU**

```
GET /api/Products/GetProductSingle?sku=ABC123
```

* **Use Case**: Find product by unique SKU code
* **Query**: `WHERE Sku = 'ABC123'`
* **Performance**: Very fast (indexed field)

### **2. Search by Name**

```
GET /api/Products/GetProductSingle?name=iPhone
```

* **Use Case**: Find product by name (partial match)
* **Query**: `WHERE Name LIKE '%iPhone%'`
* **Performance**: Depends on name index

### **3. Search by Category**

```
GET /api/Products/GetProductSingle?categoryId=CAT001
```

* **Use Case**: Find a product in specific category
* **Query**: `WHERE CategoryId = 'CAT001'`
* **Performance**: Fast (indexed field)

### **4. Search by Price Range**

```
GET /api/Products/GetProductSingle?minPrice=100&maxPrice=500
```

* **Use Case**: Find product within price range
* **Query**: `WHERE Price >= 100 AND Price <= 500`
* **Performance**: Depends on price index

### **5. Search by Active Status**

```
GET /api/Products/GetProductSingle?isActive=true
```

* **Use Case**: Find active products only
* **Query**: `WHERE IsActive = true`
* **Performance**: Fast (indexed field)

### **6. Combined Criteria**

```
GET /api/Products/GetProductSingle?categoryId=CAT001&isActive=true&minPrice=100
```

* **Use Case**: Find active product in category with minimum price
* **Query**: `WHERE CategoryId = 'CAT001' AND IsActive = true AND Price >= 100`
* **Performance**: Depends on combined indexes

## Performance Considerations

### **Optimization Strategies**

1. **Database Indexing**: Create indexes on commonly searched fields
2. **Query Optimization**: Use appropriate WHERE clauses
3. **Parameter Validation**: Validate parameters before query execution
4. **Caching**: Consider caching for frequently accessed data
5. **Query Limits**: Consider adding TOP 1 for performance

### **Indexing Recommendations**

```sql
-- Create indexes for common search criteria
CREATE INDEX IX_Product_Sku ON Products (Sku);
CREATE INDEX IX_Product_Name ON Products (Name);
CREATE INDEX IX_Product_CategoryId ON Products (CategoryId);
CREATE INDEX IX_Product_IsActive ON Products (IsActive);
CREATE INDEX IX_Product_Price ON Products (Price);
CREATE INDEX IX_Product_IsSoftDeleted ON Products (IsSoftDeleted);

-- Composite index for common combinations
CREATE INDEX IX_Product_CategoryId_IsActive ON Products (CategoryId, IsActive);
CREATE INDEX IX_Product_IsActive_Price ON Products (IsActive, Price);
```

## Error Handling

### **HTTP Status Codes**

* **200 OK**: Entity found and returned successfully
* **404 Not Found**: No entity found matching criteria
* **400 Bad Request**: Invalid parameters or missing required criteria
* **500 Internal Server Error**: Database or server error

### **Controller Error Handling**

```csharp
[HttpGet()]
[Route("GetProductSingle")]
[ProducesResponseType(typeof(GetProductSingleDto), 200)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetProductSingle([FromQuery]GetProductSingleParams parameters)
{
    // Validate that at least one search criteria is provided
    if (string.IsNullOrEmpty(parameters.Sku) && 
        string.IsNullOrEmpty(parameters.Name) && 
        string.IsNullOrEmpty(parameters.CategoryId) &&
        !parameters.IsActive.HasValue &&
        !parameters.MinPrice.HasValue &&
        !parameters.MaxPrice.HasValue)
    {
        return BadRequest("At least one search criteria must be provided");
    }
    
    return RunQuerySingleService<GetProductSingleParams, GetProductSingleDto>(
                parameters, _processProductsService.GetProductSingle);
}
```

## When to Use Get Single vs Other Queries

### **Use Get Single When:**

* **Specific Search**: Need to find one entity by business criteria
* **Unique Lookup**: Search by unique business identifier (SKU, email, etc.)
* **Complex Criteria**: Need to apply multiple search filters
* **Business Logic**: Search requires business-specific rules
* **Single Result**: Expect only one result or want the first match

### **Use Get By ID When:**

* **Direct Lookup**: Have the exact ID of the entity
* **Performance Critical**: Need fastest possible lookup
* **Simple Access**: Direct access to known entity

### **Use Get List When:**

* **Multiple Results**: Need all entities matching criteria
* **Dropdown Data**: Populate dropdowns or lists
* **Small Datasets**: Results are typically small

### **Use Get Paged List When:**

* **Large Datasets**: Results can be large
* **Data Grids**: Display data in paginated tables
* **Performance**: Need to limit result set size

## Key Benefits

* **Flexible Search**: Supports multiple search criteria
* **Business Logic**: Can implement complex search rules
* **Single Result**: Returns one entity or null
* **Query Parameters**: Easy to use with query strings
* **Performance**: Can be optimized with proper indexing
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **Error Handling**: Built-in 404 handling for no results
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetProductSingle example demonstrates how FlexBase enables flexible, criteria-based single entity retrieval operations with proper query building and performance optimization!** 🚀


# Get Paged List Example

## Overview

This document demonstrates the complete **Get Paged List flow** using the **GetOrders** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → Database → Response
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (Data Retrieval)
   ↓
5. Database (Data Query)
   ↓
6. AutoMapper (Data Transformation)
   ↓
7. Response (Paged Results)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `OrdersController_GetOrders.cs`

```csharp
[HttpGet()]
[Route("GetOrders")]
[ProducesResponseType(typeof(FlexiPagedList<GetOrdersDto>), 200)]
public async Task<IActionResult> GetOrders([FromQuery]GetOrdersParams parameters)
{
    return RunQueryPagedService<GetOrdersParams, GetOrdersDto>(parameters, _processOrdersService.GetOrders);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Orders/GetOrders`
* **Input**: `GetOrdersParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `FlexiPagedList<GetOrdersDto>`

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessOrdersService_GetOrders.cs`

```csharp
public FlexiPagedList<GetOrdersDto> GetOrders(GetOrdersParams @params)
{
    return _flexHost.GetFlexiQuery<GetOrders>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetOrders
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns paged list of orders

### 3. **Query Handler** - Data Retrieval

**File**: `GetOrders.cs`

```csharp
public class GetOrders : FlexiQueryPagedListBridge<Order, GetOrdersParams, GetOrdersDto, FlexAppContextBridge>
{
    protected readonly ILogger<GetOrders> _logger;
    protected GetOrdersParams _params;
    protected readonly RepoFactory _repoFactory;

    public GetOrders(ILogger<GetOrders> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual GetOrders AssignParameters(GetOrdersParams @params)
    {
        _params = @params;
        return this;
    }

    public override FlexiPagedList<GetOrdersDto> Fetch()
    {
        var projection = Build<Order>().SelectTo<GetOrdersDto>().ToList();

        var result = BuildPagedOutput(projection);

        return result;
    }

    protected override IQueryable<T> Build<T>()
    {
        _repoFactory.Init(_params);

        IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();

        //Build Your Query With All Parameters Here

        query = CreatePagedQuery<T>(query, _params.PageNumber, _params.PageSize);

        return query;
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in query building
* **Query Building**: Creates the database query with filtering and pagination
* **Data Projection**: Uses AutoMapper to project to DTOs
* **Pagination**: Applies pagination logic to the results
* **Result Building**: Creates the paged output with metadata

### 4. **Query Parameters** - Input DTO

**File**: `GetOrdersParams.cs`

```csharp
public class GetOrdersParams : PagedQueryParamsDtoBridge
{
    // Inherits pagination properties from PagedQueryParamsDtoBridge:
    // - PageNumber
    // - PageSize
    // - SortBy
    // - SortDirection
    
    // Add custom filtering parameters here
    public string CustomerId { get; set; }
    public DateTime? OrderDateFrom { get; set; }
    public DateTime? OrderDateTo { get; set; }
    public string OrderState { get; set; }
}
```

**What Happens:**

* **Pagination Support**: Inherits standard pagination properties
* **Custom Filters**: Allows filtering by customer, date range, order state
* **Query Parameters**: Automatically bound from URL query string

### 5. **Output DTO** - Data Transfer Object

**File**: `GetOrdersDto.cs`

```csharp
public partial class GetOrdersDto : DtoBridge 
{
    public string CurrentOrderState { get; set; }
    public DateTimeOffset OrderDate { get; set; }
    public string CustomerId { get; set; }
    public int TotalQty { get; set; }
    public decimal TotalAmount { get; set; }
    public ICollection<GetOrdersDto_OrderItem> OrderItems { get; set; }
}
```

**File**: `GetOrdersDto_OrderItem.cs`

```csharp
public partial class GetOrdersDto_OrderItem : DtoBridge
{
    public string ProductId { get; set; }
    public string ProductName { get; set; }
    public int Qty { get; set; }
    public decimal SellingPrice { get; set; }
    public decimal Amount { get; set; }
}
```

**What Happens:**

* **Data Structure**: Defines the shape of returned data
* **Nested Objects**: Includes related order items
* **Calculated Fields**: Contains computed properties like Amount

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetOrdersMapperConfiguration.cs`

```csharp
public partial class GetOrdersMapperConfiguration : FlexMapperProfile
{
    public GetOrdersMapperConfiguration() : base()
    {
        CreateMap<Order, GetOrdersDto>()
            .ForMember(o => o.CurrentOrderState, opt => opt.MapFrom(o => o.OrderState.GetType().Name)); 
        CreateMap<OrderItem, GetOrdersDto_OrderItem>()
            .ForMember(o => o.ProductName, opt => opt.MapFrom(o => o.Product.Name))
            .ForMember(o => o.Amount, opt => opt.MapFrom(o => o.SellingPrice * o.Qty)); 
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Calculated Fields**: Computes derived properties
* **Nested Mappings**: Maps related entities to nested DTOs

## Key Differences from Command Operations

### **Query vs Command Characteristics**

| Aspect                 | Query (Get Paged List) | Command (Insert/Update/Delete) |
| ---------------------- | ---------------------- | ------------------------------ |
| **Purpose**            | Data Retrieval         | Data Modification              |
| **HTTP Method**        | `GET`                  | `POST`, `PUT`, `DELETE`        |
| **Handler Type**       | Query Handler          | Command Handler                |
| **Return Type**        | `FlexiPagedList<T>`    | `CommandResult`                |
| **Database Operation** | `SELECT`               | `INSERT`, `UPDATE`, `DELETE`   |
| **Events**             | ❌ No events published  | ✅ Events published             |
| **PreBus**             | ❌ No PreBus validation | ✅ PreBus validation            |
| **State Changes**      | ❌ No state changes     | ✅ State changes                |

### **Query-Specific Features**

1. **Pagination Support**: Built-in pagination with `FlexiPagedList<T>`
2. **AutoMapper Integration**: Automatic entity-to-DTO mapping
3. **Query Building**: Flexible query construction with filtering
4. **Performance**: Optimized for data retrieval
5. **No Side Effects**: Read-only operations

### **Pagination Features**

* **PageNumber**: Current page number (1-based)
* **PageSize**: Number of items per page
* **TotalCount**: Total number of items across all pages
* **TotalPages**: Total number of pages
* **HasNextPage**: Whether there are more pages
* **HasPreviousPage**: Whether there are previous pages

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with query parameters
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Pagination** → Apply pagination logic
6. **Response** → HTTP 200 OK with paged results

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Add filtering logic here
    if (!string.IsNullOrEmpty(_params.CustomerId))
    {
        query = query.Where(o => o.CustomerId == _params.CustomerId);
    }
    
    if (_params.OrderDateFrom.HasValue)
    {
        query = query.Where(o => o.OrderDate >= _params.OrderDateFrom.Value);
    }
    
    // Apply pagination
    query = CreatePagedQuery<T>(query, _params.PageNumber, _params.PageSize);
    
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Complex filtering
    query = query.Where(o => !o.IsSoftDeleted);
    
    if (!string.IsNullOrEmpty(_params.CustomerId))
    {
        query = query.Where(o => o.CustomerId == _params.CustomerId);
    }
    
    // Date range filtering
    if (_params.OrderDateFrom.HasValue && _params.OrderDateTo.HasValue)
    {
        query = query.Where(o => o.OrderDate >= _params.OrderDateFrom.Value && 
                                o.OrderDate <= _params.OrderDateTo.Value);
    }
    
    // State filtering
    if (!string.IsNullOrEmpty(_params.OrderState))
    {
        query = query.Where(o => o.OrderState.GetType().Name == _params.OrderState);
    }
    
    // Sorting
    if (!string.IsNullOrEmpty(_params.SortBy))
    {
        switch (_params.SortBy.ToLower())
        {
            case "orderdate":
                query = _params.SortDirection == "desc" 
                    ? query.OrderByDescending(o => o.OrderDate)
                    : query.OrderBy(o => o.OrderDate);
                break;
            case "totalamount":
                query = _params.SortDirection == "desc" 
                    ? query.OrderByDescending(o => o.TotalAmount)
                    : query.OrderBy(o => o.TotalAmount);
                break;
        }
    }
    
    // Apply pagination
    query = CreatePagedQuery<T>(query, _params.PageNumber, _params.PageSize);
    
    return query;
}
```

## Key Benefits

* **Performance**: Optimized for data retrieval with pagination
* **Flexibility**: Easy to add filtering and sorting
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **Pagination**: Built-in pagination support
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetOrders example demonstrates how FlexBase enables clean, maintainable, and scalable query operations with built-in pagination, filtering, and data transformation capabilities!** 🚀


# REST Services

This section contains comprehensive documentation for REST service operations in FlexBase applications. Each document demonstrates the complete flow from API controller to database operations, including event publishing and subscriber processing.

## Available REST Operations

### **Communication Architecture**

* [**REST Client Communication**](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/solution-structure/getting-started/features/rest-services/rest-client-communication.md) - Complete communication flow explanation
* DTOs vs Request/Response Objects distinction
* Mapping between internal and external contracts
* RESTClient implementation patterns
* Error handling and resilience strategies

### **Insert Operations**

* [**Insert Example**](/solution-structure/getting-started/features/rest-services/insert-example) - `AddToShipping` flow demonstrating POST operations
* Complete flow from POST request to event publishing
* PreBus validation pipeline with business rules
* Command handler processing and domain logic
* Event-driven architecture with subscribers
* RESTClient integration for external communication

### **Update Operations**

* [**Update Example**](/solution-structure/getting-started/features/rest-services/update-example) - `UpdateShipping` flow demonstrating PUT operations
* Entity lookup and validation before updating
* PreBus validation with business rules
* Domain model state management
* Event publishing for change notifications
* RESTClient integration for external updates

### **Query Operations**

* [**Get By ID Example**](/solution-structure/getting-started/features/rest-services/get-by-id-example) - `GetShippingInfoById` flow demonstrating single entity retrieval
* Fast indexed lookup by unique identifier
* AutoMapper for entity-to-DTO transformation
* Error handling with 404 responses
* Optimized for single entity details
* RESTClient integration for external data
* [**Get List Example**](/solution-structure/getting-started/features/rest-services/get-list-example) - `GetShippingDetails` flow demonstrating list retrieval
* Simple `IEnumerable<T>` without pagination
* Optimized for dropdown/lookup scenarios
* Lightweight data transfer
* Fast loading for small datasets
* RESTClient integration for external lists
* [**Get Paged List Example**](/solution-structure/getting-started/features/rest-services/get-paged-list-example) - `GetShippingPagedList` flow demonstrating paginated retrieval
* `FlexiPagedList<T>` with pagination metadata
* Optimized for data grids and large datasets
* Built-in pagination with page numbers and sizes
* Rich metadata for frontend integration
* RESTClient integration for external pagination
* [**Get Single Example**](/solution-structure/getting-started/features/rest-services/get-single-example) - `GetShippingSingle` flow demonstrating flexible single entity retrieval
* Multiple criteria for entity identification
* Flexible filtering beyond just ID
* Business logic for complex lookups
* Alternative key support (tracking numbers, order IDs, etc.)
* RESTClient integration for external lookups

### **Delete Operations**

* [**Delete Example**](/solution-structure/getting-started/features/rest-services/delete-example) - `DeleteShipping` flow demonstrating hard delete operations
* Physical removal from database
* PreBus validation before deletion
* Event publishing for cleanup operations
* Audit trail considerations
* RESTClient integration for external deletions
* [**Soft Delete Example**](/solution-structure/getting-started/features/rest-services/soft-delete-example) - `SoftDeleteShipping` flow demonstrating soft delete operations
* Data preservation with deletion flag
* Recovery capabilities
* Complete audit trail
* Query filtering for soft-deleted items
* RESTClient integration for external soft deletes

## REST Service Architecture

### **Complete Communication Flow Pattern**

```
External System → RESTClient → Request DTO → Mapping → Internal DTO → Controller → Service → Domain → Database
                ↑                                                                                    ↓
External System ← RESTClient ← Response DTO ← Mapping ← Internal DTO ← Controller ← Service ← Domain ← Database
```

### **Internal Flow Pattern (Write Operations)**

```
HTTP Request → Controller → Service → PreBus Plugins → Command Handler → Domain Model → Database → Event Publishing → Subscribers
```

### **Internal Flow Pattern (Read Operations)**

```
HTTP Request → Controller → Service → Query Handler → Database → AutoMapper → Response
```

### **External Communication Pattern**

```
Internal DTO → Mapping → Request DTO → RESTClient → External System
External System → RESTClient → Response DTO → Mapping → Internal DTO
```

## Key Components

### **Controllers**

* API entry points with HTTP method attributes
* Parameter binding and validation
* Response type declarations
* Error handling and status codes

### **Services**

* Business orchestration layer
* PreBus processing for validation
* Command/Query resolution
* Result processing
* RESTClient integration

### **RESTClients**

* External system communication
* HTTP client management
* Request/Response serialization
* Error handling and resilience
* Retry policies and circuit breakers

### **Request/Response DTOs**

* External system contracts
* Serialization/Deserialization
* External validation rules
* Version management

### **Internal DTOs**

* Application contracts
* Business validation rules
* FlexBase integration
* Internal data structures

### **Mapping Layer**

* DTO to Request/Response transformation
* Field mapping and conversion
* Validation rule translation
* Contract versioning

### **PreBus System**

* Plugin-based validation pipeline
* Business rule sequences
* Data packet context
* Error collection and reporting

### **Command Handlers**

* Data processing for write operations
* Domain model interaction
* Database persistence
* Event publishing
* RESTClient integration

### **Query Handlers**

* Data retrieval for read operations
* Database query building
* AutoMapper integration
* Result transformation
* RESTClient integration

### **Domain Models**

* Business logic implementation
* State management
* Data validation
* Business rules

### **Event System**

* Asynchronous processing
* Event publishing
* Subscriber processing
* Side effects handling

## HTTP Methods and Use Cases

| HTTP Method | Use Case               | Example               | Response               |
| ----------- | ---------------------- | --------------------- | ---------------------- |
| **POST**    | Create new entity      | `AddToShipping`       | 201 Created            |
| **PUT**     | Update existing entity | `UpdateShipping`      | 200 OK                 |
| **GET**     | Retrieve data          | `GetShippingInfoById` | 200 OK / 404 Not Found |
| **DELETE**  | Remove entity          | `DeleteShipping`      | 200 OK                 |

## Response Patterns

### **Success Responses**

* **201 Created**: New entity created successfully
* **200 OK**: Operation completed successfully
* **200 OK with Data**: Query operations with results

### **Error Responses**

* **400 Bad Request**: Invalid parameters or validation errors
* **404 Not Found**: Entity not found (for GET operations)
* **500 Internal Server Error**: Server or database errors

## Data Transfer Objects (DTOs)

### **Input DTOs**

* Request body parameters for POST/PUT operations
* Query parameters for GET operations
* URL parameters for DELETE operations

### **Output DTOs**

* Response data for successful operations
* Error information for failed operations
* Pagination metadata for paged results

## Best Practices

### **Controller Design**

* Use appropriate HTTP methods
* Declare response types
* Handle errors gracefully
* Validate input parameters

### **Service Layer**

* Keep business logic in services
* Use PreBus for validation
* Handle command/query resolution
* Process results appropriately

### **Query Operations**

* Use appropriate query base classes
* Implement efficient query building
* Apply proper filtering
* Use AutoMapper for transformations

### **Command Operations**

* Validate business rules
* Handle domain logic
* Publish events appropriately
* Log operations

### **Error Handling**

* Use appropriate HTTP status codes
* Provide meaningful error messages
* Log errors appropriately
* Handle exceptions gracefully

## Performance Considerations

### **Query Optimization**

* Use database indexes effectively
* Implement efficient query building
* Apply appropriate filtering
* Use pagination for large datasets

### **Command Optimization**

* Validate early in the pipeline
* Use efficient database operations
* Implement proper logging
* Handle events asynchronously

### **Caching Strategies**

* Cache frequently accessed data
* Use appropriate cache keys
* Implement cache invalidation
* Consider cache warming

## Security Considerations

### **Input Validation**

* Validate all input parameters
* Use PreBus for business rule validation
* Sanitize user input
* Implement proper authorization

### **Data Protection**

* Use appropriate DTOs
* Implement data masking
* Handle sensitive data carefully
* Follow security best practices

## Testing Strategies

### **Unit Testing**

* Test each component independently
* Mock dependencies appropriately
* Test error scenarios
* Verify business logic

### **Integration Testing**

* Test complete flows
* Verify database operations
* Test event publishing
* Validate error handling

### **API Testing**

* Test HTTP endpoints
* Verify response formats
* Test error scenarios
* Validate security

***

**This REST Services documentation provides comprehensive guidance for implementing clean, maintainable, and scalable REST operations in FlexBase applications!** 🚀


# Insert Example

## Overview

This document demonstrates the complete **Insert flow** using the **AddToShipping** feature from the EBusiness application. The flow starts with a POST request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
POST Request → Controller → Service → PreBus Plugins → Command Handler → RESTClient → External System
                                                                                    ↓
Response ← Controller ← Service ← Command Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. POST Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── AddToShippingSequence (Plugin Registration)
   ├── AddToShippingDataPacket (Validation Context)
   └── ValidateShipping Plugin (Business Rules)
   ↓
5. Command Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO Processing
   ↓
6. Event Publishing (Asynchronous Processing)
   ↓
7. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_AddToShipping.cs`

```csharp
[HttpPost]
[Route("AddToShipping")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 201)]
public async Task<IActionResult> AddToShipping([FromBody]AddToShippingDto dto)
{
    return await RunService(201, dto, _processShippingService.AddToShipping);
}
```

**What Happens:**

* **HTTP Method**: `POST /api/Shipping/AddToShipping`
* **Input**: `AddToShippingDto` from request body
* **Action**: Calls the service layer to process the shipping
* **Response**: HTTP 201 Created with shipping ID

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_AddToShipping.cs`

```csharp
public async Task<CommandResult> AddToShipping(AddToShippingDto dto)
{
    var packet = await ProcessBusinessRuleSequence<AddToShippingDataPacket, AddToShippingSequence, AddToShippingDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        AddToShippingCommand cmd = new AddToShippingCommand
        {
             Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        AddToShippingResultModel outputResult = new AddToShippingResultModel();
        outputResult.Id = dto.GetGeneratedId();
        cmdResult.result = outputResult;

        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique shipping ID
* **Command Creation**: Creates `AddToShippingCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success with generated shipping ID

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `AddToShippingSequence.cs`

```csharp
public class AddToShippingSequence : FlexiBusinessRuleSequenceBase<AddToShippingDataPacket>
{
    public AddToShippingSequence()
    {
        this.Add<ValidateShipping>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `AddToShippingDataPacket.cs`

```csharp
public partial class AddToShippingDataPacket : FlexiFlowDataPacketWithDtoBridge<AddToShippingDto, FlexAppContextBridge>
{
    protected readonly ILogger<AddToShippingDataPacket> _logger;

    public AddToShippingDataPacket(ILogger<AddToShippingDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `ValidateShipping.cs`

```csharp
public partial class ValidateShipping : FlexiBusinessRuleBase, IFlexiBusinessRule<AddToShippingDataPacket>
{
    public override string Id { get; set; } = "3a1cd0401f931dd4a01587e229b720dc";
    public override string FriendlyName { get; set; } = "ValidateShipping";

    protected readonly ILogger<ValidateShipping> _logger;
    protected readonly RepoFactory _repoFactory;

    public ValidateShipping(ILogger<ValidateShipping> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(AddToShippingDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 2.4. **PreBus Plugin Benefits**

* **Modular Validation**: Each plugin handles one validation concern
* **Reusable Rules**: Plugins can be reused across different features
* **Testable**: Each plugin can be unit tested independently
* **Configurable**: Plugins can be enabled/disabled per feature
* **Extensible**: Easy to add new validation rules
* **Ordered Execution**: Plugins execute in defined sequence

### 3. **Command Handler** - RESTClient Integration

**File**: `AddToShippingHandler.cs`

```csharp
public partial class AddToShippingHandler : IAddToShippingHandler
{
    protected string EventCondition = "";
    protected readonly ILogger<AddToShippingHandler> _logger;
    protected readonly IFlexHost _flexHost;
    protected ShippingRESTClient _restClient;
    protected FlexAppContextBridge? _flexAppContext;

    public AddToShippingHandler(ILogger<AddToShippingHandler> logger, IFlexHost flexHost, ShippingRESTClient restClient)
    {
        _logger = logger;
        _flexHost = flexHost;
        _restClient = restClient;
    }

    public virtual async Task Execute(AddToShippingCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Convert internal DTO to Request DTO
        AddToShippingRequestDto requestParams = new AddToShippingRequestDto
        {
            OrderId = cmd.Dto.OrderId,
            ShippingAddress = cmd.Dto.ShippingAddress,
            TrackingNumber = cmd.Dto.TrackingNumber,
            TotalWeight = cmd.Dto.ShippingItems?.Sum(x => x.Weight) ?? 0,
            ShippingItems = cmd.Dto.ShippingItems?.Select(x => new ShippingItemRequestDto
            {
                ProductId = x.ProductId,
                Quantity = x.Qty,
                Weight = x.Weight,
                Volume = x.Volume
            }).ToList()
        };

        // Call external REST service
        var response = await _restClient.AddToShipping(requestParams);

        // Process response
        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            var responseDto = JsonConvert.DeserializeObject<AddToShippingResponseDto>(responseContent);
            
            _logger.LogDebug("Shipping created successfully with external ID: {ExternalId}", responseDto?.Id);
            
            // Set success condition for event firing
            EventCondition = "CONDITION_ONSUCCESS";
        }
        else
        {
            _logger.LogError("Failed to create shipping. Status: {StatusCode}", response.StatusCode);
            EventCondition = "CONDITION_ONFAILED";
        }

        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **DTO Mapping**: Converts internal DTO to Request DTO for external system
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Processing**: Handles success/failure responses from external system
* **Logging**: Logs success/failure of external service call
* **Event Publishing**: Fires events based on external service result

### 4. **NServiceBus Handler** - Message Processing

**File**: `AddToShippingNsbHandler.cs`

```csharp
public class AddToShippingNsbHandler : NsbCommandHandler<AddToShippingCommand>
{
    readonly ILogger<AddToShippingNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IAddToShippingHandler _handler;

    public AddToShippingNsbHandler(ILogger<AddToShippingNsbHandler> logger, IFlexHost flexHost, IAddToShippingHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(AddToShippingCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(AddToShippingNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `AddToShippingCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ShippingAddedEvent`

```csharp
public class ShippingAddedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with shipping data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **RESTClient Integration** - External Communication

**File**: `ShippingRESTClient_AddToShipping.cs`

```csharp
public async Task<HttpResponseMessage> AddToShipping(AddToShippingRequestDto model)
{
    var httpClient = _httpClientFactory.CreateClient(ShippingServicesRESTClientMaster.Name);

    var serializedModel = JsonConvert.SerializeObject(model);

    var request = new HttpRequestMessage(
           HttpMethod.Post,
           $"yourUri");
    request.Content = new StringContent(serializedModel, Encoding.UTF8, "application/json");
    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

    return await response.HandleHttpResponse();
}
```

**What Happens:**

* **HTTP Client**: Creates HTTP client for external communication
* **Serialization**: Converts Request DTO to JSON
* **HTTP Request**: Sends POST to external shipping system
* **Response Handling**: Processes HTTP response from external system

### 7.1. **Request DTO** - External Contract

**File**: `AddToShippingRequestDto.cs`

```csharp
public partial class AddToShippingRequestDto
{
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public decimal TotalWeight { get; set; }
    public ICollection<ShippingItemRequestDto> ShippingItems { get; set; }
}
```

**What Happens:**

* **External Contract**: Designed for external system consumption
* **Serialization**: Optimized for JSON serialization
* **Validation**: May include external system specific validation

### 7.2. **Response DTO** - External Contract

**File**: `AddToShippingResponseDto.cs`

```csharp
public partial class AddToShippingResponseDto
{
    public string Id { get; set; }
    public string Status { get; set; }
    public string Message { get; set; }
    public DateTime ProcessedDate { get; set; }
    public string ExternalReferenceId { get; set; }
}
```

**What Happens:**

* **External Contract**: Designed for external system responses
* **Deserialization**: Optimized for JSON deserialization
* **External Fields**: May include external system specific fields

### 7.3. **Mapping Configuration** - DTO Transformation

**File**: `ShippingRESTClientMapperProfile.cs`

```csharp
public class ShippingRESTClientMapperProfile : Profile
{
    public ShippingRESTClientMapperProfile()
    {
        // Internal DTO → Request DTO Mapping
        CreateMap<AddToShippingDto, AddToShippingRequestDto>()
            .ForMember(d => d.TotalWeight, opt => opt.MapFrom(s => s.ShippingItems.Sum(x => x.Weight)))
            .ForMember(d => d.ShippingItems, opt => opt.MapFrom(s => s.ShippingItems));
            
        // Response DTO → Internal DTO Mapping
        CreateMap<AddToShippingResponseDto, AddToShippingDto>()
            .ForMember(d => d.Status, opt => opt.MapFrom(s => ParseStatus(s.Status)))
            .ForMember(d => d.ExternalReferenceId, opt => opt.MapFrom(s => s.ExternalReferenceId));
    }
    
    private ShippingStatus ParseStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Request Mapping**: Converts internal DTO to external request format
* **Response Mapping**: Converts external response to internal DTO format
* **Field Transformation**: Handles different field names and types
* **Business Logic**: Applies business rules during mapping

### 8. **Event Subscribers** - Side Effects

**File**: `NotifyLogisticsOnShippingAdded.cs`

```csharp
public partial class NotifyLogisticsOnShippingAdded : INotifyLogisticsOnShippingAdded
{
    protected readonly ILogger<NotifyLogisticsOnShippingAdded> _logger;
    protected string EventCondition = "";

    public NotifyLogisticsOnShippingAdded(ILogger<NotifyLogisticsOnShippingAdded> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ShippingAddedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Send shipping confirmation email
        // - Update inventory levels
        // - Notify logistics system
        // - Update tracking information

        await this.Fire<NotifyLogisticsOnShippingAdded>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ShippingAddedEvent` from message bus
* **Side Effects**: Executes business logic (emails, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Internal DTOs** - Application Contracts

#### **Input DTO**: `AddToShippingDto`

```csharp
public partial class AddToShippingDto : DtoBridge 
{
    [StringLength(100)]
    public string OrderId { get; set; }

    [StringLength(200)]
    public string ShippingAddress { get; set; }

    public ICollection<AddToShippingDto_ShippingItem> ShippingItems { get; set; }
}
```

#### **Command**: `AddToShippingCommand`

```csharp
public class AddToShippingCommand : FlexCommandBridge<AddToShippingDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

### **External DTOs** - External System Contracts

#### **Request DTO**: `AddToShippingRequestDto`

```csharp
public partial class AddToShippingRequestDto
{
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public decimal TotalWeight { get; set; }
    public ICollection<ShippingItemRequestDto> ShippingItems { get; set; }
}
```

#### **Response DTO**: `AddToShippingResponseDto`

```csharp
public partial class AddToShippingResponseDto
{
    public string Id { get; set; }
    public string Status { get; set; }
    public string Message { get; set; }
    public DateTime ProcessedDate { get; set; }
    public string ExternalReferenceId { get; set; }
}
```

### **DTO Mapping Relationships**

```
Internal DTO (AddToShippingDto) ←→ Request DTO (AddToShippingRequestDto)
     ↑                                    ↓
     │                              External System
     │                                    ↓
     └── Response DTO (AddToShippingResponseDto) ←┘
```

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **POST Request** → Controller receives request
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → RESTClient integration
   * Internal DTO → Request DTO mapping
   * External system API call
   * Response DTO processing
5. **Response** → HTTP 201 with shipping ID

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ShippingAddedEvent published to message bus
2. **Subscriber Processing** → NotifyLogisticsOnShippingAdded executes
3. **Side Effects** → Emails, notifications, inventory updates
4. **Additional Events** → Can trigger more business processes

### **External Communication Flow**

1. **Internal DTO** → Request DTO mapping
2. **RESTClient Call** → HTTP request to external system
3. **External Response** → Response DTO from external system
4. **Response Mapping** → Response DTO to Internal DTO
5. **Data Integration** → External data integrated with internal data

## Key Benefits

* **Separation of Concerns**: Each layer has a single responsibility
* **Testability**: Each component can be tested independently
* **Scalability**: Asynchronous processing handles high loads
* **Maintainability**: Clear, readable code structure
* **Event-Driven**: Loose coupling between components

***

**This AddToShipping example demonstrates how FlexBase enables clean, maintainable, and scalable insert operations with proper separation of concerns and event-driven architecture!** 🚀


# Update Example

## Overview

This document demonstrates the complete **Update flow** using the **UpdateShipping** feature from the EBusiness application. The flow starts with a PUT request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
PUT Request → Controller → Service → PreBus Plugins → Command Handler → RESTClient → External System
                                                                                    ↓
Response ← Controller ← Service ← Command Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. PUT Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── UpdateShippingSequence (Plugin Registration)
   ├── UpdateShippingDataPacket (Validation Context)
   └── IsValidShipping Plugin (Business Rules)
   ↓
5. Command Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO Processing
   ↓
6. Event Publishing (Asynchronous Processing)
   ↓
7. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_UpdateShipping.cs`

```csharp
[HttpPut]
[Route("UpdateShipping")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 200)]
public async Task<IActionResult> UpdateShipping([FromBody]UpdateShippingDto dto)
{
    return await RunService(200, dto, _processShippingService.UpdateShipping);
}
```

**What Happens:**

* **HTTP Method**: `PUT /api/Shipping/UpdateShipping`
* **Input**: `UpdateShippingDto` from request body
* **Action**: Calls the service layer to process the shipping update
* **Response**: HTTP 200 OK with success status

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_UpdateShipping.cs`

```csharp
public async Task<CommandResult> UpdateShipping(UpdateShippingDto dto)
{
    var packet = await ProcessBusinessRuleSequence<UpdateShippingDataPacket, UpdateShippingSequence, UpdateShippingDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        UpdateShippingCommand cmd = new UpdateShippingCommand
        {
            Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        UpdateShippingResultModel outputResult = new UpdateShippingResultModel();
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `UpdateShippingCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success status

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `UpdateShippingSequence.cs`

```csharp
public class UpdateShippingSequence : FlexiBusinessRuleSequenceBase<UpdateShippingDataPacket>
{
    public UpdateShippingSequence()
    {
        this.Add<IsValidShipping>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `UpdateShippingDataPacket.cs`

```csharp
public partial class UpdateShippingDataPacket : FlexiFlowDataPacketWithDtoBridge<UpdateShippingDto, FlexAppContextBridge>
{
    protected readonly ILogger<UpdateShippingDataPacket> _logger;

    public UpdateShippingDataPacket(ILogger<UpdateShippingDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `IsValidShipping.cs`

```csharp
public partial class IsValidShipping : FlexiBusinessRuleBase, IFlexiBusinessRule<UpdateShippingDataPacket>
{
    public override string Id { get; set; } = "3a1cd500a49d178e88f75ed6bccaed88";
    public override string FriendlyName { get; set; } = "IsValidShipping";

    protected readonly ILogger<IsValidShipping> _logger;
    protected readonly RepoFactory _repoFactory;

    public IsValidShipping(ILogger<IsValidShipping> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(UpdateShippingDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 3. **Command Handler** - RESTClient Integration

**File**: `UpdateShippingHandler.cs`

```csharp
public partial class UpdateShippingHandler : IUpdateShippingHandler
{
    protected string EventCondition = "";
    protected readonly ILogger<UpdateShippingHandler> _logger;
    protected readonly IFlexHost _flexHost;
    protected ShippingRESTClient _restClient;
    protected FlexAppContextBridge? _flexAppContext;

    public UpdateShippingHandler(ILogger<UpdateShippingHandler> logger, IFlexHost flexHost, ShippingRESTClient restClient)
    {
        _logger = logger;
        _flexHost = flexHost;
        _restClient = restClient;
    }

    public virtual async Task Execute(UpdateShippingCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Convert internal DTO to Request DTO
        UpdateShippingRequestDto requestParams = new UpdateShippingRequestDto
        {
            Id = cmd.Dto.Id,
            ShippingAddress = cmd.Dto.ShippingAddress,
            TrackingNumber = cmd.Dto.TrackingNumber,
            Status = cmd.Dto.Status.ToString(),
            TotalWeight = cmd.Dto.ShippingItems?.Sum(x => x.Weight) ?? 0,
            ShippingItems = cmd.Dto.ShippingItems?.Select(x => new ShippingItemRequestDto
            {
                ProductId = x.ProductId,
                Quantity = x.Qty,
                Weight = x.Weight,
                Volume = x.Volume
            }).ToList()
        };

        // Call external REST service
        var response = await _restClient.UpdateShipping(requestParams);

        // Process response
        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            var responseDto = JsonConvert.DeserializeObject<UpdateShippingResponseDto>(responseContent);
            
            _logger.LogDebug("Shipping updated successfully with external ID: {ExternalId}", responseDto?.Id);
            
            // Set success condition for event firing
            EventCondition = "CONDITION_ONSUCCESS";
        }
        else
        {
            _logger.LogError("Failed to update shipping. Status: {StatusCode}", response.StatusCode);
            EventCondition = "CONDITION_ONFAILED";
        }

        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **DTO Mapping**: Converts internal DTO to Request DTO for external system
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Processing**: Handles success/failure responses from external system
* **Logging**: Logs success/failure of external service call
* **Event Publishing**: Fires events based on external service result

### 4. **Domain Model** - Business Logic

**File**: `Shipping/UpdateShipping.cs`

```csharp
public virtual Shipping UpdateShipping(UpdateShippingCommand cmd)
{
    Guard.AgainstNull("Shipping model cannot be empty", cmd);

    this.Convert(cmd.Dto);
    this.LastModifiedBy = cmd.Dto.GetAppContext()?.UserId;

    //Map any other field not handled by Automapper config

    this.SetModified();

    //Set your appropriate SetModified for the inner object here

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **Data Mapping**: Converts DTO to domain model
* **Audit Fields**: Sets last modified by user
* **State Management**: Marks entity as modified
* **Child Objects**: Processes child object updates

### 5. **NServiceBus Handler** - Message Processing

**File**: `UpdateShippingNsbHandler.cs`

```csharp
public class UpdateShippingNsbHandler : NsbCommandHandler<UpdateShippingCommand>
{
    readonly ILogger<UpdateShippingNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IUpdateShippingHandler _handler;

    public UpdateShippingNsbHandler(ILogger<UpdateShippingNsbHandler> logger, IFlexHost flexHost, IUpdateShippingHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(UpdateShippingCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(UpdateShippingNsbHandler)}");

        await _handler.Execute(message, new NSbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `UpdateShippingCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ShippingUpdatedEvent`

```csharp
public class ShippingUpdatedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with shipping data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `UpdateLogisticsOnUpdateShipping.cs`

```csharp
public partial class UpdateLogisticsOnUpdateShipping : IUpdateLogisticsOnUpdateShipping
{
    protected readonly ILogger<UpdateLogisticsOnUpdateShipping> _logger;
    protected string EventCondition = "";

    public UpdateLogisticsOnUpdateShipping(ILogger<UpdateLogisticsOnUpdateShipping> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ShippingUpdatedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Notify logistics of shipping changes
        // - Update tracking information
        // - Send update notifications
        // - Update analytics

        await this.Fire<UpdateLogisticsOnUpdateShipping>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ShippingUpdatedEvent` from message bus
* **Side Effects**: Executes business logic (notifications, tracking updates, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `UpdateShippingDto`

```csharp
public partial class UpdateShippingDto : DtoBridge 
{
    public string Id { get; set; }
    
    [StringLength(200)]
    public string ShippingAddress { get; set; }

    public string TrackingNumber { get; set; }
    
    public ShippingStatus Status { get; set; }
}
```

### **Command**: `UpdateShippingCommand`

```csharp
public class UpdateShippingCommand : FlexCommandBridge<UpdateShippingDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Key Differences from Insert Flow

### **Update-Specific Characteristics**

1. **Entity Lookup**: Must find existing entity before updating
2. **Null Check**: Validates entity exists before processing
3. **State Management**: Uses `SetModified()` instead of `SetAdded()`
4. **Audit Fields**: Updates `LastModifiedBy` instead of `CreatedBy`
5. **HTTP Method**: Uses `PUT` instead of `POST`
6. **Response Code**: Returns `200 OK` instead of `201 Created`

### **PreBus Validation Focus**

* **IsValidShipping**: Validates shipping exists and is in updatable state
* **Business Rules**: Ensures shipping can be modified (not delivered, not cancelled)
* **Data Integrity**: Validates update doesn't violate business constraints

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **PUT Request** → Controller receives request
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Entity lookup and data processing
5. **Domain Logic** → Business rules and state management
6. **Response** → HTTP 200 OK with success status

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ShippingUpdatedEvent published to message bus
2. **Subscriber Processing** → UpdateLogisticsOnUpdateShipping executes
3. **Side Effects** → Logistics notifications, tracking updates, analytics

## Key Benefits

* **Data Integrity**: Ensures entity exists before updating
* **Audit Trail**: Tracks who made changes and when
* **Business Rules**: Validates update is allowed
* **Event-Driven**: Notifies other systems of changes
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This UpdateShipping example demonstrates how FlexBase enables clean, maintainable, and scalable update operations with proper validation, audit trails, and event-driven architecture!** 🚀


# Delete Example

## Overview

This document demonstrates the complete **Delete flow** using the **DeleteShipping** feature from the EBusiness application. The flow starts with a DELETE request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
DELETE Request → Controller → Service → PreBus Plugins → Command Handler → RESTClient → External System
                                                                                    ↓
Response ← Controller ← Service ← Command Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. DELETE Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── DeleteShippingSequence (Plugin Registration)
   ├── DeleteShippingDataPacket (Validation Context)
   └── IsValidShipping Plugin (Business Rules)
   ↓
5. Command Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO Processing
   ↓
6. Event Publishing (Asynchronous Processing)
   ↓
7. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_DeleteShipping.cs`

```csharp
[HttpDelete()]
[Route("DeleteShipping/{id}")]
public async Task<IActionResult> DeleteShipping(string id)
{
    DeleteShippingDto dto = new DeleteShippingDto();
    dto.Id = id;
    return await RunService(200, dto, _processShippingService.DeleteShipping);
}
```

**What Happens:**

* **HTTP Method**: `DELETE /api/Shipping/DeleteShipping/{id}`
* **Input**: Shipping ID from URL parameter
* **DTO Creation**: Creates `DeleteShippingDto` with the ID
* **Action**: Calls the service layer to process the shipping deletion
* **Response**: HTTP 200 OK with success status

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_DeleteShipping.cs`

```csharp
public async Task<CommandResult> DeleteShipping(DeleteShippingDto dto)
{
    var packet = await ProcessBusinessRuleSequence<DeleteShippingDataPacket, DeleteShippingSequence, DeleteShippingDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        DeleteShippingCommand cmd = new DeleteShippingCommand
        {
            Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        DeleteShippingResultModel outputResult = new DeleteShippingResultModel();
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `DeleteShippingCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success status

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `DeleteShippingSequence.cs`

```csharp
public class DeleteShippingSequence : FlexiBusinessRuleSequenceBase<DeleteShippingDataPacket>
{
    public DeleteShippingSequence()
    {
        this.Add<IsValidShipping>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `DeleteShippingDataPacket.cs`

```csharp
public partial class DeleteShippingDataPacket : FlexiFlowDataPacketWithDtoBridge<DeleteShippingDto, FlexAppContextBridge>
{
    protected readonly ILogger<DeleteShippingDataPacket> _logger;

    public DeleteShippingDataPacket(ILogger<DeleteShippingDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `IsValidShipping.cs`

```csharp
public partial class IsValidShipping : FlexiBusinessRuleBase, IFlexiBusinessRule<DeleteShippingDataPacket>
{
    public override string Id { get; set; } = "3a1cd5b1fa98b4c63378de9607706082";
    public override string FriendlyName { get; set; } = "IsValidShipping";

    protected readonly ILogger<IsValidShipping> _logger;
    protected readonly RepoFactory _repoFactory;

    public IsValidShipping(ILogger<IsValidShipping> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(DeleteShippingDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 3. **Command Handler** - RESTClient Integration

**File**: `DeleteShippingHandler.cs`

```csharp
public partial class DeleteShippingHandler : IDeleteShippingHandler
{
    protected string EventCondition = "";
    protected readonly ILogger<DeleteShippingHandler> _logger;
    protected readonly IFlexHost _flexHost;
    protected ShippingRESTClient _restClient;
    protected FlexAppContextBridge? _flexAppContext;

    public DeleteShippingHandler(ILogger<DeleteShippingHandler> logger, IFlexHost flexHost, ShippingRESTClient restClient)
    {
        _logger = logger;
        _flexHost = flexHost;
        _restClient = restClient;
    }

    public virtual async Task Execute(DeleteShippingCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Convert internal DTO to Request DTO
        DeleteShippingRequestDto requestParams = new DeleteShippingRequestDto
        {
            Id = cmd.Dto.Id,
            DeletionReason = cmd.Dto.DeletionReason ?? "User requested deletion"
        };

        // Call external REST service
        var response = await _restClient.DeleteShipping(requestParams);

        // Process response
        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            var responseDto = JsonConvert.DeserializeObject<DeleteShippingResponseDto>(responseContent);
            
            _logger.LogDebug("Shipping deleted successfully with external ID: {ExternalId}", responseDto?.Id);
            
            // Set success condition for event firing
            EventCondition = "CONDITION_ONSUCCESS";
        }
        else
        {
            _logger.LogError("Failed to delete shipping. Status: {StatusCode}", response.StatusCode);
            EventCondition = "CONDITION_ONFAILED";
        }

        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **DTO Mapping**: Converts internal DTO to Request DTO for external system
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Processing**: Handles success/failure responses from external system
* **Logging**: Logs success/failure of external service call
* **Event Publishing**: Fires events based on external service result

### 4. **Domain Model** - Business Logic

**File**: `Shipping/DeleteShipping.cs`

```csharp
public virtual Shipping DeleteShipping(DeleteShippingCommand cmd)
{
    Guard.AgainstNull("Shipping model cannot be empty", cmd);

    this.Id = cmd.Dto.Id;
    this.SetDeleted();

    //Set your appropriate SetDeleted for the inner object here

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **ID Assignment**: Sets the shipping ID from DTO
* **State Management**: Marks entity as deleted (soft delete)
* **Child Objects**: Processes child object deletions

### 5. **NServiceBus Handler** - Message Processing

**File**: `DeleteShippingNsbHandler.cs`

```csharp
public class DeleteShippingNsbHandler : NsbCommandHandler<DeleteShippingCommand>
{
    readonly ILogger<DeleteShippingNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IDeleteShippingHandler _handler;

    public DeleteShippingNsbHandler(ILogger<DeleteShippingNsbHandler> logger, IFlexHost flexHost, IDeleteShippingHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(DeleteShippingCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(DeleteShippingNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `DeleteShippingCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ShippingDeletedEvent` (if implemented)

```csharp
public class ShippingDeletedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with shipping data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `NotifyLogisticsOnShippingDeleted.cs` (if implemented)

```csharp
public partial class NotifyLogisticsOnShippingDeleted : INotifyLogisticsOnShippingDeleted
{
    protected readonly ILogger<NotifyLogisticsOnShippingDeleted> _logger;
    protected string EventCondition = "";

    public NotifyLogisticsOnShippingDeleted(ILogger<NotifyLogisticsOnShippingDeleted> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ShippingDeletedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Update logistics systems
        // - Notify carriers
        // - Update analytics
        // - Archive related data

        await this.Fire<NotifyLogisticsOnShippingDeleted>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ShippingDeletedEvent` from message bus
* **Side Effects**: Executes business logic (logistics updates, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `DeleteShippingDto`

```csharp
public partial class DeleteShippingDto : DtoBridge 
{
    public string Id { get; set; }
}
```

### **Command**: `DeleteShippingCommand`

```csharp
public class DeleteShippingCommand : FlexCommandBridge<DeleteShippingDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Key Differences from Insert/Update Flow

### **Delete-Specific Characteristics**

1. **URL Parameter**: ID comes from URL path instead of request body
2. **DTO Creation**: Controller creates DTO with ID from URL
3. **Soft Delete**: Uses `SetDeleted()` instead of `SetAdded()` or `SetModified()`
4. **State Management**: Marks entity as deleted (soft delete pattern)
5. **HTTP Method**: Uses `DELETE` instead of `POST` or `PUT`
6. **Minimal Data**: Only requires ID for deletion

### **PreBus Validation Focus**

* **IsValidShipping**: Validates shipping exists and can be deleted
* **Business Rules**: Ensures shipping can be removed (not delivered, not in transit)
* **Data Integrity**: Validates deletion doesn't violate business constraints

### **Soft Delete Pattern**

* **Database**: Entity is marked as deleted, not physically removed
* **Queries**: Soft-deleted entities are filtered out of normal queries
* **Recovery**: Deleted entities can be restored if needed
* **Audit Trail**: Maintains complete history of deletions

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **DELETE Request** → Controller receives request with ID
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Data processing and soft delete
5. **Domain Logic** → Business rules and state management
6. **Response** → HTTP 200 OK with success status

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ShippingDeletedEvent published to message bus
2. **Subscriber Processing** → NotifyLogisticsOnShippingDeleted executes
3. **Side Effects** → Logistics updates, carrier notifications, analytics

## Key Benefits

* **Data Safety**: Soft delete preserves data for recovery
* **Business Rules**: Validates deletion is allowed
* **Audit Trail**: Tracks who deleted what and when
* **Event-Driven**: Notifies other systems of deletions
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This DeleteShipping example demonstrates how FlexBase enables clean, maintainable, and scalable delete operations with proper validation, soft delete patterns, and event-driven architecture!** 🚀


# Soft Delete Example

## Overview

This document demonstrates the complete **Soft Delete flow** using the **SoftDeleteShipping** feature from the EBusiness application. The flow starts with a DELETE request to the controller and ends with event publishing and subscriber processing. Soft delete marks the entity as deleted without physically removing it from the database.

## Complete Flow Architecture

```
DELETE Request → Controller → Service → PreBus Plugins → Command Handler → RESTClient → External System
                                                                                    ↓
Response ← Controller ← Service ← Command Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. DELETE Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── SoftDeleteShippingSequence (Plugin Registration)
   ├── SoftDeleteShippingDataPacket (Validation Context)
   └── IsValidShippingForSoftDelete Plugin (Business Rules)
   ↓
5. Command Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO Processing
   ↓
6. Event Publishing (Asynchronous Processing)
   ↓
7. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_SoftDeleteShipping.cs`

```csharp
[HttpDelete()]
[Route("SoftDeleteShipping/{id}")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 200)]
public async Task<IActionResult> SoftDeleteShipping(string id)
{
    SoftDeleteShippingDto dto = new SoftDeleteShippingDto();
    dto.Id = id;
    return await RunService(200, dto, _processShippingService.SoftDeleteShipping);
}
```

**What Happens:**

* **HTTP Method**: `DELETE /api/Shipping/SoftDeleteShipping/{id}`
* **Input**: Shipping ID from URL parameter
* **DTO Creation**: Creates `SoftDeleteShippingDto` with the ID
* **Action**: Calls the service layer to process the soft delete
* **Response**: HTTP 200 OK with success status

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_SoftDeleteShipping.cs`

```csharp
public async Task<CommandResult> SoftDeleteShipping(SoftDeleteShippingDto dto)
{
    var packet = await ProcessBusinessRuleSequence<SoftDeleteShippingDataPacket, SoftDeleteShippingSequence, SoftDeleteShippingDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        SoftDeleteShippingCommand cmd = new SoftDeleteShippingCommand
        {
            Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        SoftDeleteShippingResultModel outputResult = new SoftDeleteShippingResultModel();
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `SoftDeleteShippingCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success status

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `SoftDeleteShippingSequence.cs`

```csharp
public class SoftDeleteShippingSequence : FlexiBusinessRuleSequenceBase<SoftDeleteShippingDataPacket>
{
    public SoftDeleteShippingSequence()
    {
        this.Add<IsValidShippingForSoftDelete>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `SoftDeleteShippingDataPacket.cs`

```csharp
public partial class SoftDeleteShippingDataPacket : FlexiFlowDataPacketWithDtoBridge<SoftDeleteShippingDto, FlexAppContextBridge>
{
    protected readonly ILogger<SoftDeleteShippingDataPacket> _logger;

    public SoftDeleteShippingDataPacket(ILogger<SoftDeleteShippingDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `IsValidShippingForSoftDelete.cs`

```csharp
public partial class IsValidShippingForSoftDelete : FlexiBusinessRuleBase, IFlexiBusinessRule<SoftDeleteShippingDataPacket>
{
    public override string Id { get; set; } = "3a1cd5b1fa98b4c63378de9607706082";
    public override string FriendlyName { get; set; } = "IsValidShippingForSoftDelete";

    protected readonly ILogger<IsValidShippingForSoftDelete> _logger;
    protected readonly RepoFactory _repoFactory;

    public IsValidShippingForSoftDelete(ILogger<IsValidShippingForSoftDelete> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(SoftDeleteShippingDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 3. **Command Handler** - RESTClient Integration

**File**: `SoftDeleteShippingHandler.cs`

```csharp
public partial class SoftDeleteShippingHandler : ISoftDeleteShippingHandler
{
    protected string EventCondition = "";
    protected readonly ILogger<SoftDeleteShippingHandler> _logger;
    protected readonly IFlexHost _flexHost;
    protected ShippingRESTClient _restClient;
    protected FlexAppContextBridge? _flexAppContext;

    public SoftDeleteShippingHandler(ILogger<SoftDeleteShippingHandler> logger, IFlexHost flexHost, ShippingRESTClient restClient)
    {
        _logger = logger;
        _flexHost = flexHost;
        _restClient = restClient;
    }

    public virtual async Task Execute(SoftDeleteShippingCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Convert internal DTO to Request DTO
        SoftDeleteShippingRequestDto requestParams = new SoftDeleteShippingRequestDto
        {
            Id = cmd.Dto.Id,
            DeletionReason = cmd.Dto.DeletionReason ?? "User requested soft deletion",
            SoftDeleteFlag = true
        };

        // Call external REST service
        var response = await _restClient.SoftDeleteShipping(requestParams);

        // Process response
        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            var responseDto = JsonConvert.DeserializeObject<SoftDeleteShippingResponseDto>(responseContent);
            
            _logger.LogDebug("Shipping soft deleted successfully with external ID: {ExternalId}", responseDto?.Id);
            
            // Set success condition for event firing
            EventCondition = "CONDITION_ONSUCCESS";
        }
        else
        {
            _logger.LogError("Failed to soft delete shipping. Status: {StatusCode}", response.StatusCode);
            EventCondition = "CONDITION_ONFAILED";
        }

        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **DTO Mapping**: Converts internal DTO to Request DTO for external system
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Processing**: Handles success/failure responses from external system
* **Logging**: Logs success/failure of external service call
* **Event Publishing**: Fires events based on external service result

### 4. **Domain Model** - Business Logic

**File**: `Shipping/SoftDeleteShipping.cs`

```csharp
public virtual Shipping SoftDeleteShipping(SoftDeleteShippingCommand cmd)
{
    Guard.AgainstNull("Shipping model cannot be empty", cmd);

    this.Id = cmd.Dto.Id;
    this.SetSoftDeleted();

    //Set your appropriate SetSoftDeleted for the inner object here

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **ID Assignment**: Sets the shipping ID from DTO
* **State Management**: Marks entity as soft deleted
* **Child Objects**: Processes child object soft deletions

### 5. **NServiceBus Handler** - Message Processing

**File**: `SoftDeleteShippingNsbHandler.cs`

```csharp
public class SoftDeleteShippingNsbHandler : NsbCommandHandler<SoftDeleteShippingCommand>
{
    readonly ILogger<SoftDeleteShippingNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly ISoftDeleteShippingHandler _handler;

    public SoftDeleteShippingNsbHandler(ILogger<SoftDeleteShippingNsbHandler> logger, IFlexHost flexHost, ISoftDeleteShippingHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(SoftDeleteShippingCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(SoftDeleteShippingNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `SoftDeleteShippingCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ShippingSoftDeletedEvent` (if implemented)

```csharp
public class ShippingSoftDeletedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with shipping data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **Event Subscribers** - Side Effects

**File**: `NotifyLogisticsOnShippingSoftDeleted.cs` (if implemented)

```csharp
public partial class NotifyLogisticsOnShippingSoftDeleted : INotifyLogisticsOnShippingSoftDeleted
{
    protected readonly ILogger<NotifyLogisticsOnShippingSoftDeleted> _logger;
    protected string EventCondition = "";

    public NotifyLogisticsOnShippingSoftDeleted(ILogger<NotifyLogisticsOnShippingSoftDeleted> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ShippingSoftDeletedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Update logistics systems
        // - Notify carriers of cancellation
        // - Update analytics
        // - Archive related data

        await this.Fire<NotifyLogisticsOnShippingSoftDeleted>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ShippingSoftDeletedEvent` from message bus
* **Side Effects**: Executes business logic (logistics updates, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Input DTO**: `SoftDeleteShippingDto`

```csharp
public partial class SoftDeleteShippingDto : DtoBridge 
{
    public string Id { get; set; }
    
    // Optional: Reason for soft delete
    public string DeletionReason { get; set; }
}
```

### **Command**: `SoftDeleteShippingCommand`

```csharp
public class SoftDeleteShippingCommand : FlexCommandBridge<SoftDeleteShippingDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

## Key Differences from Hard Delete

### **Soft Delete vs Hard Delete Characteristics**

| Aspect               | Soft Delete                    | Hard Delete                  |
| -------------------- | ------------------------------ | ---------------------------- |
| **Data Persistence** | ✅ Data remains in database     | ❌ Data physically removed    |
| **Recovery**         | ✅ Can be restored              | ❌ Cannot be recovered        |
| **Audit Trail**      | ✅ Complete history maintained  | ❌ History lost               |
| **Performance**      | ✅ Fast (just flag update)      | ✅ Fast (row deletion)        |
| **Storage**          | ❌ Uses more storage            | ✅ Frees storage              |
| **Queries**          | ❌ Need to filter deleted items | ✅ No filtering needed        |
| **Business Rules**   | ✅ Can validate before delete   | ✅ Can validate before delete |

### **Soft Delete-Specific Features**

1. **Data Preservation**: Entity remains in database with deleted flag
2. **Recovery**: Can be restored if needed
3. **Audit Trail**: Maintains complete history
4. **Query Filtering**: Queries must filter out soft-deleted items
5. **Business Logic**: Can implement complex deletion rules

### **Soft Delete Pattern Benefits**

* **Data Safety**: No accidental data loss
* **Compliance**: Meets regulatory requirements for data retention
* **Audit Trail**: Complete history of all operations
* **Recovery**: Can restore deleted data if needed
* **Business Rules**: Can implement complex deletion logic

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **DELETE Request** → Controller receives request with ID
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Data processing and soft delete
5. **Domain Logic** → Business rules and state management
6. **Response** → HTTP 200 OK with success status

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ShippingSoftDeletedEvent published to message bus
2. **Subscriber Processing** → NotifyLogisticsOnShippingSoftDeleted executes
3. **Side Effects** → Logistics updates, carrier notifications, analytics

## Query Filtering for Soft Deleted Items

### **Standard Query Filtering**

```csharp
// In query handlers, always filter out soft deleted items
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Always exclude soft deleted items
    query = query.Where(s => !s.IsSoftDeleted);
    
    // Add other filtering logic here
    
    return query;
}
```

### **Include Soft Deleted Items (Admin Queries)**

```csharp
// For admin queries that need to see soft deleted items
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Only include soft deleted items if specifically requested
    if (_params.IncludeSoftDeleted == true)
    {
        // Don't filter out soft deleted items
    }
    else
    {
        query = query.Where(s => !s.IsSoftDeleted);
    }
    
    return query;
}
```

## Key Benefits

* **Data Safety**: No accidental data loss
* **Compliance**: Meets regulatory requirements
* **Audit Trail**: Complete history of operations
* **Recovery**: Can restore deleted data
* **Business Rules**: Complex deletion logic support
* **Event-Driven**: Notifies other systems of deletions
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This SoftDeleteShipping example demonstrates how FlexBase enables clean, maintainable, and scalable soft delete operations with proper validation, data preservation, and event-driven architecture!** 🚀


# Get By Id Example

## Overview

This document demonstrates the complete **Get By ID flow** using the **GetShippingInfoById** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This returns a single entity by its unique identifier.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → RESTClient → External System
                                                                    ↓
Response ← Controller ← Service ← Query Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO → Internal DTO Mapping
   ↓
5. Response (Single Entity)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_GetShippingInfoById.cs`

```csharp
[HttpGet()]
[Route("GetShippingInfoById/{id}")]
[ProducesResponseType(typeof(GetShippingInfoByIdDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetShippingInfoById(string id)
{
    GetShippingInfoByIdParams parameters = new GetShippingInfoByIdParams();
    parameters.Id = id;

    return RunQuerySingleService<GetShippingInfoByIdParams, GetShippingInfoByIdDto>(
                parameters, _processShippingService.GetShippingInfoById);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Shipping/GetShippingInfoById/{id}`
* **Input**: Shipping ID from URL parameter
* **Parameter Creation**: Creates `GetShippingInfoByIdParams` with the ID
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `GetShippingInfoByIdDto` or 404 Not Found

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_GetShippingInfoById.cs`

```csharp
public GetShippingInfoByIdDto GetShippingInfoById(GetShippingInfoByIdParams @params)
{
    return _flexHost.GetFlexiQuery<GetShippingInfoById>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetShippingInfoById
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns single shipping or null if not found

### 3. **Query Handler** - RESTClient Integration

**File**: `GetShippingInfoById.cs`

```csharp
public class GetShippingInfoById : FlexiQueryBridge<Shipping, GetShippingInfoByIdDto>
{
    protected readonly ILogger<GetShippingInfoById> _logger;
    protected GetShippingInfoByIdParams _params;
    protected readonly ShippingRESTClient _restClient;

    public GetShippingInfoById(ILogger<GetShippingInfoById> logger, ShippingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }

    public virtual GetShippingInfoById AssignParameters(GetShippingInfoByIdParams @params)
    {
        _params = @params;
        return this;
    }

    public override GetShippingInfoByIdDto Fetch()
    {
        try
        {
            // Convert internal parameters to Request DTO
            GetShippingInfoByIdRequestDto requestParams = new GetShippingInfoByIdRequestDto
            {
                Id = _params.Id
            };

            // Call external REST service
            var response = _restClient.GetShippingInfoById(requestParams).Result;

            if (response.IsSuccessStatusCode)
            {
                var responseContent = response.Content.ReadAsStringAsync().Result;
                var responseDto = JsonConvert.DeserializeObject<GetShippingInfoByIdResponseDto>(responseContent);
                
                // Convert Response DTO to Internal DTO
                var result = new GetShippingInfoByIdDto
                {
                    Id = responseDto.Id,
                    OrderId = responseDto.OrderId,
                    ShippingAddress = responseDto.ShippingAddress,
                    TrackingNumber = responseDto.TrackingNumber,
                    Status = ParseShippingStatus(responseDto.Status),
                    StatusDescription = responseDto.StatusDescription,
                    TotalWeight = responseDto.TotalWeight,
                    TotalVolume = responseDto.TotalVolume,
                    CreatedDate = responseDto.CreatedDate,
                    LastModifiedDate = responseDto.LastModifiedDate,
                    CreatedBy = responseDto.CreatedBy,
                    LastModifiedBy = responseDto.LastModifiedBy,
                    ShippingItems = responseDto.ShippingItems?.Select(x => new ShippingItemDto
                    {
                        ProductId = x.ProductId,
                        Quantity = x.Quantity,
                        Weight = x.Weight,
                        Volume = x.Volume
                    }).ToList()
                };

                _logger.LogDebug("Shipping info retrieved successfully for ID: {Id}", _params.Id);
                return result;
            }
            else
            {
                _logger.LogWarning("Shipping not found for ID: {Id}. Status: {StatusCode}", _params.Id, response.StatusCode);
                return null;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving shipping info for ID: {Id}", _params.Id);
            return null;
        }
    }

    private ShippingStatus ParseShippingStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in RESTClient calls
* **Request Mapping**: Converts internal parameters to Request DTO
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Mapping**: Converts Response DTO to Internal DTO
* **Error Handling**: Handles success/failure responses from external system
* **Data Transformation**: Applies business logic during mapping

### 4. **Query Parameters** - Input DTO

**File**: `GetShippingInfoByIdParams.cs`

```csharp
public class GetShippingInfoByIdParams : DtoBridge
{
    public string Id { get; set; }
}
```

**What Happens:**

* **ID Parameter**: Contains the unique identifier for the entity
* **Simple Structure**: Minimal parameters for single entity lookup
* **URL Binding**: ID is automatically bound from URL parameter

### 5. **Output DTO** - Data Transfer Object

**File**: `GetShippingInfoByIdDto.cs`

```csharp
public partial class GetShippingInfoByIdDto : DtoBridge 
{
    public string Id { get; set; }
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public ShippingStatus Status { get; set; }
    public string StatusDescription { get; set; }
    public decimal TotalWeight { get; set; }
    public decimal TotalVolume { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? LastModifiedDate { get; set; }
    public string CreatedBy { get; set; }
    public string LastModifiedBy { get; set; }
    public ICollection<ShippingItemDto> ShippingItems { get; set; }
}
```

**What Happens:**

* **Complete Data**: Contains all relevant fields for the entity
* **Detailed Structure**: Includes all properties for full entity display
* **Related Data**: May include related entity information (ShippingItems)
* **Audit Fields**: Includes creation and modification tracking

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetShippingInfoByIdMapperConfiguration.cs`

```csharp
public partial class GetShippingInfoByIdMapperConfiguration : FlexMapperProfile
{
    public GetShippingInfoByIdMapperConfiguration() : base()
    {
        CreateMap<Shipping, GetShippingInfoByIdDto>()
            .ForMember(d => d.StatusDescription, opt => opt.MapFrom(s => s.Status.ToString()))
            .ForMember(d => d.ShippingItems, opt => opt.MapFrom(s => s.ShippingItems));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Related Data**: Maps related entity properties
* **Computed Fields**: Handles calculated properties

## Key Differences from Other Query Operations

### **Get By ID vs Other Query Characteristics**

| Aspect                | Get By ID                  | Get List                     | Get Paged List               |
| --------------------- | -------------------------- | ---------------------------- | ---------------------------- |
| **Return Type**       | `T` (single entity)        | `IEnumerable<T>`             | `FlexiPagedList<T>`          |
| **Input**             | ID from URL                | Query parameters             | Query parameters             |
| **Result Count**      | 0 or 1                     | 0 to many                    | 0 to many (paginated)        |
| **Use Case**          | Single entity details      | Dropdown/lookup              | Data grids/tables            |
| **Performance**       | Very fast (indexed lookup) | Fast for small datasets      | Optimized for large datasets |
| **Controller Method** | `RunQuerySingleService`    | `RunQueryListService`        | `RunQueryPagedService`       |
| **Query Base**        | `FlexiQueryBridge`         | `FlexiQueryEnumerableBridge` | `FlexiQueryPagedListBridge`  |
| **HTTP Status**       | 200 OK or 404 Not Found    | 200 OK                       | 200 OK                       |

### **Get By ID-Specific Features**

1. **Single Entity**: Returns one entity or null
2. **ID-Based Lookup**: Uses unique identifier for fast retrieval
3. **404 Handling**: Returns 404 when entity not found
4. **Complete Data**: Returns all entity details
5. **Fast Performance**: Optimized for indexed lookups

### **Common Use Cases**

* **Entity Details**: Display detailed information about a specific shipping
* **Edit Forms**: Load shipping data for editing
* **View Pages**: Show complete shipping information
* **API Integration**: Retrieve specific shipping for external systems
* **Validation**: Check if shipping exists before operations

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with ID parameter
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Response** → HTTP 200 OK with entity or 404 Not Found

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>().Where(t => t.Id == _params.Id);
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Filter by ID
    query = query.Where(t => t.Id == _params.Id);
    
    // Exclude soft deleted items
    query = query.Where(t => !t.IsSoftDeleted);
    
    // Include related entities if needed
    // query = query.Include(t => t.ShippingItems);
    
    return query;
}
```

### **Error Handling Patterns**

```csharp
public override GetShippingInfoByIdDto Fetch()
{
    var result = Build<Shipping>().SelectTo<GetShippingInfoByIdDto>().FirstOrDefault();
    
    if (result == null)
    {
        _logger.LogWarning("Shipping with ID {ShippingId} not found", _params.Id);
    }
    else
    {
        _logger.LogDebug("Shipping with ID {ShippingId} retrieved successfully", _params.Id);
    }
    
    return result;
}
```

## Performance Considerations

### **Optimization Strategies**

1. **Database Indexing**: Ensure ID field is properly indexed
2. **Selective Fields**: Only return necessary fields in DTO
3. **Related Data**: Use Include() judiciously for related entities
4. **Caching**: Consider caching for frequently accessed entities
5. **Query Optimization**: Use FirstOrDefault() for single entity retrieval

### **When to Use Get By ID vs Other Queries**

| Scenario                | Use Get By ID | Use Get List | Use Get Paged List |
| ----------------------- | ------------- | ------------ | ------------------ |
| **Entity Details Page** | ✅ Yes         | ❌ No         | ❌ No               |
| **Edit Form Loading**   | ✅ Yes         | ❌ No         | ❌ No               |
| **API Integration**     | ✅ Yes         | ❌ No         | ❌ No               |
| **Dropdown Population** | ❌ No          | ✅ Yes        | ❌ No               |
| **Data Grids**          | ❌ No          | ❌ No         | ✅ Yes              |
| **Search Results**      | ❌ No          | ✅ Yes        | ✅ Yes              |
| **Lookup Tables**       | ❌ No          | ✅ Yes        | ❌ No               |

## Error Handling

### **HTTP Status Codes**

* **200 OK**: Entity found and returned successfully
* **404 Not Found**: Entity with specified ID does not exist
* **400 Bad Request**: Invalid ID format or missing ID parameter
* **500 Internal Server Error**: Database or server error

### **Controller Error Handling**

```csharp
[HttpGet()]
[Route("GetShippingInfoById/{id}")]
[ProducesResponseType(typeof(GetShippingInfoByIdDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetShippingInfoById(string id)
{
    if (string.IsNullOrEmpty(id))
    {
        return BadRequest("Shipping ID is required");
    }
    
    GetShippingInfoByIdParams parameters = new GetShippingInfoByIdParams();
    parameters.Id = id;

    return RunQuerySingleService<GetShippingInfoByIdParams, GetShippingInfoByIdDto>(
                parameters, _processShippingService.GetShippingInfoById);
}
```

## Key Benefits

* **Performance**: Very fast retrieval using indexed ID lookup
* **Simplicity**: Simple single entity retrieval
* **Complete Data**: Returns full entity details
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **Error Handling**: Built-in 404 handling for missing entities
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetShippingInfoById example demonstrates how FlexBase enables clean, maintainable, and scalable single entity retrieval operations with proper error handling and performance optimization!** 🚀


# Get List Example

## Overview

This document demonstrates the complete **Get List flow** using the **GetShippingDetails** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This is similar to Get Paged List but returns a simple `IEnumerable<T>` without pagination.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → RESTClient → External System
                                                                    ↓
Response ← Controller ← Service ← Query Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO → Internal DTO Mapping
   ↓
5. Response (Simple List)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_GetShippingDetails.cs`

```csharp
[HttpGet()]
[Route("GetShippingDetails")]
[ProducesResponseType(typeof(IEnumerable<GetShippingDetailsDto>), 200)]
public async Task<IActionResult> GetShippingDetails([FromQuery]GetShippingDetailsParams parameters)
{
    return RunQueryListService<GetShippingDetailsParams, GetShippingDetailsDto>(
                parameters, _processShippingService.GetShippingDetails);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Shipping/GetShippingDetails`
* **Input**: `GetShippingDetailsParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `IEnumerable<GetShippingDetailsDto>`

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_GetShippingDetails.cs`

```csharp
public IEnumerable<GetShippingDetailsDto> GetShippingDetails(GetShippingDetailsParams @params)
{
    return _flexHost.GetFlexiQuery<GetShippingDetails>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetShippingDetails
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns simple list of shipping details for lookup

### 3. **Query Handler** - RESTClient Integration

**File**: `GetShippingDetails.cs`

```csharp
public class GetShippingDetails : FlexiQueryEnumerableBridge<Shipping, GetShippingDetailsDto>
{
    protected readonly ILogger<GetShippingDetails> _logger;
    protected GetShippingDetailsParams _params;
    protected readonly ShippingRESTClient _restClient;

    public GetShippingDetails(ILogger<GetShippingDetails> logger, ShippingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }

    public virtual GetShippingDetails AssignParameters(GetShippingDetailsParams @params)
    {
        _params = @params;
        return this;
    }

    public override IEnumerable<GetShippingDetailsDto> Fetch()
    {
        try
        {
            // Convert internal parameters to Request DTO
            GetShippingDetailsRequestDto requestParams = new GetShippingDetailsRequestDto
            {
                SearchTerm = _params.SearchTerm,
                OrderId = _params.OrderId,
                Status = _params.Status?.ToString(),
                FromDate = _params.FromDate,
                ToDate = _params.ToDate,
                Limit = _params.Limit
            };

            // Call external REST service
            var response = _restClient.GetShippingDetails(requestParams).Result;

            if (response.IsSuccessStatusCode)
            {
                var responseContent = response.Content.ReadAsStringAsync().Result;
                var responseDto = JsonConvert.DeserializeObject<GetShippingDetailsResponseDto>(responseContent);
                
                // Convert Response DTO to Internal DTO
                var result = responseDto.ShippingDetails?.Select(x => new GetShippingDetailsDto
                {
                    Id = x.Id,
                    OrderId = x.OrderId,
                    ShippingAddress = x.ShippingAddress,
                    TrackingNumber = x.TrackingNumber,
                    Status = ParseShippingStatus(x.Status),
                    StatusDescription = x.StatusDescription,
                    TotalWeight = x.TotalWeight,
                    CreatedDate = x.CreatedDate,
                    IsActive = x.IsActive
                }).ToList() ?? new List<GetShippingDetailsDto>();

                _logger.LogDebug("Shipping details retrieved successfully. Count: {Count}", result.Count);
                return result;
            }
            else
            {
                _logger.LogWarning("Failed to retrieve shipping details. Status: {StatusCode}", response.StatusCode);
                return new List<GetShippingDetailsDto>();
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving shipping details");
            return new List<GetShippingDetailsDto>();
        }
    }

    private ShippingStatus ParseShippingStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in RESTClient calls
* **Request Mapping**: Converts internal parameters to Request DTO
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Mapping**: Converts Response DTO to Internal DTO list
* **Error Handling**: Handles success/failure responses from external system
* **Data Transformation**: Applies business logic during mapping

### 4. **Query Parameters** - Input DTO

**File**: `GetShippingDetailsParams.cs`

```csharp
public class GetShippingDetailsParams : DtoBridge
{
    // Add custom filtering parameters here
    public string SearchTerm { get; set; }
    public string OrderId { get; set; }
    public ShippingStatus? Status { get; set; }
    public DateTime? FromDate { get; set; }
    public DateTime? ToDate { get; set; }
    public int? Limit { get; set; }
}
```

**What Happens:**

* **Custom Filters**: Allows filtering by search term, order ID, status, date range
* **Limit Support**: Optional limit for lookup results
* **Query Parameters**: Automatically bound from URL query string

### 5. **Output DTO** - Data Transfer Object

**File**: `GetShippingDetailsDto.cs`

```csharp
public partial class GetShippingDetailsDto : DtoBridge 
{
    public string Id { get; set; }
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public ShippingStatus Status { get; set; }
    public string StatusDescription { get; set; }
    public decimal TotalWeight { get; set; }
    public DateTime CreatedDate { get; set; }
    public bool IsActive { get; set; }
}
```

**What Happens:**

* **Lookup Data**: Contains essential fields for dropdown/lookup scenarios
* **Minimal Structure**: Only includes necessary fields for selection
* **Performance**: Lightweight DTO for fast loading

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetShippingDetailsMapperConfiguration.cs`

```csharp
public partial class GetShippingDetailsMapperConfiguration : FlexMapperProfile
{
    public GetShippingDetailsMapperConfiguration() : base()
    {
        CreateMap<Shipping, GetShippingDetailsDto>()
            .ForMember(d => d.StatusDescription, opt => opt.MapFrom(s => s.Status.ToString()))
            .ForMember(d => d.IsActive, opt => opt.MapFrom(s => !s.IsSoftDeleted));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Lookup Optimization**: Maps only necessary fields for lookup scenarios

## Key Differences from Get Paged List

### **Get List vs Get Paged List Characteristics**

| Aspect                | Get List                       | Get Paged List                    |
| --------------------- | ------------------------------ | --------------------------------- |
| **Return Type**       | `IEnumerable<T>`               | `FlexiPagedList<T>`               |
| **Pagination**        | ❌ No pagination                | ✅ Built-in pagination             |
| **Use Case**          | Lookup/Dropdown                | Data grids/tables                 |
| **Performance**       | Fast for small datasets        | Optimized for large datasets      |
| **Memory Usage**      | Lower (no pagination metadata) | Higher (includes pagination info) |
| **Controller Method** | `RunQueryListService`          | `RunQueryPagedService`            |
| **Query Base**        | `FlexiQueryEnumerableBridge`   | `FlexiQueryPagedListBridge`       |

### **Get List-Specific Features**

1. **Simple List**: Returns basic `IEnumerable<T>` without pagination
2. **Lookup Optimized**: Designed for dropdown/lookup scenarios
3. **Lightweight**: Minimal data transfer for performance
4. **No Pagination**: All results returned in single response
5. **Fast Loading**: Optimized for quick data retrieval

### **Common Use Cases**

* **Dropdown Lists**: Populate dropdown controls
* **Lookup Tables**: Search and select scenarios
* **Reference Data**: Load reference data for forms
* **Auto-complete**: Provide suggestions for input fields
* **Quick Filters**: Fast filtering options

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with query parameters
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Response** → HTTP 200 OK with simple list

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Add filtering logic here
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        query = query.Where(s => s.ShippingAddress.Contains(_params.SearchTerm) || 
                                s.TrackingNumber.Contains(_params.SearchTerm));
    }
    
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    
    if (_params.Status.HasValue)
    {
        query = query.Where(s => s.Status == _params.Status.Value);
    }
    
    // Apply limit if specified
    if (_params.Limit.HasValue)
    {
        query = query.Take(_params.Limit.Value);
    }
    
    return query;
}
```

### **Advanced Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Exclude soft deleted items
    query = query.Where(s => !s.IsSoftDeleted);
    
    // Search functionality
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        var searchTerm = _params.SearchTerm.ToLower();
        query = query.Where(s => s.ShippingAddress.ToLower().Contains(searchTerm) || 
                                s.TrackingNumber.ToLower().Contains(searchTerm) ||
                                s.OrderId.ToLower().Contains(searchTerm));
    }
    
    // Order ID filtering
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    
    // Status filtering
    if (_params.Status.HasValue)
    {
        query = query.Where(s => s.Status == _params.Status.Value);
    }
    
    // Date range filtering
    if (_params.FromDate.HasValue)
    {
        query = query.Where(s => s.CreatedDate >= _params.FromDate.Value);
    }
    
    if (_params.ToDate.HasValue)
    {
        query = query.Where(s => s.CreatedDate <= _params.ToDate.Value);
    }
    
    // Sorting for consistent results
    query = query.OrderByDescending(s => s.CreatedDate);
    
    // Apply limit for performance
    if (_params.Limit.HasValue)
    {
        query = query.Take(_params.Limit.Value);
    }
    else
    {
        // Default limit for lookup scenarios
        query = query.Take(100);
    }
    
    return query;
}
```

## Performance Considerations

### **Optimization Strategies**

1. **Limit Results**: Always apply reasonable limits for lookup scenarios
2. **Selective Fields**: Only return necessary fields in DTO
3. **Indexing**: Ensure proper database indexes on filter fields
4. **Caching**: Consider caching for frequently accessed lookup data
5. **Lazy Loading**: Use lazy loading for related entities when appropriate

### **When to Use Get List vs Get Paged List**

| Scenario                | Use Get List | Use Get Paged List |
| ----------------------- | ------------ | ------------------ |
| **Dropdown Population** | ✅ Yes        | ❌ No               |
| **Lookup Tables**       | ✅ Yes        | ❌ No               |
| **Auto-complete**       | ✅ Yes        | ❌ No               |
| **Data Grids**          | ❌ No         | ✅ Yes              |
| **Large Datasets**      | ❌ No         | ✅ Yes              |
| **Admin Interfaces**    | ❌ No         | ✅ Yes              |
| **Reporting**           | ❌ No         | ✅ Yes              |

## Key Benefits

* **Performance**: Fast loading for small datasets
* **Simplicity**: Simple list without pagination complexity
* **Lookup Optimized**: Perfect for dropdown/lookup scenarios
* **Lightweight**: Minimal data transfer
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetShippingDetails example demonstrates how FlexBase enables clean, maintainable, and scalable list operations optimized for lookup and dropdown scenarios!** 🚀


# Get Single Example

## Overview

This document demonstrates the complete **Get Single flow** using the **GetShippingSingle** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This returns a single entity based on specific criteria, similar to Get By ID but with more flexible filtering.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → RESTClient → External System
                                                                    ↓
Response ← Controller ← Service ← Query Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO → Internal DTO Mapping
   ↓
5. Response (Single Entity)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_GetShippingSingle.cs`

```csharp
[HttpGet()]
[Route("GetShippingSingle")]
[ProducesResponseType(typeof(GetShippingSingleDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetShippingSingle([FromQuery]GetShippingSingleParams parameters)
{
    return RunQuerySingleService<GetShippingSingleParams, GetShippingSingleDto>(
                parameters, _processShippingService.GetShippingSingle);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Shipping/GetShippingSingle`
* **Input**: `GetShippingSingleParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `GetShippingSingleDto` or 404 Not Found

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_GetShippingSingle.cs`

```csharp
public GetShippingSingleDto GetShippingSingle(GetShippingSingleParams @params)
{
    return _flexHost.GetFlexiQuery<GetShippingSingle>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetShippingSingle
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns single shipping or null if not found

### 3. **Query Handler** - RESTClient Integration

**File**: `GetShippingSingle.cs`

```csharp
public class GetShippingSingle : FlexiQueryBridge<Shipping, GetShippingSingleDto>
{
    protected readonly ILogger<GetShippingSingle> _logger;
    protected GetShippingSingleParams _params;
    protected readonly ShippingRESTClient _restClient;

    public GetShippingSingle(ILogger<GetShippingSingle> logger, ShippingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }

    public virtual GetShippingSingle AssignParameters(GetShippingSingleParams @params)
    {
        _params = @params;
        return this;
    }

    public override GetShippingSingleDto Fetch()
    {
        try
        {
            // Convert internal parameters to Request DTO
            GetShippingSingleRequestDto requestParams = new GetShippingSingleRequestDto
            {
                Id = _params.Id,
                OrderId = _params.OrderId,
                TrackingNumber = _params.TrackingNumber,
                Status = _params.Status?.ToString(),
                CreatedDate = _params.CreatedDate,
                CreatedBy = _params.CreatedBy
            };

            // Call external REST service
            var response = _restClient.GetShippingSingle(requestParams).Result;

            if (response.IsSuccessStatusCode)
            {
                var responseContent = response.Content.ReadAsStringAsync().Result;
                var responseDto = JsonConvert.DeserializeObject<GetShippingSingleResponseDto>(responseContent);
                
                // Convert Response DTO to Internal DTO
                var result = new GetShippingSingleDto
                {
                    Id = responseDto.Id,
                    OrderId = responseDto.OrderId,
                    ShippingAddress = responseDto.ShippingAddress,
                    TrackingNumber = responseDto.TrackingNumber,
                    Status = ParseShippingStatus(responseDto.Status),
                    StatusDescription = responseDto.StatusDescription,
                    TotalWeight = responseDto.TotalWeight,
                    TotalVolume = responseDto.TotalVolume,
                    CreatedDate = responseDto.CreatedDate,
                    LastModifiedDate = responseDto.LastModifiedDate,
                    CreatedBy = responseDto.CreatedBy,
                    LastModifiedBy = responseDto.LastModifiedBy,
                    ShippingItems = responseDto.ShippingItems?.Select(x => new ShippingItemDto
                    {
                        ProductId = x.ProductId,
                        Quantity = x.Quantity,
                        Weight = x.Weight,
                        Volume = x.Volume
                    }).ToList()
                };

                _logger.LogDebug("Shipping single retrieved successfully for criteria: {Criteria}", 
                    _params.Id ?? _params.OrderId ?? _params.TrackingNumber);
                return result;
            }
            else
            {
                _logger.LogWarning("Shipping not found for criteria. Status: {StatusCode}", response.StatusCode);
                return null;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving shipping single for criteria: {Criteria}", 
                _params.Id ?? _params.OrderId ?? _params.TrackingNumber);
            return null;
        }
    }

    private ShippingStatus ParseShippingStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in RESTClient calls
* **Request Mapping**: Converts internal parameters to Request DTO
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Mapping**: Converts Response DTO to Internal DTO
* **Error Handling**: Handles success/failure responses from external system
* **Data Transformation**: Applies business logic during mapping

### 4. **Query Parameters** - Input DTO

**File**: `GetShippingSingleParams.cs`

```csharp
public class GetShippingSingleParams : DtoBridge
{
    // Primary identifier (optional - can use other criteria)
    public string Id { get; set; }
    
    // Alternative filtering criteria
    public string OrderId { get; set; }
    public string TrackingNumber { get; set; }
    public ShippingStatus? Status { get; set; }
    
    // Additional criteria
    public DateTime? CreatedDate { get; set; }
    public string CreatedBy { get; set; }
}
```

**What Happens:**

* **Flexible Parameters**: Multiple ways to identify the entity
* **Primary ID**: Can use ID for direct lookup
* **Alternative Criteria**: Can use OrderId, TrackingNumber, etc.
* **Query Parameters**: Automatically bound from URL query string

### 5. **Output DTO** - Data Transfer Object

**File**: `GetShippingSingleDto.cs`

```csharp
public partial class GetShippingSingleDto : DtoBridge 
{
    public string Id { get; set; }
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public ShippingStatus Status { get; set; }
    public string StatusDescription { get; set; }
    public decimal TotalWeight { get; set; }
    public decimal TotalVolume { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? LastModifiedDate { get; set; }
    public string CreatedBy { get; set; }
    public string LastModifiedBy { get; set; }
    public ICollection<ShippingItemDto> ShippingItems { get; set; }
}
```

**What Happens:**

* **Complete Data**: Contains all relevant fields for the entity
* **Detailed Structure**: Includes all properties for full entity display
* **Related Data**: May include related entity information (ShippingItems)
* **Audit Fields**: Includes creation and modification tracking

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetShippingSingleMapperConfiguration.cs`

```csharp
public partial class GetShippingSingleMapperConfiguration : FlexMapperProfile
{
    public GetShippingSingleMapperConfiguration() : base()
    {
        CreateMap<Shipping, GetShippingSingleDto>()
            .ForMember(d => d.StatusDescription, opt => opt.MapFrom(s => s.Status.ToString()))
            .ForMember(d => d.ShippingItems, opt => opt.MapFrom(s => s.ShippingItems));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Related Data**: Maps related entity properties
* **Computed Fields**: Handles calculated properties

## Key Differences from Get By ID

### **Get Single vs Get By ID Characteristics**

| Aspect                | Get Single                   | Get By ID               |
| --------------------- | ---------------------------- | ----------------------- |
| **Input**             | Query parameters             | URL parameter (ID)      |
| **Filtering**         | Multiple criteria            | Single ID only          |
| **Flexibility**       | High (multiple ways to find) | Low (ID only)           |
| **Use Case**          | Complex lookups              | Direct ID lookup        |
| **Performance**       | Depends on criteria          | Very fast (indexed)     |
| **Controller Method** | `RunQuerySingleService`      | `RunQuerySingleService` |
| **Query Base**        | `FlexiQueryBridge`           | `FlexiQueryBridge`      |

### **Get Single-Specific Features**

1. **Flexible Filtering**: Multiple ways to identify the entity
2. **Complex Criteria**: Can combine multiple filter conditions
3. **Business Logic**: Can implement complex lookup rules
4. **Alternative Keys**: Can use non-primary key fields
5. **Conditional Logic**: Can apply different logic based on parameters

### **Common Use Cases**

* **Lookup by Alternative Key**: Find by tracking number, order ID, etc.
* **Conditional Lookups**: Different logic based on user role or context
* **Business Rules**: Complex business logic for entity identification
* **API Integration**: Flexible lookup for external systems
* **Search Scenarios**: Find entity based on multiple criteria

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with query parameters
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Response** → HTTP 200 OK with entity or 404 Not Found

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Primary ID lookup
    if (!string.IsNullOrEmpty(_params.Id))
    {
        query = query.Where(s => s.Id == _params.Id);
    }
    // Alternative criteria
    else if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    else if (!string.IsNullOrEmpty(_params.TrackingNumber))
    {
        query = query.Where(s => s.TrackingNumber == _params.TrackingNumber);
    }
    
    return query;
}
```

### **Advanced Query Building with Multiple Criteria**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Exclude soft deleted items
    query = query.Where(s => !s.IsSoftDeleted);
    
    // Primary ID lookup (highest priority)
    if (!string.IsNullOrEmpty(_params.Id))
    {
        query = query.Where(s => s.Id == _params.Id);
    }
    else
    {
        // Alternative lookup criteria
        if (!string.IsNullOrEmpty(_params.OrderId))
        {
            query = query.Where(s => s.OrderId == _params.OrderId);
        }
        
        if (!string.IsNullOrEmpty(_params.TrackingNumber))
        {
            query = query.Where(s => s.TrackingNumber == _params.TrackingNumber);
        }
        
        if (_params.Status.HasValue)
        {
            query = query.Where(s => s.Status == _params.Status.Value);
        }
        
        if (_params.CreatedDate.HasValue)
        {
            query = query.Where(s => s.CreatedDate.Date == _params.CreatedDate.Value.Date);
        }
        
        if (!string.IsNullOrEmpty(_params.CreatedBy))
        {
            query = query.Where(s => s.CreatedBy == _params.CreatedBy);
        }
    }
    
    // Order by creation date for consistent results
    query = query.OrderByDescending(s => s.CreatedDate);
    
    return query;
}
```

### **Business Logic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Exclude soft deleted items
    query = query.Where(s => !s.IsSoftDeleted);
    
    // Business logic: Find active shipping for order
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId && 
                                s.Status != ShippingStatus.Cancelled &&
                                s.Status != ShippingStatus.Delivered);
    }
    
    // Business logic: Find shipping by tracking number (any status)
    if (!string.IsNullOrEmpty(_params.TrackingNumber))
    {
        query = query.Where(s => s.TrackingNumber == _params.TrackingNumber);
    }
    
    // Business logic: Find latest shipping for user
    if (!string.IsNullOrEmpty(_params.CreatedBy))
    {
        query = query.Where(s => s.CreatedBy == _params.CreatedBy)
                    .OrderByDescending(s => s.CreatedDate);
    }
    
    return query;
}
```

## Error Handling

### **HTTP Status Codes**

* **200 OK**: Entity found and returned successfully
* **404 Not Found**: Entity with specified criteria does not exist
* **400 Bad Request**: Invalid parameters or missing required criteria
* **500 Internal Server Error**: Database or server error

### **Controller Error Handling**

```csharp
[HttpGet()]
[Route("GetShippingSingle")]
[ProducesResponseType(typeof(GetShippingSingleDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetShippingSingle([FromQuery]GetShippingSingleParams parameters)
{
    // Validate that at least one criteria is provided
    if (string.IsNullOrEmpty(parameters.Id) && 
        string.IsNullOrEmpty(parameters.OrderId) && 
        string.IsNullOrEmpty(parameters.TrackingNumber))
    {
        return BadRequest("At least one search criteria must be provided");
    }
    
    return RunQuerySingleService<GetShippingSingleParams, GetShippingSingleDto>(
                parameters, _processShippingService.GetShippingSingle);
}
```

## Performance Considerations

### **Optimization Strategies**

1. **Database Indexing**: Ensure proper indexes on filter fields
2. **Query Optimization**: Use efficient WHERE clauses
3. **Parameter Validation**: Validate parameters early
4. **Caching**: Consider caching for frequently accessed data
5. **Query Planning**: Plan queries based on most common use cases

### **When to Use Get Single vs Get By ID**

| Scenario                 | Use Get Single | Use Get By ID |
| ------------------------ | -------------- | ------------- |
| **Alternative Keys**     | ✅ Yes          | ❌ No          |
| **Complex Lookups**      | ✅ Yes          | ❌ No          |
| **Business Rules**       | ✅ Yes          | ❌ No          |
| **Direct ID Lookup**     | ❌ No           | ✅ Yes         |
| **Simple Lookups**       | ❌ No           | ✅ Yes         |
| **Performance Critical** | ❌ No           | ✅ Yes         |

## Key Benefits

* **Flexibility**: Multiple ways to find entities
* **Business Logic**: Can implement complex lookup rules
* **Alternative Keys**: Support for non-primary key lookups
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **Error Handling**: Built-in 404 handling for missing entities
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetShippingSingle example demonstrates how FlexBase enables clean, maintainable, and scalable single entity retrieval operations with flexible filtering and business logic support!** 🚀


# Get Paged List Example

## Overview

This document demonstrates the complete **Get Paged List flow** using the **GetShippingPagedList** feature from the EBusiness application. The flow starts with a GET request to the controller and uses **Query projects** instead of **Handlers** in the DomainHandler section for data retrieval. This returns a paginated list of entities with metadata for data grids and large datasets.

## Complete Flow Architecture

```
GET Request → Controller → Service → Query Handler → RESTClient → External System
                                                                    ↓
Response ← Controller ← Service ← Query Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. GET Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. Query Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO → Internal DTO Mapping
   ↓
5. Response (Paged List with Metadata)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_GetShippingPagedList.cs`

```csharp
[HttpGet()]
[Route("GetShippingPagedList")]
[ProducesResponseType(typeof(FlexiPagedList<GetShippingPagedListDto>), 200)]
public async Task<IActionResult> GetShippingPagedList([FromQuery]GetShippingPagedListParams parameters)
{
    return RunQueryPagedService<GetShippingPagedListParams, GetShippingPagedListDto>(
                parameters, _processShippingService.GetShippingPagedList);
}
```

**What Happens:**

* **HTTP Method**: `GET /api/Shipping/GetShippingPagedList`
* **Input**: `GetShippingPagedListParams` from query parameters
* **Action**: Calls the service layer to process the query
* **Response**: HTTP 200 OK with `FlexiPagedList<GetShippingPagedListDto>`

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_GetShippingPagedList.cs`

```csharp
public FlexiPagedList<GetShippingPagedListDto> GetShippingPagedList(GetShippingPagedListParams @params)
{
    return _flexHost.GetFlexiQuery<GetShippingPagedList>().AssignParameters(@params).Fetch();
}
```

**What Happens:**

* **Query Resolution**: Gets the FlexiQuery instance for GetShippingPagedList
* **Parameter Assignment**: Assigns query parameters to the query handler
* **Query Execution**: Calls the Fetch() method to execute the query
* **Result**: Returns paginated list of shipping with metadata

### 3. **Query Handler** - RESTClient Integration

**File**: `GetShippingPagedList.cs`

```csharp
public class GetShippingPagedList : FlexiQueryPagedListBridge<Shipping, GetShippingPagedListDto>
{
    protected readonly ILogger<GetShippingPagedList> _logger;
    protected GetShippingPagedListParams _params;
    protected readonly ShippingRESTClient _restClient;

    public GetShippingPagedList(ILogger<GetShippingPagedList> logger, ShippingRESTClient restClient)
    {
        _logger = logger;
        _restClient = restClient;
    }

    public virtual GetShippingPagedList AssignParameters(GetShippingPagedListParams @params)
    {
        _params = @params;
        return this;
    }

    public override FlexiPagedList<GetShippingPagedListDto> Fetch()
    {
        try
        {
            // Convert internal parameters to Request DTO
            GetShippingPagedListRequestDto requestParams = new GetShippingPagedListRequestDto
            {
                PageNumber = _params.PageNumber,
                PageSize = _params.PageSize,
                SearchTerm = _params.SearchTerm,
                OrderId = _params.OrderId,
                Status = _params.Status?.ToString(),
                FromDate = _params.FromDate,
                ToDate = _params.ToDate,
                SortBy = _params.SortBy,
                SortDirection = _params.SortDirection
            };

            // Call external REST service
            var response = _restClient.GetShippingPagedList(requestParams).Result;

            if (response.IsSuccessStatusCode)
            {
                var responseContent = response.Content.ReadAsStringAsync().Result;
                var responseDto = JsonConvert.DeserializeObject<GetShippingPagedListResponseDto>(responseContent);
                
                // Convert Response DTO to Internal DTO
                var items = responseDto.Items?.Select(x => new GetShippingPagedListDto
                {
                    Id = x.Id,
                    OrderId = x.OrderId,
                    ShippingAddress = x.ShippingAddress,
                    TrackingNumber = x.TrackingNumber,
                    Status = ParseShippingStatus(x.Status),
                    StatusDescription = x.StatusDescription,
                    TotalWeight = x.TotalWeight,
                    CreatedDate = x.CreatedDate,
                    CreatedBy = x.CreatedBy,
                    IsActive = x.IsActive
                }).ToList() ?? new List<GetShippingPagedListDto>();

                // Create paginated result
                var result = new FlexiPagedList<GetShippingPagedListDto>
                {
                    Items = items,
                    TotalCount = responseDto.TotalCount,
                    PageNumber = responseDto.PageNumber,
                    PageSize = responseDto.PageSize,
                    TotalPages = responseDto.TotalPages,
                    HasPreviousPage = responseDto.HasPreviousPage,
                    HasNextPage = responseDto.HasNextPage
                };

                _logger.LogDebug("Shipping paged list retrieved successfully. Count: {Count}, Page: {PageNumber}", 
                    result.TotalCount, result.PageNumber);
                return result;
            }
            else
            {
                _logger.LogWarning("Failed to retrieve shipping paged list. Status: {StatusCode}", response.StatusCode);
                return new FlexiPagedList<GetShippingPagedListDto>
                {
                    Items = new List<GetShippingPagedListDto>(),
                    TotalCount = 0,
                    PageNumber = _params.PageNumber,
                    PageSize = _params.PageSize,
                    TotalPages = 0,
                    HasPreviousPage = false,
                    HasNextPage = false
                };
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error retrieving shipping paged list");
            return new FlexiPagedList<GetShippingPagedListDto>
            {
                Items = new List<GetShippingPagedListDto>(),
                TotalCount = 0,
                PageNumber = _params.PageNumber,
                PageSize = _params.PageSize,
                TotalPages = 0,
                HasPreviousPage = false,
                HasNextPage = false
            };
        }
    }

    private ShippingStatus ParseShippingStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Parameter Assignment**: Stores query parameters for use in RESTClient calls
* **Request Mapping**: Converts internal parameters to Request DTO
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Mapping**: Converts Response DTO to Internal DTO with pagination
* **Error Handling**: Handles success/failure responses from external system
* **Data Transformation**: Applies business logic during mapping

### 4. **Query Parameters** - Input DTO

**File**: `GetShippingPagedListParams.cs`

```csharp
public class GetShippingPagedListParams : DtoBridge
{
    // Pagination parameters
    public int PageNumber { get; set; } = 1;
    public int PageSize { get; set; } = 10;
    
    // Filtering parameters
    public string SearchTerm { get; set; }
    public string OrderId { get; set; }
    public ShippingStatus? Status { get; set; }
    public DateTime? FromDate { get; set; }
    public DateTime? ToDate { get; set; }
    
    // Sorting parameters
    public string SortBy { get; set; } = "CreatedDate";
    public string SortDirection { get; set; } = "desc";
}
```

**What Happens:**

* **Pagination**: PageNumber and PageSize for pagination control
* **Filtering**: Multiple filter options for data refinement
* **Sorting**: SortBy and SortDirection for data ordering
* **Query Parameters**: Automatically bound from URL query string

### 5. **Output DTO** - Data Transfer Object

**File**: `GetShippingPagedListDto.cs`

```csharp
public partial class GetShippingPagedListDto : DtoBridge 
{
    public string Id { get; set; }
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public ShippingStatus Status { get; set; }
    public string StatusDescription { get; set; }
    public decimal TotalWeight { get; set; }
    public DateTime CreatedDate { get; set; }
    public string CreatedBy { get; set; }
    public bool IsActive { get; set; }
}
```

**What Happens:**

* **Grid Data**: Contains fields suitable for data grid display
* **Essential Fields**: Includes key information for list views
* **Performance**: Optimized for large dataset display

### 6. **AutoMapper Configuration** - Data Transformation

**File**: `GetShippingPagedListMapperConfiguration.cs`

```csharp
public partial class GetShippingPagedListMapperConfiguration : FlexMapperProfile
{
    public GetShippingPagedListMapperConfiguration() : base()
    {
        CreateMap<Shipping, GetShippingPagedListDto>()
            .ForMember(d => d.StatusDescription, opt => opt.MapFrom(s => s.Status.ToString()))
            .ForMember(d => d.IsActive, opt => opt.MapFrom(s => !s.IsSoftDeleted));
    }
}
```

**What Happens:**

* **Entity to DTO Mapping**: Maps domain entities to DTOs
* **Custom Mappings**: Handles complex property transformations
* **Grid Optimization**: Maps fields optimized for data grid display

## Key Differences from Get List

### **Get Paged List vs Get List Characteristics**

| Aspect                | Get Paged List                    | Get List                       |
| --------------------- | --------------------------------- | ------------------------------ |
| **Return Type**       | `FlexiPagedList<T>`               | `IEnumerable<T>`               |
| **Pagination**        | ✅ Built-in pagination             | ❌ No pagination                |
| **Use Case**          | Data grids/tables                 | Lookup/Dropdown                |
| **Performance**       | Optimized for large datasets      | Fast for small datasets        |
| **Memory Usage**      | Higher (includes pagination info) | Lower (no pagination metadata) |
| **Controller Method** | `RunQueryPagedService`            | `RunQueryListService`          |
| **Query Base**        | `FlexiQueryPagedListBridge`       | `FlexiQueryEnumerableBridge`   |

### **Get Paged List-Specific Features**

1. **Pagination**: Built-in pagination with PageNumber and PageSize
2. **Metadata**: Includes total count, page count, and pagination info
3. **Large Datasets**: Optimized for handling large amounts of data
4. **Data Grids**: Perfect for admin interfaces and data tables
5. **Performance**: Efficient memory usage for large datasets

### **Common Use Cases**

* **Data Grids**: Populate data tables with pagination
* **Admin Interfaces**: Large dataset management
* **Reporting**: Paginated report data
* **Search Results**: Paginated search results
* **Audit Logs**: Large audit trail displays

## Flow Summary

### **Synchronous Flow (Data Retrieval)**

1. **GET Request** → Controller receives request with query parameters
2. **Service Processing** → Business orchestration and query resolution
3. **Query Handler** → Database query building and execution
4. **AutoMapper** → Entity-to-DTO transformation
5. **Pagination** → Apply pagination to results
6. **Response** → HTTP 200 OK with paginated list and metadata

### **No Asynchronous Flow**

* **No Events**: Query operations don't publish events
* **No Subscribers**: No side effects or event processing
* **Immediate Response**: Data is returned immediately

## Query Building Patterns

### **Basic Query Building**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Add filtering logic here
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        query = query.Where(s => s.ShippingAddress.Contains(_params.SearchTerm) || 
                                s.TrackingNumber.Contains(_params.SearchTerm));
    }
    
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    
    if (_params.Status.HasValue)
    {
        query = query.Where(s => s.Status == _params.Status.Value);
    }
    
    return query;
}
```

### **Advanced Query Building with Sorting**

```csharp
protected override IQueryable<T> Build<T>()
{
    _repoFactory.Init(_params);
    IQueryable<T> query = _repoFactory.GetRepo().FindAll<T>();
    
    // Exclude soft deleted items
    query = query.Where(s => !s.IsSoftDeleted);
    
    // Search functionality
    if (!string.IsNullOrEmpty(_params.SearchTerm))
    {
        var searchTerm = _params.SearchTerm.ToLower();
        query = query.Where(s => s.ShippingAddress.ToLower().Contains(searchTerm) || 
                                s.TrackingNumber.ToLower().Contains(searchTerm) ||
                                s.OrderId.ToLower().Contains(searchTerm));
    }
    
    // Order ID filtering
    if (!string.IsNullOrEmpty(_params.OrderId))
    {
        query = query.Where(s => s.OrderId == _params.OrderId);
    }
    
    // Status filtering
    if (_params.Status.HasValue)
    {
        query = query.Where(s => s.Status == _params.Status.Value);
    }
    
    // Date range filtering
    if (_params.FromDate.HasValue)
    {
        query = query.Where(s => s.CreatedDate >= _params.FromDate.Value);
    }
    
    if (_params.ToDate.HasValue)
    {
        query = query.Where(s => s.CreatedDate <= _params.ToDate.Value);
    }
    
    // Dynamic sorting
    switch (_params.SortBy?.ToLower())
    {
        case "createddate":
            query = _params.SortDirection?.ToLower() == "asc" 
                ? query.OrderBy(s => s.CreatedDate)
                : query.OrderByDescending(s => s.CreatedDate);
            break;
        case "status":
            query = _params.SortDirection?.ToLower() == "asc" 
                ? query.OrderBy(s => s.Status)
                : query.OrderByDescending(s => s.Status);
            break;
        case "trackingnumber":
            query = _params.SortDirection?.ToLower() == "asc" 
                ? query.OrderBy(s => s.TrackingNumber)
                : query.OrderByDescending(s => s.TrackingNumber);
            break;
        default:
            query = query.OrderByDescending(s => s.CreatedDate);
            break;
    }
    
    return query;
}
```

## Pagination Metadata

### **FlexiPagedList Structure**

```csharp
public class FlexiPagedList<T>
{
    public IEnumerable<T> Items { get; set; }
    public int TotalCount { get; set; }
    public int PageNumber { get; set; }
    public int PageSize { get; set; }
    public int TotalPages { get; set; }
    public bool HasPreviousPage { get; set; }
    public bool HasNextPage { get; set; }
}
```

### **Frontend Integration Example**

```javascript
// Example frontend usage
const response = await fetch('/api/Shipping/GetShippingPagedList?pageNumber=1&pageSize=10&searchTerm=tracking');
const pagedData = await response.json();

console.log(`Total items: ${pagedData.totalCount}`);
console.log(`Page ${pagedData.pageNumber} of ${pagedData.totalPages}`);
console.log(`Items:`, pagedData.items);
```

## Performance Considerations

### **Optimization Strategies**

1. **Database Indexing**: Ensure proper indexes on filter and sort fields
2. **Selective Fields**: Only return necessary fields in DTO
3. **Query Optimization**: Use efficient WHERE clauses and sorting
4. **Page Size Limits**: Set reasonable maximum page sizes
5. **Caching**: Consider caching for frequently accessed data

### **When to Use Get Paged List vs Get List**

| Scenario                | Use Get Paged List | Use Get List |
| ----------------------- | ------------------ | ------------ |
| **Data Grids**          | ✅ Yes              | ❌ No         |
| **Large Datasets**      | ✅ Yes              | ❌ No         |
| **Admin Interfaces**    | ✅ Yes              | ❌ No         |
| **Reporting**           | ✅ Yes              | ❌ No         |
| **Dropdown Population** | ❌ No               | ✅ Yes        |
| **Lookup Tables**       | ❌ No               | ✅ Yes        |
| **Auto-complete**       | ❌ No               | ✅ Yes        |

## Error Handling

### **HTTP Status Codes**

* **200 OK**: Data retrieved successfully
* **400 Bad Request**: Invalid parameters (invalid page number, page size)
* **500 Internal Server Error**: Database or server error

### **Parameter Validation**

```csharp
[HttpGet()]
[Route("GetShippingPagedList")]
[ProducesResponseType(typeof(FlexiPagedList<GetShippingPagedListDto>), 200)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetShippingPagedList([FromQuery]GetShippingPagedListParams parameters)
{
    // Validate pagination parameters
    if (parameters.PageNumber < 1)
    {
        return BadRequest("Page number must be greater than 0");
    }
    
    if (parameters.PageSize < 1 || parameters.PageSize > 100)
    {
        return BadRequest("Page size must be between 1 and 100");
    }
    
    return RunQueryPagedService<GetShippingPagedListParams, GetShippingPagedListDto>(
                parameters, _processShippingService.GetShippingPagedList);
}
```

## Key Benefits

* **Performance**: Optimized for large datasets with pagination
* **Memory Efficiency**: Only loads required page of data
* **User Experience**: Smooth navigation through large datasets
* **Metadata**: Rich pagination information for frontend
* **Type Safety**: Strongly typed DTOs and parameters
* **AutoMapper**: Automatic entity-to-DTO mapping
* **No Side Effects**: Read-only operations
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This GetShippingPagedList example demonstrates how FlexBase enables clean, maintainable, and scalable paginated list operations optimized for data grids and large datasets!** 🚀


# Workflow State Machine

## Workflow State Machine

## YourApplication State Machine Pattern - Domain State Management

### 🚨 Why State Machines Are Essential: The Hidden Complexity Problem

#### **The State Management Nightmare**

Imagine you're building an e-commerce application. Your order can be in various states: `Created`, `Updated`, `PaymentInitiated`, `PaymentConfirmed`, `Shipped`, `Delivered`, `Cancelled`, `Refunded`.

**Without a State Machine, your code looks like this:**

```csharp
// ❌ NIGHTMARE: Complex if-else chains everywhere
public void UpdateOrder(Order order)
{
    if (order.Status == "Created" || order.Status == "Updated")
    {
        if (order.CustomerType == "Premium" && order.Amount < 1000)
        {
            // Allow update
        }
        else if (order.CustomerType == "Standard" && order.Amount < 500)
        {
            // Allow update with restrictions
        }
        else
        {
            throw new InvalidOperationException("Cannot update order");
        }
    }
    else if (order.Status == "PaymentInitiated")
    {
        throw new InvalidOperationException("Cannot update order after payment initiated");
    }
    else if (order.Status == "PaymentConfirmed")
    {
        throw new InvalidOperationException("Cannot update order after payment confirmed");
    }
    // ... 50+ more lines of complex conditions
}

public void ProcessPayment(Order order)
{
    if (order.Status == "Created" || order.Status == "Updated")
    {
        if (order.PaymentMethod == "CreditCard" && order.Amount > 0)
        {
            // Process payment
        }
        else
        {
            throw new InvalidOperationException("Invalid payment conditions");
        }
    }
    else if (order.Status == "PaymentInitiated")
    {
        throw new InvalidOperationException("Payment already initiated");
    }
    // ... more complex conditions
}
```

#### **The Problems with This Approach**

**1. Code Complexity Explosion 💥**

* **Exponential Growth**: Each new state multiplies the complexity
* **Nested Conditions**: Deep if-else chains become unreadable
* **Scattered Logic**: State rules spread across multiple methods
* **Maintenance Hell**: Changing one rule breaks multiple places

**2. Error-Prone Development ⚠️**

* **Missing Cases**: Easy to forget edge cases
* **Inconsistent Rules**: Same logic implemented differently
* **Silent Failures**: Invalid states not caught until runtime
* **Race Conditions**: Concurrent state changes cause bugs

**3. Business Evolution Nightmare 🔄**

* **New States**: Adding a state requires touching every method
* **Rule Changes**: Business rules change frequently
* **Role-Based Access**: Different users have different permissions
* **Workflow Modifications**: Process changes break existing code

**4. Testing Complexity 🧪**

* **Combinatorial Explosion**: Test every state × action combination
* **Mock Complexity**: Mock all possible state scenarios
* **Integration Issues**: State changes affect multiple systems
* **Regression Risk**: Changes break existing functionality

#### **The State Machine Solution: Elegant Simplicity** ✨

**With a State Machine, your code becomes:**

```csharp
// ✅ ELEGANT: Clean, maintainable, and self-documenting
public void UpdateOrder(Order order)
{
    // The state knows what it can do!
    if (!order.OrderState.CanUpdate)
    {
        throw new InvalidOperationException("Order cannot be updated in current state");
    }
    
    // Simple, clean logic
    order.OrderState = order.OrderState.Update();
    order.SetModified();
}

public void ProcessPayment(Order order)
{
    // The state handles the complexity!
    if (!order.OrderState.CanMakePayment)
    {
        throw new InvalidOperationException("Payment cannot be initiated in current state");
    }
    
    // Clean, simple logic
    order.OrderState = order.OrderState.MakePayment();
}
```

#### **Why State Machines Are Game-Changers** 🎯

**1. Self-Documenting Code 📚**

* **States Know Themselves**: Each state defines its own capabilities
* **Clear Intent**: Code reads like business requirements
* **No Hidden Logic**: All rules are explicit and visible
* **Business Language**: States match business terminology

**2. Bulletproof Validation 🛡️**

* **Compile-Time Safety**: Invalid transitions caught at compile time
* **Type Safety**: Each state is a distinct type
* **Impossible States**: Cannot create invalid state combinations
* **Consistent Rules**: Same validation everywhere

**3. Effortless Evolution 🚀**

* **Add New States**: Just create a new state class
* **Modify Rules**: Change state behavior in one place
* **Role-Based Access**: Built into the state machine
* **Workflow Changes**: Configuration-driven, not code changes

**4. Testing Made Simple 🧪**

* **Unit Test States**: Test each state independently
* **Clear Test Cases**: Each state has defined behavior
* **Mock-Free Testing**: States are pure objects
* **Regression Safety**: Changes are isolated and safe

#### **Real-World Impact: Before vs After** 📊

**Before State Machine:**

* **Lines of Code**: 500+ lines of complex conditionals
* **Bugs**: 15+ state-related bugs per month
* **Development Time**: 2 weeks to add a new state
* **Maintenance**: 80% of time spent fixing state issues
* **Business Changes**: 3 days to modify workflow rules

**After State Machine:**

* **Lines of Code**: 50 lines of clean, readable code
* **Bugs**: 0 state-related bugs
* **Development Time**: 2 hours to add a new state
* **Maintenance**: 20% of time spent on state management
* **Business Changes**: 30 minutes to modify workflow rules

#### **The Curious Question: How Does It Work?** 🤔

You might be wondering:

* **How do states know what they can do?**
* **How do we prevent invalid transitions?**
* **How do we handle complex business rules?**
* **How do we make it role-based and secure?**
* **How do we make it configurable without code changes?**

**The answer lies in the sophisticated State Machine pattern that FlexBase implements...**

***

### 🎯 State Machine Pattern in Domain-Driven Design

The Application created with Flexbase implements a sophisticated **State Machine pattern** within the Order domain model to ensure **business rule enforcement**, **state consistency**, and **workflow validation** throughout the order lifecycle.

***

### 🏗️ State Machine Architecture

#### **Core State Machine Components**

```csharp
// Base State Class - Defines State Interface
public class OrderWorkflowState : FlexState
{
    public virtual string FriendlyName => "";
    public virtual OrderWorkflowState Create() => this;
    public virtual OrderWorkflowState Update() => this;
    public virtual OrderWorkflowState MakePayment() => this;
    public virtual OrderWorkflowState ConfirmPayment() => this;

    public virtual bool CanUpdate { get; }
    public virtual bool CanConfirmPayment { get; }
}
```

#### **Order Domain Model Integration**

```csharp
public partial class Order : DomainModelBridge
{
    // State Machine Property - Encapsulates Order State
    public OrderWorkflowState OrderState { get; protected set; }
    
    // Domain Properties
    public DateTimeOffset OrderDate { get; protected set; }
    public string CustomerId { get; protected set; }
    public int TotalQty { get; protected set; }
    public decimal TotalAmount { get; protected set; }
    public ICollection<OrderItem> OrderItems { get; protected set; }
    public Payment Payment { get; protected set; }
}
```

***

### 🔄 Order Workflow States

#### **State Transition Diagram**

```mermaid
graph TD
    A[OrderIsCreated] -->|Update| B[OrderIsUpdated]
    A -->|MakePayment| C[PaymentInitiated]
    B -->|Update| B
    B -->|MakePayment| C
    C -->|ConfirmPayment| D[OrderPaymentIsConfirmed]
    
    A -.->|Cannot Confirm Payment| A
    C -.->|Cannot Update| C
    D -.->|Final State| D
```

#### **State Definitions**

**1. OrderIsCreated State**

```csharp
public class OrderIsCreated : OrderWorkflowState
{
    public OrderIsCreated()
    {
        this.SetAdded(); // Marks as new entity
    }
    
    // State Transitions
    public override OrderWorkflowState Update() => new OrderIsUpdated();
    public override OrderWorkflowState MakePayment() => new PaymentInitiated();
    public override OrderWorkflowState ConfirmPayment() => this; // No transition
    
    // State Capabilities
    public override bool CanUpdate { get; } = true;
    public override bool CanConfirmPayment { get; } = false;
}
```

**2. OrderIsUpdated State**

```csharp
public class OrderIsUpdated : OrderWorkflowState
{
    public OrderIsUpdated()
    {
        this.SetAdded(); // Marks as modified entity
    }
    
    // State Transitions
    public override OrderWorkflowState Update() => this; // Stay in same state
    public override OrderWorkflowState MakePayment() => new PaymentInitiated();
    public override OrderWorkflowState ConfirmPayment() => this; // No transition
    
    // State Capabilities
    public override bool CanUpdate { get; } = true;
    public override bool CanConfirmPayment { get; } = false;
}
```

**3. PaymentInitiated State**

```csharp
public class PaymentInitiated : OrderWorkflowState
{
    public PaymentInitiated()
    {
        this.SetAdded(); // Marks as modified entity
    }
    
    // State Transitions
    public override OrderWorkflowState Update() => this; // No transition allowed
    public override OrderWorkflowState MakePayment() => this; // No transition
    public override OrderWorkflowState ConfirmPayment() => new OrderPaymentIsConfirmed();
    
    // State Capabilities
    public override bool CanUpdate { get; } = false;
    public override bool CanConfirmPayment { get; } = true;
}
```

**4. OrderPaymentIsConfirmed State**

```csharp
public class OrderPaymentIsConfirmed : OrderWorkflowState
{
    public OrderPaymentIsConfirmed()
    {
        this.SetAdded(); // Marks as modified entity
    }
    
    // State Transitions - Final State
    public override OrderWorkflowState Create() => this;
    public override OrderWorkflowState Update() => this;
    public override OrderWorkflowState MakePayment() => this;
    public override OrderWorkflowState ConfirmPayment() => this;
    
    // State Capabilities - No further actions allowed
    public override bool CanUpdate { get; } = false;
    public override bool CanConfirmPayment { get; } = false;
}
```

***

### 🎯 State Machine Benefits

#### **1. Business Rule Enforcement**

**State-Based Validation**

```csharp
// Domain method can check state before allowing operations
public virtual Order UpdateOrder(UpdateOrderCommand cmd)
{
    // State validation - Business rule enforcement
    if (!OrderState.CanUpdate)
    {
        throw new InvalidOperationException("Order cannot be updated in current state");
    }
    
    // Proceed with update logic
    this.Convert(cmd.Dto);
    this.OrderState = this.OrderState.Update(); // State transition
    this.SetModified();
    
    return this;
}
```

**Workflow Validation**

```csharp
public virtual Order MakePayment(MakePaymentCommand cmd)
{
    // State validation - Workflow enforcement
    if (!OrderState.CanConfirmPayment && OrderState is PaymentInitiated)
    {
        throw new InvalidOperationException("Payment already initiated");
    }
    
    // Payment logic
    this.Payment = new Payment(cmd.Dto);
    this.OrderState = this.OrderState.MakePayment(); // State transition
    
    return this;
}
```

#### **2. State Consistency Guarantee**

**Immutable State Transitions**

* **Type Safety**: Each state is a distinct type
* **Compile-Time Validation**: Invalid transitions caught at compile time
* **State Encapsulation**: State logic contained within state classes
* **Transition Control**: Only valid transitions are allowed

**Domain Invariant Protection**

```csharp
// State machine ensures business invariants
public class OrderIsCreated : OrderWorkflowState
{
    // Cannot confirm payment before initiating it
    public override OrderWorkflowState ConfirmPayment() => this; // No transition
    
    // Cannot update after payment is initiated
    public override bool CanUpdate { get; } = true;
    public override bool CanConfirmPayment { get; } = false;
}
```

#### **3. Workflow Management**

**Clear Business Process**

* **Order Creation** → OrderIsCreated
* **Order Updates** → OrderIsUpdated (can continue updating)
* **Payment Initiation** → PaymentInitiated (no more updates)
* **Payment Confirmation** → OrderPaymentIsConfirmed (final state)

**State-Based Capabilities**

```csharp
// UI can check state capabilities
if (order.OrderState.CanUpdate)
{
    // Show update button
}

if (order.OrderState.CanConfirmPayment)
{
    // Show confirm payment button
}
```

***

### 🔧 Implementation Patterns

#### **1. State Pattern Implementation**

**Polymorphic State Behavior**

```csharp
// Each state implements its own behavior
public class OrderIsCreated : OrderWorkflowState
{
    public override OrderWorkflowState Update() => new OrderIsUpdated();
    public override OrderWorkflowState MakePayment() => new PaymentInitiated();
}

public class PaymentInitiated : OrderWorkflowState
{
    public override OrderWorkflowState Update() => this; // No transition
    public override OrderWorkflowState ConfirmPayment() => new OrderPaymentIsConfirmed();
}
```

**State Capability Queries**

```csharp
// Query state capabilities without side effects
public virtual bool CanPerformUpdate()
{
    return OrderState.CanUpdate;
}

public virtual bool CanPerformPaymentConfirmation()
{
    return OrderState.CanConfirmPayment;
}
```

#### **2. Domain Event Integration**

**State Transition Events**

```csharp
public virtual Order UpdateOrder(UpdateOrderCommand cmd)
{
    // Validate state
    if (!OrderState.CanUpdate)
    {
        throw new InvalidOperationException("Order cannot be updated");
    }
    
    // Perform update
    this.Convert(cmd.Dto);
    
    // State transition
    var previousState = OrderState;
    this.OrderState = this.OrderState.Update();
    
    // Publish domain event
    this.RaiseEvent(new OrderStateChangedEvent
    {
        OrderId = this.Id,
        PreviousState = previousState.GetType().Name,
        NewState = OrderState.GetType().Name,
        ChangedAt = DateTime.UtcNow
    });
    
    return this;
}
```

#### **3. Repository Integration**

**State Persistence**

```csharp
// Repository handles state persistence
public virtual async Task Execute(UpdateOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    // Get order from repository
    var order = _repoFactory.GetRepo().FindAll<Order>()
        .Where(o => o.Id == cmd.Dto.Id)
        .FirstOrDefault();
    
    if (order != null)
    {
        // State transition happens in domain
        order.UpdateOrder(cmd);
        
        // Persist state change
        _repoFactory.GetRepo().InsertOrUpdate(order);
        await _repoFactory.GetRepo().SaveAsync();
        
        // Publish events
        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

***

### 🚀 Advanced State Machine Features

#### **1. State History Tracking**

**State Transition History**

```csharp
public class Order : DomainModelBridge
{
    public OrderWorkflowState OrderState { get; protected set; }
    public List<OrderStateTransition> StateHistory { get; protected set; } = new List<OrderStateTransition>();
    
    protected virtual void TransitionTo(OrderWorkflowState newState, string reason)
    {
        var transition = new OrderStateTransition
        {
            FromState = OrderState?.GetType().Name,
            ToState = newState.GetType().Name,
            Reason = reason,
            Timestamp = DateTime.UtcNow,
            UserId = GetCurrentUserId()
        };
        
        StateHistory.Add(transition);
        OrderState = newState;
    }
}
```

#### **2. State-Based Business Rules**

**Complex State Validation**

```csharp
public class OrderIsUpdated : OrderWorkflowState
{
    public override OrderWorkflowState Update() 
    {
        // Additional business rules can be applied
        if (ShouldPreventFurtherUpdates())
        {
            return this; // Stay in current state
        }
        
        return new OrderIsUpdated();
    }
    
    private bool ShouldPreventFurtherUpdates()
    {
        // Complex business logic
        // e.g., Check if order has been pending too long
        // e.g., Check if customer has exceeded update limit
        return false;
    }
}
```

#### **3. Role-Based State Transitions**

**User Role Configuration for State Transitions**

```csharp
// Enhanced State Machine with Role-Based Access Control
public class OrderWorkflowState : FlexState
{
    public virtual string FriendlyName => "";
    public virtual OrderWorkflowState Create() => this;
    public virtual OrderWorkflowState Update() => this;
    public virtual OrderWorkflowState MakePayment() => this;
    public virtual OrderWorkflowState ConfirmPayment() => this;

    public virtual bool CanUpdate { get; }
    public virtual bool CanConfirmPayment { get; }
    
    // Role-based access control
    public virtual bool CanTransition(string userRole, string action)
    {
        return GetAllowedRoles(action).Contains(userRole);
    }
    
    protected virtual string[] GetAllowedRoles(string action)
    {
        return new string[0]; // Override in specific states
    }
}
```

**State-Specific Role Configuration**

```csharp
// OrderIsCreated State - Only Customer and Sales can update
public class OrderIsCreated : OrderWorkflowState
{
    public OrderIsCreated()
    {
        this.SetAdded();
    }
    
    public override OrderWorkflowState Update() => new OrderIsUpdated();
    public override OrderWorkflowState MakePayment() => new PaymentInitiated();
    public override OrderWorkflowState ConfirmPayment() => this;
    
    public override bool CanUpdate { get; } = true;
    public override bool CanConfirmPayment { get; } = false;
    
    protected override string[] GetAllowedRoles(string action)
    {
        return action switch
        {
            "Update" => new[] { "Customer", "Sales" },
            "MakePayment" => new[] { "Customer" },
            "ConfirmPayment" => new string[0], // Not allowed
            _ => new string[0]
        };
    }
}

// OrderIsUpdated State - Only Customer and Sales can continue updating
public class OrderIsUpdated : OrderWorkflowState
{
    public OrderIsUpdated()
    {
        this.SetAdded();
    }
    
    public override OrderWorkflowState Update() => this;
    public override OrderWorkflowState MakePayment() => new PaymentInitiated();
    public override OrderWorkflowState ConfirmPayment() => this;
    
    public override bool CanUpdate { get; } = true;
    public override bool CanConfirmPayment { get; } = false;
    
    protected override string[] GetAllowedRoles(string action)
    {
        return action switch
        {
            "Update" => new[] { "Customer", "Sales" },
            "MakePayment" => new[] { "Customer" },
            "ConfirmPayment" => new string[0], // Not allowed
            _ => new string[0]
        };
    }
}

// PaymentInitiated State - Only Finance can confirm payment
public class PaymentInitiated : OrderWorkflowState
{
    public PaymentInitiated()
    {
        this.SetAdded();
    }
    
    public override OrderWorkflowState Update() => this;
    public override OrderWorkflowState MakePayment() => this;
    public override OrderWorkflowState ConfirmPayment() => new OrderPaymentIsConfirmed();
    
    public override bool CanUpdate { get; } = false;
    public override bool CanConfirmPayment { get; } = true;
    
    protected override string[] GetAllowedRoles(string action)
    {
        return action switch
        {
            "Update" => new string[0], // Not allowed
            "MakePayment" => new string[0], // Not allowed
            "ConfirmPayment" => new[] { "Finance", "Admin" },
            _ => new string[0]
        };
    }
}

// OrderPaymentIsConfirmed State - No further transitions allowed
public class OrderPaymentIsConfirmed : OrderWorkflowState
{
    public OrderPaymentIsConfirmed()
    {
        this.SetAdded();
    }
    
    public override OrderWorkflowState Create() => this;
    public override OrderWorkflowState Update() => this;
    public override OrderWorkflowState MakePayment() => this;
    public override OrderWorkflowState ConfirmPayment() => this;
    
    public override bool CanUpdate { get; } = false;
    public override bool CanConfirmPayment { get; } = false;
    
    protected override string[] GetAllowedRoles(string action)
    {
        return new string[0]; // No transitions allowed
    }
}
```

**Role-Based Domain Method Implementation**

```csharp
// Enhanced Domain Method with Role Validation
public virtual Order UpdateOrder(UpdateOrderCommand cmd)
{
    // Role-based validation
    var userRole = cmd.Dto.GetAppContext()?.UserRole ?? "Guest";
    
    if (!OrderState.CanTransition(userRole, "Update"))
    {
        throw new UnauthorizedAccessException($"User role '{userRole}' cannot update order in current state");
    }
    
    // State validation
    if (!OrderState.CanUpdate)
    {
        throw new InvalidOperationException("Order cannot be updated in current state");
    }
    
    // Proceed with update logic
    this.Convert(cmd.Dto);
    this.OrderState = this.OrderState.Update();
    this.SetModified();
    
    return this;
}

public virtual Order MakePayment(MakePaymentCommand cmd)
{
    // Role-based validation
    var userRole = cmd.Dto.GetAppContext()?.UserRole ?? "Guest";
    
    if (!OrderState.CanTransition(userRole, "MakePayment"))
    {
        throw new UnauthorizedAccessException($"User role '{userRole}' cannot initiate payment in current state");
    }
    
    // State validation
    if (!OrderState.CanConfirmPayment && OrderState is PaymentInitiated)
    {
        throw new InvalidOperationException("Payment already initiated");
    }
    
    // Payment logic
    this.Payment = new Payment(cmd.Dto);
    this.OrderState = this.OrderState.MakePayment();
    
    return this;
}

public virtual Order ConfirmPayment(ConfirmPaymentCommand cmd)
{
    // Role-based validation
    var userRole = cmd.Dto.GetAppContext()?.UserRole ?? "Guest";
    
    if (!OrderState.CanTransition(userRole, "ConfirmPayment"))
    {
        throw new UnauthorizedAccessException($"User role '{userRole}' cannot confirm payment in current state");
    }
    
    // State validation
    if (!OrderState.CanConfirmPayment)
    {
        throw new InvalidOperationException("Payment cannot be confirmed in current state");
    }
    
    // Payment confirmation logic
    this.Payment.Confirm();
    this.OrderState = this.OrderState.ConfirmPayment();
    
    return this;
}
```

#### **4. Workflow Engine Configuration**

**Dynamic State Transition Configuration**

```csharp
// Workflow Configuration for Dynamic State Transitions
public class WorkflowConfiguration
{
    public string WorkflowName { get; set; }
    public List<StateTransitionRule> TransitionRules { get; set; } = new List<StateTransitionRule>();
    public List<WorkflowCondition> Conditions { get; set; } = new List<WorkflowCondition>();
}

public class StateTransitionRule
{
    public string FromState { get; set; }
    public string Action { get; set; }
    public string ToState { get; set; }
    public string[] AllowedRoles { get; set; }
    public string Condition { get; set; } // Optional condition for transition
    public bool IsAutomatic { get; set; } // For automatic transitions
}

public class WorkflowCondition
{
    public string Name { get; set; }
    public string Expression { get; set; }
    public string Description { get; set; }
}

// Enhanced State Machine with Workflow Configuration
public class OrderWorkflowState : FlexState
{
    protected static WorkflowConfiguration _workflowConfig;
    
    public virtual string FriendlyName => "";
    public virtual OrderWorkflowState Create() => this;
    public virtual OrderWorkflowState Update() => this;
    public virtual OrderWorkflowState MakePayment() => this;
    public virtual OrderWorkflowState ConfirmPayment() => this;

    public virtual bool CanUpdate { get; }
    public virtual bool CanConfirmPayment { get; }
    
    // Role-based access control
    public virtual bool CanTransition(string userRole, string action)
    {
        return GetAllowedRoles(action).Contains(userRole);
    }
    
    protected virtual string[] GetAllowedRoles(string action)
    {
        return new string[0]; // Override in specific states
    }
    
    // Workflow Engine Integration
    public virtual OrderWorkflowState GetNextState(string action, Dictionary<string, object> context = null)
    {
        var currentStateName = this.GetType().Name;
        var rule = _workflowConfig?.TransitionRules
            .FirstOrDefault(r => r.FromState == currentStateName && r.Action == action);
            
        if (rule == null)
        {
            return this; // No transition defined
        }
        
        // Check conditions if specified
        if (!string.IsNullOrEmpty(rule.Condition) && context != null)
        {
            if (!EvaluateCondition(rule.Condition, context))
            {
                return this; // Condition not met
            }
        }
        
        // Return next state based on configuration
        return CreateStateFromName(rule.ToState);
    }
    
    protected virtual bool EvaluateCondition(string condition, Dictionary<string, object> context)
    {
        // Simple condition evaluation - can be enhanced with expression engine
        return condition switch
        {
            "OrderAmount > 1000" => context.ContainsKey("OrderAmount") && 
                decimal.TryParse(context["OrderAmount"].ToString(), out var amount) && amount > 1000,
            "CustomerType == 'Premium'" => context.ContainsKey("CustomerType") && 
                context["CustomerType"].ToString() == "Premium",
            _ => true
        };
    }
    
    protected virtual OrderWorkflowState CreateStateFromName(string stateName)
    {
        return stateName switch
        {
            "OrderIsCreated" => new OrderIsCreated(),
            "OrderIsUpdated" => new OrderIsUpdated(),
            "PaymentInitiated" => new PaymentInitiated(),
            "OrderPaymentIsConfirmed" => new OrderPaymentIsConfirmed(),
            _ => this
        };
    }
}
```

**Workflow Configuration Examples**

```csharp
// Configure Order Workflow
public static void ConfigureOrderWorkflow()
{
    _workflowConfig = new WorkflowConfiguration
    {
        WorkflowName = "OrderProcessing",
        TransitionRules = new List<StateTransitionRule>
        {
            // Standard transitions
            new StateTransitionRule
            {
                FromState = "OrderIsCreated",
                Action = "Update",
                ToState = "OrderIsUpdated",
                AllowedRoles = new[] { "Customer", "Sales" }
            },
            new StateTransitionRule
            {
                FromState = "OrderIsCreated",
                Action = "MakePayment",
                ToState = "PaymentInitiated",
                AllowedRoles = new[] { "Customer" }
            },
            new StateTransitionRule
            {
                FromState = "OrderIsUpdated",
                Action = "Update",
                ToState = "OrderIsUpdated",
                AllowedRoles = new[] { "Customer", "Sales" }
            },
            new StateTransitionRule
            {
                FromState = "OrderIsUpdated",
                Action = "MakePayment",
                ToState = "PaymentInitiated",
                AllowedRoles = new[] { "Customer" }
            },
            new StateTransitionRule
            {
                FromState = "PaymentInitiated",
                Action = "ConfirmPayment",
                ToState = "OrderPaymentIsConfirmed",
                AllowedRoles = new[] { "Finance", "Admin" }
            },
            
            // Conditional transitions
            new StateTransitionRule
            {
                FromState = "OrderIsCreated",
                Action = "AutoApprove",
                ToState = "OrderPaymentIsConfirmed",
                AllowedRoles = new[] { "System" },
                Condition = "OrderAmount < 100",
                IsAutomatic = true
            },
            
            // Workflow-specific transitions
            new StateTransitionRule
            {
                FromState = "PaymentInitiated",
                Action = "RejectPayment",
                ToState = "OrderIsUpdated",
                AllowedRoles = new[] { "Finance" }
            }
        },
        Conditions = new List<WorkflowCondition>
        {
            new WorkflowCondition
            {
                Name = "OrderAmount > 1000",
                Expression = "OrderAmount > 1000",
                Description = "Order amount exceeds 1000"
            },
            new WorkflowCondition
            {
                Name = "CustomerType == 'Premium'",
                Expression = "CustomerType == 'Premium'",
                Description = "Customer is premium type"
            }
        }
    };
}
```

**Enhanced Domain Methods with Workflow Engine**

```csharp
// Enhanced Domain Method with Workflow Engine Integration
public virtual Order UpdateOrder(UpdateOrderCommand cmd)
{
    // Role-based validation
    var userRole = cmd.Dto.GetAppContext()?.UserRole ?? "Guest";
    
    if (!OrderState.CanTransition(userRole, "Update"))
    {
        throw new UnauthorizedAccessException($"User role '{userRole}' cannot update order in current state");
    }
    
    // State validation
    if (!OrderState.CanUpdate)
    {
        throw new InvalidOperationException("Order cannot be updated in current state");
    }
    
    // Proceed with update logic
    this.Convert(cmd.Dto);
    
    // Use workflow engine for state transition
    var context = new Dictionary<string, object>
    {
        ["OrderAmount"] = this.TotalAmount,
        ["CustomerType"] = this.Customer?.Type ?? "Standard"
    };
    
    this.OrderState = this.OrderState.GetNextState("Update", context);
    this.SetModified();
    
    return this;
}

public virtual Order ProcessWorkflowAction(string action, Dictionary<string, object> context = null)
{
    // Generic workflow action processing
    var userRole = context?["UserRole"]?.ToString() ?? "Guest";
    
    if (!OrderState.CanTransition(userRole, action))
    {
        throw new UnauthorizedAccessException($"User role '{userRole}' cannot perform '{action}' in current state");
    }
    
    // Get next state from workflow configuration
    var nextState = OrderState.GetNextState(action, context);
    
    if (nextState != OrderState) // State transition occurred
    {
        var previousState = OrderState;
        this.OrderState = nextState;
        
        // Publish state change event
        this.RaiseEvent(new OrderStateChangedEvent
        {
            OrderId = this.Id,
            PreviousState = previousState.GetType().Name,
            NewState = OrderState.GetType().Name,
            Action = action,
            ChangedAt = DateTime.UtcNow,
            Context = context
        });
    }
    
    return this;
}
```

**Workflow Engine Testing**

```csharp
[Test]
public void WorkflowEngine_ShouldTransitionBasedOnConfiguration()
{
    // Arrange
    ConfigureOrderWorkflow();
    var order = new Order();
    order.OrderState = new OrderIsCreated();
    
    var context = new Dictionary<string, object>
    {
        ["UserRole"] = "Customer",
        ["OrderAmount"] = 500m
    };
    
    // Act
    order.ProcessWorkflowAction("Update", context);
    
    // Assert
    Assert.IsInstanceOf<OrderIsUpdated>(order.OrderState);
}

[Test]
public void WorkflowEngine_ShouldRespectConditions()
{
    // Arrange
    ConfigureOrderWorkflow();
    var order = new Order();
    order.OrderState = new OrderIsCreated();
    order.TotalAmount = 50m; // Small amount for auto-approval
    
    var context = new Dictionary<string, object>
    {
        ["UserRole"] = "System",
        ["OrderAmount"] = order.TotalAmount
    };
    
    // Act
    order.ProcessWorkflowAction("AutoApprove", context);
    
    // Assert
    Assert.IsInstanceOf<OrderPaymentIsConfirmed>(order.OrderState);
}

[Test]
public void WorkflowEngine_ShouldNotTransitionWhenConditionNotMet()
{
    // Arrange
    ConfigureOrderWorkflow();
    var order = new Order();
    order.OrderState = new OrderIsCreated();
    order.TotalAmount = 1500m; // Large amount - no auto-approval
    
    var context = new Dictionary<string, object>
    {
        ["UserRole"] = "System",
        ["OrderAmount"] = order.TotalAmount
    };
    
    // Act
    order.ProcessWorkflowAction("AutoApprove", context);
    
    // Assert
    Assert.IsInstanceOf<OrderIsCreated>(order.OrderState); // No transition
}
```

#### **5. State Machine Testing**

**Unit Testing States with Role Validation**

```csharp
[Test]
public void OrderIsCreated_ShouldAllowCustomerToUpdate()
{
    // Arrange
    var state = new OrderIsCreated();
    
    // Act & Assert
    Assert.IsTrue(state.CanTransition("Customer", "Update"));
    Assert.IsTrue(state.CanTransition("Sales", "Update"));
    Assert.IsFalse(state.CanTransition("Finance", "Update"));
    Assert.IsFalse(state.CanTransition("Admin", "Update"));
}

[Test]
public void OrderIsCreated_ShouldOnlyAllowCustomerToMakePayment()
{
    // Arrange
    var state = new OrderIsCreated();
    
    // Act & Assert
    Assert.IsTrue(state.CanTransition("Customer", "MakePayment"));
    Assert.IsFalse(state.CanTransition("Sales", "MakePayment"));
    Assert.IsFalse(state.CanTransition("Finance", "MakePayment"));
}

[Test]
public void PaymentInitiated_ShouldOnlyAllowFinanceToConfirmPayment()
{
    // Arrange
    var state = new PaymentInitiated();
    
    // Act & Assert
    Assert.IsTrue(state.CanTransition("Finance", "ConfirmPayment"));
    Assert.IsTrue(state.CanTransition("Admin", "ConfirmPayment"));
    Assert.IsFalse(state.CanTransition("Customer", "ConfirmPayment"));
    Assert.IsFalse(state.CanTransition("Sales", "ConfirmPayment"));
}

[Test]
public void OrderPaymentIsConfirmed_ShouldNotAllowAnyTransitions()
{
    // Arrange
    var state = new OrderPaymentIsConfirmed();
    
    // Act & Assert
    Assert.IsFalse(state.CanTransition("Customer", "Update"));
    Assert.IsFalse(state.CanTransition("Sales", "Update"));
    Assert.IsFalse(state.CanTransition("Finance", "ConfirmPayment"));
    Assert.IsFalse(state.CanTransition("Admin", "ConfirmPayment"));
}
```

***

### 📊 State Machine Benefits Summary

#### **1. Business Value**

* **Workflow Enforcement** - Ensures orders follow proper business process
* **Data Integrity** - Prevents invalid state transitions
* **Business Rule Compliance** - Enforces complex business logic
* **Role-Based Security** - Controls who can perform state transitions
* **Dynamic Workflow Configuration** - Configure state transitions without code changes
* **Conditional Transitions** - Business rules drive automatic state changes
* **Audit Trail** - Tracks state changes for compliance

#### **2. Technical Benefits**

* **Type Safety** - Compile-time validation of state transitions
* **Maintainability** - Clear separation of state logic
* **Testability** - Each state can be tested independently
* **Extensibility** - Easy to add new states and transitions
* **Security Integration** - Role-based access control built into state machine
* **Configuration-Driven** - Workflow rules defined in configuration, not code
* **Expression Engine** - Dynamic condition evaluation for business rules

#### **3. Domain-Driven Design Alignment**

* **Rich Domain Models** - State behavior encapsulated in domain
* **Business Language** - States reflect business concepts
* **Invariant Protection** - Business rules enforced at domain level
* **Event-Driven** - State changes can trigger domain events

***

### 🎯 Key Takeaways

#### **State Machine Pattern Success**

The YourApplication solution demonstrates **enterprise-grade state management** through:

1. **Business Rule Enforcement** - States prevent invalid operations
2. **Workflow Management** - Clear order lifecycle management
3. **Type Safety** - Compile-time validation of state transitions
4. **Domain Integration** - State machine integrated with domain model
5. **Event-Driven Architecture** - State changes trigger domain events

#### **Domain Model Benefits**

* **Consistent State** - Order state is always valid
* **Business Logic Encapsulation** - State rules in domain layer
* **Workflow Validation** - Prevents invalid business operations
* **Audit Capability** - Complete state transition history
* **Maintainable Code** - Clear separation of state concerns

***

*This document showcases how the YourApplication solution implements the State Machine pattern within the Order domain model to ensure business rule enforcement, state consistency, and workflow validation throughout the order lifecycle.*


# Unit Testing

FlexBase is designed from the ground up to be testable. The framework provides clear separation of concerns, making it easy to write focused unit tests for each layer of your application.

## Why FlexBase Testing is Different

Traditional enterprise applications often have tightly coupled components that are difficult to test in isolation. FlexBase solves this through:

| Challenge                  | FlexBase Solution                                          |
| -------------------------- | ---------------------------------------------------------- |
| Tightly coupled components | Clear layer separation (Domain, PreBus, Handlers, Queries) |
| Database dependencies      | InMemory EF Core with `InMemoryRepoFactory`                |
| Service locator patterns   | Dependency injection with `FlexHostMock`                   |
| Complex setup requirements | Reusable fixtures and seed data                            |
| Hard to mock dependencies  | Interface-based design (`IRepoFactory`, `IFlexHost`)       |

## Testing Layers

FlexBase applications have four primary testing layers:

```
┌─────────────────────────────────────────────────────────────┐
│                    Test Layer Overview                       │
├─────────────────────────────────────────────────────────────┤
│  1. Domain Model Tests     - Business logic, no DB needed   │
│  2. PreBus Validation Tests - Rules with InMemory database  │
│  3. Query Tests            - Read operations, verify fetches │
│  4. Handler Tests          - Command orchestration (optional)│
└─────────────────────────────────────────────────────────────┘
```

### 1. Domain Model Tests

Test pure business logic without any database. Uses `FlexHostMock` to get domain model instances.

**What to test:** CreateX, UpdateX, DeleteX methods, property mapping, validation guards.

### 2. PreBus Validation Tests

Test validation plugins (business rules) with InMemory EF Core. Each plugin is tested in isolation.

**What to test:** Existence checks (CategoryExists, ProductTypeExists), uniqueness (SlugUnique), value validation.

### 3. Query Tests

Test read operations against InMemory database with seed data.

**What to test:** Fetch operations, null handling for missing records, property mapping from entities to DTOs.

### 4. Handler Tests (Optional)

For complex orchestration scenarios. Often the combination of domain model + validation tests provides sufficient coverage.

## Quick Start

See the [xUnit Guide](/solution-structure/getting-started/unit-testing/xunit) for detailed setup instructions and code examples.

## Key Components

| Component                        | Purpose                                  | NuGet Package                    |
| -------------------------------- | ---------------------------------------- | -------------------------------- |
| `FlexHostMock`                   | Test-friendly `IFlexHost` implementation | Sumeru.Flex.Core                 |
| `InMemoryRepoFactory`            | InMemory EF Core repository factory      | Your `.Testing.InMemory` project |
| `ApplicationEFInMemoryDbContext` | InMemory DbContext with seed data        | Your `.Testing.InMemory` project |

## Recommended Test Project Structure

```
YourApp/
├── Domain/
│   └── YourApp.DomainModels.Tests/
│       ├── Fixtures/
│       │   └── FlexHostMockFixture.cs
│       └── Product/
│           └── ProductDomainModelTests.cs
├── DomainHandler/
│   ├── YourApp.PreBus.Tests/
│   │   ├── Fixtures/
│   │   └── Products/Validations/
│   │       ├── SlugUniqueValidationTests.cs
│   │       └── CategoryExistsValidationTests.cs
│   ├── YourApp.Queries.Tests/
│   │   ├── Fixtures/
│   │   │   └── QueryTestFixture.cs
│   │   └── Products/
│   │       └── GetProductByIdTests.cs
│   └── YourApp.Handlers.Tests/
│       └── (Optional - for complex scenarios)
└── Infrastructure/
    └── YourApp.Testing.InMemory/
        ├── InMemoryRepoFactory.cs
        ├── ApplicationEFInMemoryDbContext.cs
        └── SeedData/
            ├── ProductType_SeedData.cs
            ├── Category_SeedData.cs
            └── Product_SeedData.cs
```

## Best Practices

1. **Use unique database names** - Each test class should use `Guid.NewGuid()` in the database name to ensure isolation
2. **Leverage seed data** - Create realistic seed data once, reference it in all tests
3. **Use xUnit collection fixtures** - Share expensive setup (like FlexHostMock) across test classes
4. **Test one thing per test** - Each test should verify a single behavior
5. **Use FluentAssertions** - Makes assertions readable and provides helpful error messages

## Next Steps

* [xUnit Testing Guide](/solution-structure/getting-started/unit-testing/xunit) - Complete setup and examples
* [ECommerz Sample Tests](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/samples/ecommerz/testing/README.md) - Real-world examples


# xUnit

This guide provides complete examples for testing FlexBase applications using xUnit, FluentAssertions, and InMemory EF Core.

## Prerequisites

### NuGet Packages

Add these packages to your test projects:

```xml
<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.x" />
  <PackageReference Include="xunit" Version="2.x" />
  <PackageReference Include="xunit.runner.visualstudio" Version="2.x" />
  <PackageReference Include="FluentAssertions" Version="6.x" />
  <PackageReference Include="Moq" Version="4.x" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.x" />
</ItemGroup>
```

***

## Part 1: Domain Model Tests

Domain model tests verify pure business logic without any database dependencies. They use `FlexHostMock` to create domain model instances with proper dependency injection.

### Setting Up FlexHostMockFixture

Create a shared fixture to configure `FlexHostMock` with AutoMapper and domain model registrations:

```csharp
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Sumeru.Flex;
using YourApp.ProductsModule;
using Xunit;

namespace YourApp.DomainModels.Tests.Fixtures;

/// <summary>
/// Shared fixture that configures FlexHostMock with AutoMapper and domain model registrations.
/// </summary>
public class FlexHostMockFixture : IDisposable
{
    public IFlexHost FlexHost { get; }
    public IServiceProvider ServiceProvider { get; }

    public FlexHostMockFixture()
    {
        var services = new ServiceCollection();

        // Register AutoMapper with all mapper profiles
        services.AddAutoMapper(cfg =>
        {
            cfg.AddProfile<CreateProductMapperConfiguration>();
            cfg.AddProfile<UpdateProductMapperConfiguration>();
            cfg.AddProfile<DeleteProductMapperConfiguration>();
        }, typeof(Product).Assembly, typeof(CreateProductMapperConfiguration).Assembly);

        // Register loggers using NullLoggerFactory for tests
        services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
        services.AddSingleton(typeof(ILogger<>), typeof(NullLogger<>));

        // Register domain models
        services.AddTransient<Product>(sp =>
        {
            var logger = sp.GetRequiredService<ILogger<Product>>();
            return new Product(logger);
        });

        // Build the service provider
        ServiceProvider = services.BuildServiceProvider();

        // Create FlexHostMock and configure it
        var flexHostMock = new FlexHostMock();
        flexHostMock.SetServiceCollection(services);
        flexHostMock.SetServiceProvider(ServiceProvider);
        FlexHost = flexHostMock;
    }

    public void Dispose()
    {
        if (ServiceProvider is IDisposable disposable)
        {
            disposable.Dispose();
        }
    }
}

/// <summary>
/// Collection definition for sharing FlexHostMockFixture across test classes.
/// </summary>
[CollectionDefinition("FlexHostMock")]
public class FlexHostMockCollection : ICollectionFixture<FlexHostMockFixture>
{
}
```

### Writing Domain Model Tests

```csharp
using FluentAssertions;
using Sumeru.Flex;
using YourApp.ProductsModule;
using YourApp.DomainModels.Tests.Fixtures;
using Xunit;

namespace YourApp.DomainModels.Tests.Products;

/// <summary>
/// Unit tests for the Product domain model.
/// Tests CreateProduct, UpdateProduct, and DeleteProduct operations.
/// </summary>
[Collection("FlexHostMock")]
public class ProductDomainModelTests
{
    private readonly FlexHostMockFixture _fixture;

    public ProductDomainModelTests(FlexHostMockFixture fixture)
    {
        _fixture = fixture;
    }

    #region CreateProduct Tests

    [Fact]
    public void CreateProduct_WithValidCommand_ShouldSetAllProperties()
    {
        // Arrange
        var product = _fixture.FlexHost.GetDomainModel<Product>();
        var dto = new CreateProductDto
        {
            Name = "Test Product",
            Slug = "test-product",
            ProductTypeId = "pt-001"
        };
        var command = new CreateProductCommand { Dto = dto };

        // Act
        var result = product.CreateProduct(command);

        // Assert
        result.Should().NotBeNull();
        result.Should().BeSameAs(product);
        result.Name.Should().Be(dto.Name);
        result.Slug.Should().Be(dto.Slug);
        result.ProductTypeId.Should().Be(dto.ProductTypeId);
    }

    [Fact]
    public void CreateProduct_WithOptionalFields_ShouldMapCorrectly()
    {
        // Arrange
        var product = _fixture.FlexHost.GetDomainModel<Product>();
        var dto = new CreateProductDto
        {
            Name = "Test Product",
            Slug = "test-product",
            ProductTypeId = "pt-001",
            Description = "Test description in EditorJS format",
            DescriptionPlaintext = "Test description plain text",
            CategoryId = "cat-123",
            Weight = 1.5m,
            ExternalReference = "ext-ref-001"
        };
        var command = new CreateProductCommand { Dto = dto };

        // Act
        var result = product.CreateProduct(command);

        // Assert
        result.Description.Should().Be(dto.Description);
        result.DescriptionPlaintext.Should().Be(dto.DescriptionPlaintext);
        result.CategoryId.Should().Be(dto.CategoryId);
        result.Weight.Should().Be(dto.Weight);
        result.ExternalReference.Should().Be(dto.ExternalReference);
    }

    [Fact]
    public void CreateProduct_WithNullCommand_ShouldThrowGuardException()
    {
        // Arrange
        var product = _fixture.FlexHost.GetDomainModel<Product>();

        // Act
        Action act = () => product.CreateProduct(null!);

        // Assert
        act.Should().Throw<Exception>()
           .WithMessage("*command cannot be empty*");
    }

    [Fact]
    public void CreateProduct_ShouldSetCreatedByFromAppContext()
    {
        // Arrange
        var product = _fixture.FlexHost.GetDomainModel<Product>();
        var dto = new CreateProductDto
        {
            Name = "Test Product",
            Slug = "test-product",
            ProductTypeId = "pt-001"
        };
        
        var userId = "user-123";
        var appContext = new FlexAppContextBridge { UserId = userId };
        dto.SetAppContext(appContext);
        
        var command = new CreateProductCommand { Dto = dto };

        // Act
        var result = product.CreateProduct(command);

        // Assert
        result.CreatedBy.Should().Be(userId);
        result.LastModifiedBy.Should().Be(userId);
    }

    #endregion

    #region UpdateProduct Tests

    [Fact]
    public void UpdateProduct_WithValidCommand_ShouldUpdateProperties()
    {
        // Arrange
        var product = _fixture.FlexHost.GetDomainModel<Product>();
        
        // First create the product
        var createDto = new CreateProductDto
        {
            Name = "Original Name",
            Slug = "original-slug",
            ProductTypeId = "pt-001"
        };
        createDto.SetAppContext(new FlexAppContextBridge { UserId = "creator" });
        product.CreateProduct(new CreateProductCommand { Dto = createDto });

        // Now update it
        var updateDto = new UpdateProductDto
        {
            Id = product.Id,
            Name = "Updated Name",
            Slug = "updated-slug"
        };
        updateDto.SetAppContext(new FlexAppContextBridge { UserId = "updater" });
        var updateCommand = new UpdateProductCommand { Dto = updateDto };

        // Act
        var result = product.UpdateProduct(updateCommand);

        // Assert
        result.Name.Should().Be("Updated Name");
        result.Slug.Should().Be("updated-slug");
        result.LastModifiedBy.Should().Be("updater");
    }

    #endregion
}
```

***

## Part 2: PreBus Validation Tests

PreBus validation tests verify your business rule plugins. These tests use `InMemoryRepoFactory` to provide a real (but in-memory) database with seed data.

### Setting Up InMemoryRepoFactory

Create an InMemory repository factory that uses EF Core's InMemory provider:

```csharp
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Sumeru.Flex;

namespace YourApp.Testing;

/// <summary>
/// InMemory RepoFactory for testing purposes.
/// Replaces the standard RepoFactory to use InMemory EF Core repositories.
/// </summary>
public class InMemoryRepoFactory : IRepoFactory, IDisposable
{
    private bool _disposed = false;
    private IFlexRepositoryBridge? _repo;
    private readonly string _databaseName;
    private readonly ILoggerFactory _loggerFactory;

    public InMemoryRepoFactory(string? databaseName = null, ILoggerFactory? loggerFactory = null)
    {
        // Use unique database name per test to ensure isolation
        _databaseName = databaseName ?? $"TestDb_{Guid.NewGuid():N}";
        _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
    }

    public IRepoFactory Init(DtoBridge dto)
    {
        InitializeRepo(ConnectionType.WriteDb);
        return this;
    }

    public IRepoFactory Init(PagedQueryParamsDtoBridge dto)
    {
        InitializeRepo(ConnectionType.ReadDb);
        return this;
    }

    private void InitializeRepo(ConnectionType type)
    {
        var connectionProvider = new InMemoryConnectionProvider(_databaseName);

        if (type == ConnectionType.ReadDb)
        {
            var logger = _loggerFactory.CreateLogger<FlexReadDbRepositoryEFInMemory>();
            var repo = new FlexReadDbRepositoryEFInMemory(logger, _databaseName);
            repo.InitializeConnection(connectionProvider);
            _repo = (IFlexRepositoryBridge)repo;
        }
        else
        {
            var logger = _loggerFactory.CreateLogger<FlexWriteDbRepositoryEFInMemory>();
            var repo = new FlexWriteDbRepositoryEFInMemory(logger, _databaseName);
            repo.InitializeConnection(connectionProvider);
            _repo = repo;
        }
    }

    public IFlexRepositoryBridge GetRepo() => _repo!;

    public void Dispose()
    {
        _disposed = true;
        // InMemory database is automatically cleaned up when all references are released
    }
}
```

### Setting Up Seed Data

Create seed data classes that are applied when the InMemory database is created:

```csharp
using Microsoft.EntityFrameworkCore;

namespace YourApp.Testing.SeedData;

public static class Category_SeedData
{
    public static void Seed(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Category>().HasData(
            new Category
            {
                Id = "cat-electronics",
                Name = "Electronics",
                Slug = "electronics",
                Lft = 1,
                Rght = 6,
                TreeId = 1,
                Level = 0
            },
            new Category
            {
                Id = "cat-computers",
                Name = "Computers",
                Slug = "computers",
                ParentId = "cat-electronics",
                Lft = 2,
                Rght = 3,
                TreeId = 1,
                Level = 1
            }
        );
    }
}

public static class ProductType_SeedData
{
    public static void Seed(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ProductType>().HasData(
            new ProductType
            {
                Id = "pt-physical",
                Name = "Physical Product",
                Slug = "physical-product",
                Kind = "NORMAL",
                HasVariants = true,
                IsShippingRequired = true,
                IsDigital = false
            },
            new ProductType
            {
                Id = "pt-electronics",
                Name = "Electronics",
                Slug = "electronics",
                Kind = "NORMAL"
            }
        );
    }
}

public static class Product_SeedData
{
    public static void Seed(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().HasData(
            new Product
            {
                Id = "prod-001",
                Name = "MacBook Pro 16-inch M3 Max",
                Slug = "macbook-pro-16-m3-max",
                ProductTypeId = "pt-electronics",
                CategoryId = "cat-computers",
                Description = "{\"blocks\":[{\"type\":\"paragraph\",\"data\":{\"text\":\"Powerful laptop\"}}]}",
                DescriptionPlaintext = "Powerful laptop with M3 Max chip",
                Weight = 2.14m,
                Rating = 4.8m
            }
        );
    }
}
```

### Writing Validation Tests

```csharp
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Moq;
using Sumeru.Flex;
using YourApp.ProductsModule;
using YourApp.ProductsModule.CreateProductProductsPlugins;
using YourApp.Testing;
using Xunit;

namespace YourApp.PreBus.Tests.Products.Validations;

/// <summary>
/// Unit tests for CategoryExists validation plugin.
/// Tests that the CategoryId references an existing category.
/// Uses seed data which includes "cat-electronics".
/// </summary>
public class CategoryExistsValidationTests : IDisposable
{
    private readonly string _databaseName;
    private readonly Mock<ILoggerFactory> _mockLoggerFactory;
    private readonly Mock<ILogger<CategoryExists>> _mockLogger;
    private readonly InMemoryRepoFactory _repoFactory;

    public CategoryExistsValidationTests()
    {
        // Use unique database name per test class for isolation
        _databaseName = $"CategoryExistsTest_{Guid.NewGuid():N}";
        _mockLoggerFactory = new Mock<ILoggerFactory>();
        _mockLogger = new Mock<ILogger<CategoryExists>>();
        _mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
            .Returns(Mock.Of<ILogger>());
        _repoFactory = new InMemoryRepoFactory(_databaseName, _mockLoggerFactory.Object);
    }

    public void Dispose()
    {
        _repoFactory?.Dispose();
    }

    private CreateProductDataPacket CreateDataPacket(string? categoryId)
    {
        var dto = new CreateProductDto
        {
            Name = "Test Product",
            Slug = $"test-product-{Guid.NewGuid():N}",
            ProductTypeId = "pt-physical",
            CategoryId = categoryId
        };
        dto.SetAppContext(new FlexAppContextBridge { UserId = "test-user" });

        var mockPacketLogger = new Mock<ILogger<CreateProductDataPacket>>();
        var packet = new CreateProductDataPacket(mockPacketLogger.Object);
        packet.Dto = dto;
        return packet;
    }

    [Fact]
    public async Task Validate_WithExistingCategory_ShouldPass()
    {
        // Arrange - Use category from seed data
        var validation = new CategoryExists(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket("cat-electronics");

        // Act
        await validation.Validate(packet);

        // Assert
        packet.HasError.Should().BeFalse();
    }

    [Fact]
    public async Task Validate_WithNonExistentCategory_ShouldAddError()
    {
        // Arrange
        var validation = new CategoryExists(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket("non-existent-category-id");

        // Act
        await validation.Validate(packet);

        // Assert
        packet.HasError.Should().BeTrue();
        packet.Errors().Should().ContainKey("CategoryId");
    }

    [Fact]
    public async Task Validate_WithNullCategoryId_ShouldPass()
    {
        // Arrange - Category is optional
        var validation = new CategoryExists(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket(null);

        // Act
        await validation.Validate(packet);

        // Assert - Null category is valid (it's optional)
        packet.HasError.Should().BeFalse();
    }

    [Fact]
    public async Task Validate_WithEmptyCategoryId_ShouldPass()
    {
        // Arrange - Empty string should be treated as no category
        var validation = new CategoryExists(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket("");

        // Act
        await validation.Validate(packet);

        // Assert - Empty category is valid (it's optional)
        packet.HasError.Should().BeFalse();
    }

    [Fact]
    public async Task Validate_WithWhitespaceCategoryId_ShouldPass()
    {
        // Arrange
        var validation = new CategoryExists(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket("   ");

        // Act
        await validation.Validate(packet);

        // Assert - Whitespace should be treated as empty
        packet.HasError.Should().BeFalse();
    }
}
```

### Testing SlugUnique Validation

```csharp
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Moq;
using Sumeru.Flex;
using YourApp.ProductsModule;
using YourApp.ProductsModule.CreateProductProductsPlugins;
using YourApp.Testing;
using Xunit;

namespace YourApp.PreBus.Tests.Products.Validations;

/// <summary>
/// Unit tests for SlugUnique validation plugin.
/// Ensures product slugs are unique across the catalog.
/// Uses seed data which includes product with slug "macbook-pro-16-m3-max".
/// </summary>
public class SlugUniqueValidationTests : IDisposable
{
    private readonly string _databaseName;
    private readonly Mock<ILoggerFactory> _mockLoggerFactory;
    private readonly Mock<ILogger<SlugUnique>> _mockLogger;
    private readonly InMemoryRepoFactory _repoFactory;

    public SlugUniqueValidationTests()
    {
        _databaseName = $"SlugUniqueTest_{Guid.NewGuid():N}";
        _mockLoggerFactory = new Mock<ILoggerFactory>();
        _mockLogger = new Mock<ILogger<SlugUnique>>();
        _mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
            .Returns(Mock.Of<ILogger>());
        _repoFactory = new InMemoryRepoFactory(_databaseName, _mockLoggerFactory.Object);
    }

    public void Dispose() => _repoFactory?.Dispose();

    private CreateProductDataPacket CreateDataPacket(string slug)
    {
        var dto = new CreateProductDto
        {
            Name = "Test Product",
            Slug = slug,
            ProductTypeId = "pt-physical"
        };
        dto.SetAppContext(new FlexAppContextBridge { UserId = "test-user" });

        var mockPacketLogger = new Mock<ILogger<CreateProductDataPacket>>();
        var packet = new CreateProductDataPacket(mockPacketLogger.Object);
        packet.Dto = dto;
        return packet;
    }

    [Fact]
    public async Task Validate_WithUniqueSlug_ShouldPass()
    {
        // Arrange
        var validation = new SlugUnique(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket($"unique-slug-{Guid.NewGuid():N}");

        // Act
        await validation.Validate(packet);

        // Assert
        packet.HasError.Should().BeFalse();
    }

    [Fact]
    public async Task Validate_WithExistingSlug_ShouldAddError()
    {
        // Arrange - Use slug from seed data
        var validation = new SlugUnique(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket("macbook-pro-16-m3-max");

        // Act
        await validation.Validate(packet);

        // Assert
        packet.HasError.Should().BeTrue();
        packet.Errors().Should().ContainKey("Slug");
    }

    [Fact]
    public async Task Validate_WithNullSlug_ShouldPass()
    {
        // Arrange - Null/empty slug will be auto-generated later
        var validation = new SlugUnique(_mockLogger.Object, _repoFactory);
        var packet = CreateDataPacket(null!);

        // Act
        await validation.Validate(packet);

        // Assert
        packet.HasError.Should().BeFalse();
    }
}
```

***

## Part 3: Query Tests

Query tests verify that your read operations correctly fetch data from the database. They use InMemory EF Core with seed data.

### Setting Up QueryTestFixture

```csharp
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using YourApp.ProductsModule;
using YourApp.Testing;
using Xunit;

namespace YourApp.Queries.Tests.Fixtures;

/// <summary>
/// Shared fixture for Query tests with FlexHostMock and InMemory repository.
/// </summary>
public class QueryTestFixture : IDisposable
{
    public IFlexHost FlexHost { get; }
    public IServiceProvider ServiceProvider { get; }
    public string DatabaseName { get; }

    public QueryTestFixture()
    {
        // Use unique database name per fixture instance
        DatabaseName = $"QueryTestDb_{Guid.NewGuid():N}";
        
        var services = new ServiceCollection();

        // Register AutoMapper
        services.AddAutoMapper(cfg =>
        {
            cfg.AddProfile<CreateProductMapperConfiguration>();
            cfg.AddProfile<UpdateProductMapperConfiguration>();
        }, typeof(Product).Assembly);

        // Register logging
        services.AddLogging();

        // Register domain models
        services.AddTransient<Product>(sp =>
        {
            var logger = sp.GetRequiredService<ILogger<Product>>();
            return new Product(logger);
        });

        // Register InMemory RepoFactory
        services.AddScoped<IRepoFactory>(sp => 
            new InMemoryRepoFactory(DatabaseName, sp.GetRequiredService<ILoggerFactory>()));

        ServiceProvider = services.BuildServiceProvider();

        // Configure FlexContainer (required by some FlexBase internals)
        FlexContainer.ServiceCollection = services;
        FlexContainer.ServiceProvider = ServiceProvider;

        // Create FlexHostMock
        var flexHostMock = new FlexHostMock();
        flexHostMock.SetServiceCollection(services);
        flexHostMock.SetServiceProvider(ServiceProvider);
        FlexHost = flexHostMock;
    }

    /// <summary>
    /// Creates a new InMemoryRepoFactory with the same database name.
    /// </summary>
    public IRepoFactory CreateRepoFactory()
    {
        return new InMemoryRepoFactory(DatabaseName, ServiceProvider.GetRequiredService<ILoggerFactory>());
    }

    /// <summary>
    /// Creates a GetProductById query for testing.
    /// </summary>
    public GetProductById CreateGetProductByIdQuery()
    {
        var logger = ServiceProvider.GetRequiredService<ILogger<GetProductById>>();
        var repoFactory = CreateRepoFactory();
        return new GetProductById(logger, repoFactory);
    }

    /// <summary>
    /// Seeds a product into the database for testing.
    /// </summary>
    public async Task<Product> SeedProductAsync(string? id = null, string? name = null)
    {
        var product = FlexHost.GetDomainModel<Product>();
        var dto = new CreateProductDto
        {
            Name = name ?? $"Seeded Product {Guid.NewGuid():N}",
            Slug = $"seeded-product-{Guid.NewGuid():N}",
            ProductTypeId = "pt-001"
        };
        
        var appContext = new FlexAppContextBridge { UserId = "seed-user" };
        dto.SetAppContext(appContext);
        dto.SetGeneratedId(id ?? $"prod-{Guid.NewGuid():N}");
        
        var command = new CreateProductCommand { Dto = dto };
        product.CreateProduct(command);

        var repoFactory = CreateRepoFactory();
        repoFactory.Init(dto);
        repoFactory.GetRepo().InsertOrUpdate(product);
        await repoFactory.GetRepo().SaveAsync();

        return product;
    }

    public void Dispose()
    {
        if (ServiceProvider is IDisposable disposable)
        {
            disposable.Dispose();
        }
    }
}

[CollectionDefinition("QueryTests")]
public class QueryTestCollection : ICollectionFixture<QueryTestFixture>
{
}
```

### Writing Query Tests

```csharp
using FluentAssertions;
using Sumeru.Flex;
using YourApp.ProductsModule;
using YourApp.Queries.Tests.Fixtures;
using Xunit;

namespace YourApp.Queries.Tests.Products;

/// <summary>
/// Unit tests for GetProductById query.
/// Tests retrieval from InMemory EF Core database.
/// </summary>
[Collection("QueryTests")]
public class GetProductByIdTests
{
    private readonly QueryTestFixture _fixture;

    public GetProductByIdTests(QueryTestFixture fixture)
    {
        _fixture = fixture;
    }

    [Fact]
    public async Task Fetch_WithSeedDataProductId_ShouldReturnProductFromDatabase()
    {
        // Arrange - Use product from seed data
        // This proves data is being fetched from InMemory database
        var query = _fixture.CreateGetProductByIdQuery();
        var appContext = new FlexAppContextBridge { UserId = "test-user" };
        var @params = new GetProductByIdParams { Id = "prod-001" };
        @params.SetAppContext(appContext);
        
        query.AssignParameters(@params);

        // Act
        var result = await query.Fetch();

        // Assert - Verify actual seed data values
        result.Should().NotBeNull("product 'prod-001' should exist in seed data");
        result.Id.Should().Be("prod-001");
        result.Name.Should().Be("MacBook Pro 16-inch M3 Max");
        result.Slug.Should().Be("macbook-pro-16-m3-max");
        result.ProductTypeId.Should().Be("pt-electronics");
        result.CategoryId.Should().Be("cat-computers");
    }

    [Fact]
    public async Task Fetch_WithDynamicallySeedProduct_ShouldReturnProduct()
    {
        // Arrange
        var productId = $"prod-query-test-{Guid.NewGuid():N}";
        var productName = "Query Test Product";
        await _fixture.SeedProductAsync(productId, productName);
        
        var query = _fixture.CreateGetProductByIdQuery();
        var appContext = new FlexAppContextBridge { UserId = "test-user" };
        var @params = new GetProductByIdParams { Id = productId };
        @params.SetAppContext(appContext);
        
        query.AssignParameters(@params);

        // Act
        var result = await query.Fetch();

        // Assert
        result.Should().NotBeNull();
        result.Id.Should().Be(productId);
        result.Name.Should().Be(productName);
    }

    [Fact]
    public async Task Fetch_WithNonExistingProductId_ShouldReturnNull()
    {
        // Arrange
        var query = _fixture.CreateGetProductByIdQuery();
        var appContext = new FlexAppContextBridge { UserId = "test-user" };
        var @params = new GetProductByIdParams { Id = "non-existent-product-id" };
        @params.SetAppContext(appContext);
        
        query.AssignParameters(@params);

        // Act
        var result = await query.Fetch();

        // Assert
        result.Should().BeNull();
    }

    [Fact]
    public async Task Fetch_ShouldMapAllProductProperties()
    {
        // Arrange - Create product with all properties
        var productId = $"prod-full-props-{Guid.NewGuid():N}";
        
        var product = _fixture.FlexHost.GetDomainModel<Product>();
        var dto = new CreateProductDto
        {
            Name = "Full Properties Product",
            Slug = $"full-properties-{Guid.NewGuid():N}",
            ProductTypeId = "pt-001",
            CategoryId = "cat-electronics",
            Description = "Rich text description",
            DescriptionPlaintext = "Plain text description",
            Weight = 3.5m,
            ExternalReference = "ext-ref-test"
        };
        
        var appContext = new FlexAppContextBridge { UserId = "test-user" };
        dto.SetAppContext(appContext);
        dto.SetGeneratedId(productId);
        
        product.CreateProduct(new CreateProductCommand { Dto = dto });
        
        var repoFactory = _fixture.CreateRepoFactory();
        repoFactory.Init(dto);
        repoFactory.GetRepo().InsertOrUpdate(product);
        await repoFactory.GetRepo().SaveAsync();
        
        var query = _fixture.CreateGetProductByIdQuery();
        var queryParams = new GetProductByIdParams { Id = productId };
        queryParams.SetAppContext(appContext);
        query.AssignParameters(queryParams);

        // Act
        var result = await query.Fetch();

        // Assert
        result.Should().NotBeNull();
        result.Name.Should().Be("Full Properties Product");
        result.CategoryId.Should().Be("cat-electronics");
        result.Description.Should().Be("Rich text description");
        result.Weight.Should().Be(3.5m);
        result.ExternalReference.Should().Be("ext-ref-test");
    }
}
```

***

## Part 4: Handler Tests (Optional)

Handler tests verify the orchestration logic in command handlers. These are optional because domain model + validation tests often provide sufficient coverage.

```csharp
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Moq;
using Sumeru.Flex;
using YourApp.ProductsModule;
using YourApp.Testing;
using Xunit;

namespace YourApp.Handlers.Tests.Products;

/// <summary>
/// Unit tests for CreateProductHandler.
/// Tests command execution with mocked service bus context.
/// </summary>
public class CreateProductHandlerTests : IDisposable
{
    private readonly string _databaseName;
    private readonly Mock<ILogger<CreateProductHandler>> _mockLogger;
    private readonly Mock<ILoggerFactory> _mockLoggerFactory;
    private readonly InMemoryRepoFactory _repoFactory;
    private readonly IFlexHost _flexHost;

    public CreateProductHandlerTests()
    {
        _databaseName = $"HandlerTest_{Guid.NewGuid():N}";
        _mockLogger = new Mock<ILogger<CreateProductHandler>>();
        _mockLoggerFactory = new Mock<ILoggerFactory>();
        _mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
            .Returns(Mock.Of<ILogger>());
        _repoFactory = new InMemoryRepoFactory(_databaseName, _mockLoggerFactory.Object);

        // Setup FlexHost
        var services = new ServiceCollection();
        services.AddLogging();
        services.AddAutoMapper(cfg =>
        {
            cfg.AddProfile<CreateProductMapperConfiguration>();
        });
        services.AddTransient<Product>(sp =>
        {
            var logger = sp.GetRequiredService<ILogger<Product>>();
            return new Product(logger);
        });
        
        var serviceProvider = services.BuildServiceProvider();
        var flexHostMock = new FlexHostMock();
        flexHostMock.SetServiceCollection(services);
        flexHostMock.SetServiceProvider(serviceProvider);
        _flexHost = flexHostMock;
    }

    public void Dispose() => _repoFactory?.Dispose();

    [Fact]
    public async Task Execute_WithValidCommand_ShouldPersistProduct()
    {
        // Arrange
        var handler = new CreateProductHandler(_mockLogger.Object, _flexHost, _repoFactory);
        var mockContext = new Mock<IFlexServiceBusContext>();
        
        var dto = new CreateProductDto
        {
            Name = "Handler Test Product",
            Slug = $"handler-test-{Guid.NewGuid():N}",
            ProductTypeId = "pt-001"
        };
        var appContext = new FlexAppContextBridge { UserId = "test-user" };
        dto.SetAppContext(appContext);
        dto.SetGeneratedId($"prod-handler-{Guid.NewGuid():N}");
        
        var command = new CreateProductCommand { Dto = dto };

        // Act
        await handler.Execute(command, mockContext.Object);

        // Assert - Verify product was persisted
        var repoFactory = new InMemoryRepoFactory(_databaseName, _mockLoggerFactory.Object);
        repoFactory.Init(dto);
        var savedProduct = repoFactory.GetRepo()
            .FindAll<Product>()
            .FirstOrDefault(p => p.Id == dto.GetGeneratedId());
        
        savedProduct.Should().NotBeNull();
        savedProduct!.Name.Should().Be("Handler Test Product");
    }
}
```

***

## Best Practices Summary

### ✅ Do

1. **Use unique database names** per test class:

   ```csharp
   _databaseName = $"TestName_{Guid.NewGuid():N}";
   ```
2. **Implement IDisposable** to clean up resources:

   ```csharp
   public void Dispose() => _repoFactory?.Dispose();
   ```
3. **Use xUnit collection fixtures** for expensive setup:

   ```csharp
   [Collection("FlexHostMock")]
   public class MyTests
   ```
4. **Leverage seed data** for realistic test scenarios:

   ```csharp
   var packet = CreateDataPacket("cat-electronics"); // Known seed data
   ```
5. **Use FluentAssertions** for readable assertions:

   ```csharp
   result.Should().NotBeNull();
   result.Name.Should().Be("Expected Name");
   ```
6. **Test edge cases** (null, empty, whitespace):

   ```csharp
   [Fact] public async Task Validate_WithNullValue_ShouldPass() { }
   [Fact] public async Task Validate_WithEmptyValue_ShouldPass() { }
   ```

### ❌ Don't

1. **Don't share mutable state** between tests without isolation
2. **Don't rely on test execution order**
3. **Don't use magic strings** - define constants or use seed data
4. **Don't test FlexBase internals** - focus on your business logic
5. **Don't over-mock** - use real InMemory database when possible

***

## Troubleshooting

### Common Issues

**Issue:** Tests fail with "Entity type 'X' was not found" **Solution:** Ensure your `ApplicationEFInMemoryDbContext` includes all entity DbSets

**Issue:** Seed data not found during tests **Solution:** Verify `OnModelCreating` calls your seed data methods

**Issue:** Tests interfere with each other **Solution:** Use unique database names with `Guid.NewGuid()`

**Issue:** AutoMapper configuration errors **Solution:** Register all required mapper profiles in the fixture

***

## Reference: FlexBase Testing APIs

| API                            | Purpose                                  |
| ------------------------------ | ---------------------------------------- |
| `FlexHostMock`                 | Test-friendly `IFlexHost` implementation |
| `flexHost.GetDomainModel<T>()` | Gets domain model instance with DI       |
| `packet.Dto = dto`             | Assigns DTO to data packet               |
| `packet.HasError`              | Boolean - check if validation failed     |
| `packet.Errors()`              | Returns `FlexErrorDictionary`            |
| `packet.AddError(key, msg)`    | Adds validation error                    |
| `dto.SetAppContext(ctx)`       | Sets application context                 |
| `dto.SetGeneratedId(id)`       | Sets pre-generated entity ID             |
| `dto.GetAppContext()`          | Gets application context                 |
| `dto.GetGeneratedId()`         | Gets pre-generated entity ID             |


# Data And Providers

hidden: true

## Data And Providers

### Infrastructure Arrangement

The generated FlexBase infrastructure wires all data stores, AI providers, messaging, and email sources through shared abstractions so `YourApplication` only depends on the interface contracts. Flex Studio scaffolds provider folders, NuGet references, configuration sections, and README examples while the hosted builder registers each provider with telemetry, resiliency, and secrets integration.

### Highlights

* **AI Providers**: Offer `IFlexAIProvider` implementations (OpenAI, Azure OpenAI, Anthropic, Gemini, Ollama) with samples showing how to resolve completions and surface configuration hints such as deployments, secrets, and throttling.
* **Data Stores**: Cover vector, full-text, document, file, graph, and time-series stores with interface-based wiring (`IFlexVectorStore`, `IFlexSearchStore`, `IFlexDocumentStore<T>`, `IFlexFileStore`, `IFlexGraphStore`, `IFlexTimeSeriesStore`), usage snippets, and config guidance for endpoints, indexes, credentials, and qos settings.
* **Email + Messaging**: Document `IFlexEmailProvider` and `IFlexTextMessageProvider` implementations (AWS SES, SendGrid, SMTP, Azure Communication, console, Twilio, etc.) including configuration keys and example usage.
* **Generated Docs**: Each subfolder contains provider-specific markdown that explains the infrastructure arrangement, shows a `{YourApplication}` consumer, and lists configuration hints aligned with the generated infrastructure.

### Next Steps

1. Use Flex Studio to add the provider you need; the generated folder will mirror these docs and provide registration snippets.
2. Inject the shared interface in your services (e.g., `IFlexAIProvider`, `IFlexDocumentStore<T>`, `IFlexFileStore`) and call the provided methods.
3. Maintain configuration under `FlexBase:AI:*`, `FlexBase:DataStores:*`, and `FlexBase:Providers:*` so the builder can resolve secrets, endpoints, and provider-specific metadata.


# Relational Db

FlexBase provides flexible options for working with relational databases, supporting both full-featured ORM (Entity Framework Core) and high-performance micro-ORM (Dapper/Flex MicroORM) approaches.

## Available Options

| Option                                                                               | Description                                                          | Best For                                                                |
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| [**Entity Framework Core**](/data-and-providers/relational-db/entity-framework-core) | Full-featured ORM with change tracking, LINQ queries, and migrations | Complex domain models, navigation properties, automatic change tracking |
| [**Dapper (Flex MicroORM)**](/data-and-providers/relational-db/dapper)               | High-performance micro-ORM with provider-agnostic abstractions       | High-performance reads, bulk operations, complex SQL queries            |

## Quick Comparison

| Feature                   | EF Core              | Dapper           |
| ------------------------- | -------------------- | ---------------- |
| **Performance**           | Good                 | Excellent        |
| **Abstraction Level**     | High                 | Low              |
| **Change Tracking**       | ✅ Automatic          | ❌ Manual         |
| **LINQ Support**          | ✅ Full               | ❌ Raw SQL        |
| **Migrations**            | ✅ Built-in           | ❌ Manual         |
| **Navigation Properties** | ✅ Lazy/Eager loading | ❌ Manual mapping |
| **Learning Curve**        | Moderate             | Minimal          |
| **Bulk Operations**       | Good                 | Excellent        |

## Supported Database Providers

Both EF Core and Dapper support multiple database providers:

* **SQL Server** (default)
* **PostgreSQL**
* **MySQL / MariaDB**
* **SQLite**
* **Oracle**

## When to Use Each

### Use Entity Framework Core when:

* You have complex domain models with relationships
* You need automatic change tracking
* You want to use LINQ for type-safe queries
* You need automatic database migrations
* You prefer higher-level abstractions

### Use Dapper when:

* Performance is critical
* You're comfortable with SQL
* You need to execute complex, optimized queries
* You're doing bulk operations
* You want minimal overhead

## Can I Use Both?

**Yes!** Many applications use both:

* **EF Core** for complex domain models and transactional operations
* **Dapper** for high-performance read queries and reporting

```csharp
// Register both in DI
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));

builder.Services.AddFlexDapper(options =>
{
    options.ConnectionString = connectionString;
    options.ProviderName = "SqlServer";
});

// Use EF Core for writes
public class OrderService
{
    private readonly ApplicationDbContext _context;
    private readonly IFlexMicroOrmRepository _dapper;

    // Write with EF Core (change tracking, transactions)
    public async Task CreateOrderAsync(Order order)
    {
        _context.Orders.Add(order);
        await _context.SaveChangesAsync();
    }

    // Read with Dapper (high performance)
    public async Task<IReadOnlyList<OrderSummary>> GetOrderSummariesAsync()
    {
        return await _dapper.QueryAsync<OrderSummary>(
            "SELECT * FROM OrderSummariesView");
    }
}
```

## FlexBase Integration

Both approaches integrate seamlessly with FlexBase features:

* **Provider-agnostic SQL** - Use `ProviderSqlMap` to write database-specific queries
* **Async query extensions** - Use `*AsyncFlex` methods that work across both
* **Soft delete filtering** - Automatic filtering of soft-deleted records
* **Audit trail** - Automatic audit logging of changes
* **Multi-database support** - Switch providers without code changes

## Getting Started

1. Choose your approach (or use both)
2. Follow the specific guide:
   * [Entity Framework Core Setup](/data-and-providers/relational-db/entity-framework-core)
   * [Dapper Setup](/data-and-providers/relational-db/dapper)
3. Configure your database provider
4. Start building!

## See Also

* [Full-Text Search](/data-and-providers/data-stores/search-store-full-text) - Search capabilities across databases
* [Provider SQL Map](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/ReferenceDocs/README_ProviderSqlMap.md) - Multi-database SQL support
* [Audit Trail](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/ReferenceDocs/README_AuditTrailInterceptor.md) - Automatic audit logging


# Entity Framework Core

Entity Framework Core (EF Core) powers FlexBase’s relational story, but it is not wired as a “DataStore Provider” the way document DB, file store, etc. are.

In generated apps, relational infrastructure is organized under:

* `Infrastructure/Db/*` (EF `DbContext` base + provider-specific repositories/bridges + connection providers)
* `EndPoints/DbMigrations/*` (provider-specific migrations runners)

### Why it matters

* **Change Tracking** keeps entity graphs in sync during persistence.
* **LINQ/Projection** simplifies reporting and pagination from handlers.
* **Navigation properties** let you compose rich joins when handlers need related data.
* **Resilience** features from EF Core keep transient failures transparent to your handlers.

> Flex note: for async `IQueryable<T>` execution, prefer `Sumeru.Flex.FlexQueryableAsyncExtensions` (e.g., `ToListAsyncFlex`, `FirstOrDefaultAsyncFlex`) over EF Core’s native async query helpers.

## Infrastructure Arrangement

Rather than inventing domain repositories, generated code leans on `DomainHandler/.../Queries` and `DomainHandler/.../Handlers` folders (for example `List{Entities}`, `Create{Entity}Handler`, etc.). Each query/handler receives relational services through DI (for example `IRepoFactory`, `IPostBus`, logging), executes LINQ queries or persists changes, and then publishes events.

Typical layout:

* EF base context: `Infrastructure/Db/{YourApplication}.BaseEF/ApplicationEFDbContext.cs`
* Provider-specific repos/bridges: `Infrastructure/Db/{YourApplication}.BaseEF.SqlServer/*`, `...PostgreSql/*`, `...MySql/*`
* Connection providers (appsettings-driven): `Infrastructure/Db/{YourApplication}.BaseEF/ConnectionProviders/*`
* Migrations runners: `EndPoints/DbMigrations/{YourApplication}.Migrations.{Provider}/*`

## Handler Example (Insert/Update)

Handlers typically:

1. Hydrate the request context (`cmd.Dto.GetAppContext()`)
2. Initialize relational context with the DTO parameters
3. Create/update the domain model
4. Persist changes
5. Optionally raise follow-up events through the generated `Fire(...)` pipeline

```csharp
using Sumeru.Flex;

public partial class CreateApplicationHandler : ICreateApplicationHandler
{
  protected readonly IFlexHost _flexHost;
  protected readonly IRepoFactory _repoFactory;
  protected FlexAppContextBridge? _flexAppContext;
  protected string EventCondition = "";

  public CreateApplicationHandler(IFlexHost flexHost, IRepoFactory repoFactory)
  {
    _flexHost = flexHost;
    _repoFactory = repoFactory;
  }

  public virtual async Task Execute(CreateApplicationCommand cmd, IFlexServiceBusContext serviceBusContext)
  {
    _flexAppContext = cmd.Dto.GetAppContext();  //do not remove this line
    _repoFactory.Init(cmd.Dto);

    var model = _flexHost.GetDomainModel<Application>().CreateApplication(cmd);
    var repo = _repoFactory.GetRepo();

    repo.InsertOrUpdate(model);
    var records = await repo.SaveAsync();

    // TODO: Set EventCondition based on business logic (e.g., "ONSUCCESS")
    await this.Fire(EventCondition, serviceBusContext);
  }
}

public partial class UpdateReferralHandler : IUpdateReferralHandler
{
  protected readonly IRepoFactory _repoFactory;
  protected FlexAppContextBridge? _flexAppContext;
  protected string EventCondition = "";

  public UpdateReferralHandler(IRepoFactory repoFactory) => _repoFactory = repoFactory;

  public virtual async Task Execute(UpdateReferralCommand cmd, IFlexServiceBusContext serviceBusContext)
  {
    _flexAppContext = cmd.Dto.GetAppContext();  //do not remove this line
    _repoFactory.Init(cmd.Dto);
    var repo = _repoFactory.GetRepo();

    var model = await repo.FindAll<EmployeeReferral>()
      .FirstOrDefaultAsyncFlex(m => m.Id == cmd.Dto.Id);

    if (model == null)
    {
      // Optionally set EventCondition to a failure condition.
      await this.Fire(EventCondition, serviceBusContext);
      return;
    }

    model.UpdateReferral(cmd);
    repo.InsertOrUpdate(model);
    await repo.SaveAsync();

    // TODO: Set EventCondition based on business logic (e.g., "ONSUCCESS")
    await this.Fire(EventCondition, serviceBusContext);
  }
}
```

Both handlers keep the intent logic in the command class while reusing the generated infrastructure for EF Core context resolution and event publishing.

## Sample Usage

```csharp
using Sumeru.Flex;

public class ListApplications : FlexiQueryPagedListBridgeAsync<Application, ListApplicationsParams, ListApplicationsDto, FlexAppContextBridge>
{
  protected readonly ILogger<ListApplications> _logger;
  protected ListApplicationsParams _params;
  protected readonly IRepoFactory _repoFactory;

  public ListApplications(ILogger<ListApplications> logger, IRepoFactory repoFactory)
  {
    _logger = logger;
    _repoFactory = repoFactory;
  }

  public virtual ListApplications AssignParameters(ListApplicationsParams @params)
  {
    _params = @params;
    return this;
  }

  public override async Task<FlexiPagedList<ListApplicationsDto>> Fetch()
  {
    _repoFactory.Init(_params);

    var items = await Build<Application>()
      .Where(a => !a.IsDeleted)
      .Select(a => new ListApplicationsDto { Id = a.Id, JobTitle = a.JobPosting.JobTitle })
      .ToListAsyncFlex();

    return BuildPagedOutput(items);
  }

  protected override IQueryable<T> Build<T>()
  {
    _repoFactory.Init(_params);
    var query = _repoFactory.GetRepo().FindAll<T>();
    return CreatePagedQuery(query, _params.Skip, _params.PageSize);
  }
}
```

### Simple list example (lookup)

Use a simple enumerable query for “lookup” lists (the pattern matches typical `Get{Entity}ForLookup` queries).

```csharp
using Sumeru.Flex;

public class GetDepartmentsForLookup : FlexiQueryEnumerableBridgeAsync<OrgAccount, GetDepartmentsForLookupDto>
{
  protected readonly ILogger<GetDepartmentsForLookup> _logger;
  protected GetDepartmentsForLookupParams _params;
  protected readonly IRepoFactory _repoFactory;

  public GetDepartmentsForLookup(ILogger<GetDepartmentsForLookup> logger, IRepoFactory repoFactory)
  {
    _logger = logger;
    _repoFactory = repoFactory;
  }

  public virtual GetDepartmentsForLookup AssignParameters(GetDepartmentsForLookupParams @params)
  {
    _params = @params;
    return this;
  }

  public override async Task<IEnumerable<GetDepartmentsForLookupDto>> Fetch()
  {
    _repoFactory.Init(_params);

    var items = await Build<OrgAccount>()
      .Where(o => o.IsActive)
      .Where(o => o.OrgAccountTypeId == OrgAccountTypeEnum.Department.Value)
      .OrderBy(o => o.Name)
      .SelectTo<GetDepartmentsForLookupDto>()
      .ToListAsyncFlex();

    return items;
  }

  protected override IQueryable<T> Build<T>()
  {
    _repoFactory.Init(_params);
    return _repoFactory.GetRepo().FindAll<T>();
  }
}

public class GetDepartmentsForLookupParams : DtoBridge { }
```

### Get-by-id example

Use a single-result query for `Get{Entity}ById` patterns.

```csharp
using Sumeru.Flex;

public class GetApplicationById : FlexiQueryBridgeAsync<Application, GetApplicationByIdDto>
{
  protected readonly ILogger<GetApplicationById> _logger;
  protected GetApplicationByIdParams _params;
  protected readonly IRepoFactory _repoFactory;

  public GetApplicationById(ILogger<GetApplicationById> logger, IRepoFactory repoFactory)
  {
    _logger = logger;
    _repoFactory = repoFactory;
  }

  public virtual GetApplicationById AssignParameters(GetApplicationByIdParams @params)
  {
    _params = @params;
    return this;
  }

  public override async Task<GetApplicationByIdDto> Fetch()
  {
    var result = await Build<Application>()
      .FlexInclude("ApplicationState")
      .FlexInclude("JobPosting")
      .FlexInclude("Candidate")
      .SelectTo<GetApplicationByIdDto>()
      .FirstOrDefaultAsyncFlex();

    return result;
  }

  protected override IQueryable<T> Build<T>()
  {
    _repoFactory.Init(_params);
    return _repoFactory.GetRepo().FindAll<T>().Where(t => t.Id == _params.Id);
  }
}

public class GetApplicationByIdParams : DtoBridge
{
  public string Id { get; set; }
}
```

Handlers follow this approach—initialize relational context, project entities, and return DTOs—so you can rely on the same pattern across modules.

## Configuration Keys

1. `FlexBase:AppDbConnection` – Primary relational connection string.

If you need separate read/write connections or tenant/master connections, follow the provider-specific connection providers under `Infrastructure/Db/*/ConnectionProviders`.

## Best Practices

1. Stick to the handlers/queries in `DomainHandler/...` so the generator can update wiring and keep telemetry consistent.
2. Emit events via `PostBus` inside handlers like `CreateApplicationHandler`/`SubmitReferralHandler` to keep integration points decoupled.
3. Use DTO projections (see `ListApplications`) to keep EF Core in read-only mode when possible.

## Testing & Tooling

* Unit tests typically execute the generated queries/handlers directly and provide any relational dependencies through DI.

## Provider-Specific SQL (ProviderSqlMap)

When you need raw SQL that differs per provider (SQL Server vs PostgreSQL vs MySQL), use `ProviderSqlMap` so a repository can pick the correct SQL based on the configured EF provider.

```csharp
using Sumeru.Flex;

var sqlMap = ProviderSqlMap.Create(sql => sql
  .ForSqlServer("SELECT TOP 10 * FROM dbo.MyEntities ORDER BY CreatedDate DESC")
  .ForPostgres("SELECT * FROM \"MyEntities\" ORDER BY \"CreatedDate\" DESC LIMIT 10")
  .ForMySql("SELECT * FROM `MyEntities` ORDER BY `CreatedDate` DESC LIMIT 10")
  .UseDefault("SELECT * FROM MyEntities ORDER BY CreatedDate DESC LIMIT 10"));

var repo = _repoFactory.GetRepo();
var results = await repo.ExecuteSqlRaw<MyEntity>(sqlMap).ToListAsyncFlex();
```

## Soft Delete Filter

If your entities derive from `TFlex`, you can enable a global query filter that hides rows where `IsDeleted` is `true`.

Enable either:

* Per context: `context.UseSoftDeleteFilters()`
* Via DI: `FlexSoftDeleteOptions` (e.g., `Enabled = true`)

To include deleted rows for a scope:

```csharp
using Sumeru.Flex;

using (queryRepository.SuppressSoftDeleteFilter())
{
  var all = await queryRepository.FindAll<MyEntity>()
    .Where(e => e.IsDeleted)
    .ToListAsyncFlex();
}
```

## Audit Trail

To capture audit trail rows for Added/Modified/Deleted entities, enable audit trail behavior on the EF context / interceptor as documented.

Typical options:

* Enable on your `FlexEFDbContext` implementation (often a one-liner such as `EnableAuditTrail()`).
* Or register an interceptor and options in DI and attach it via `AddDbContext`.

Querying audit trails is then just a normal EF query:

```csharp
using Sumeru.Flex;

var recent = await db.AuditTrails
  .OrderByDescending(a => a.DateTime)
  .Take(50)
  .ToListAsyncFlex();
```


# Dapper

## Description

Dapper is the relational “micro-ORM” option in FlexBase: explicit SQL, minimal overhead, and high performance.

Flex wraps Dapper with **Flex Dapper** (a Dapper-first implementation of the **Flex MicroORM** abstraction). Your application code can stay provider-agnostic by using:

* `IFlexDapperRepository` for query/command helpers
* `FlexDapperSql` + `ProviderSqlMap` for provider-specific SQL variants
* Built-in soft-delete filtering (optional)
* Paging helpers
* Transaction helpers

If you prefer LINQ, change tracking, and migrations, see [Entity Framework Core](/data-and-providers/relational-db/entity-framework-core).

## When to Use Dapper

| Scenario                                                     | Recommendation                                                                          |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| High-performance reads (lists, dashboards, reporting)        | ✅ Use Dapper/Flex Dapper                                                                |
| Complex/hand-tuned SQL (CTEs, vendor features, query hints)  | ✅ Use Dapper/Flex Dapper                                                                |
| Bulk operations (insert/update many rows)                    | ✅ Use Dapper/Flex Dapper                                                                |
| Simple table-centric CRUD on `TFlex` entities                | ✅ Use `FlexDapperTableRepository<TEntity>`                                              |
| Rich domain graphs + change tracking + navigation properties | Prefer [Entity Framework Core](/data-and-providers/relational-db/entity-framework-core) |

## Configuration in DI

```csharp
using Sumeru.Flex;

services.AddSingleton<IFlexDapperConnectionFactory, FlexDapperConnectionFactory>();

services.AddScoped(_ => new FlexDapperRepositoryOptions
{
    ProviderName = "SqlServer",
    ConnectionString = configuration.GetConnectionString("FlexWriteDb"),
    EnableSoftDeleteFilter = true,
    SoftDeleteColumnName = "IsDeleted"
});
```

## appsettings.json

Where you store the connection string is app-specific, but most apps keep it under standard connection strings:

```json
{
  "ConnectionStrings": {
    "FlexWriteDb": "Server=...;Database=...;User Id=...;Password=<store-in-secrets>;TrustServerCertificate=True"
  }
}
```

## Sample usage (Queries / Handlers)

The typical pattern is: **queries** call `QueryAsync`/`QuerySingleAsync`, and **handlers** call `ExecuteAsync`/`ExecuteScalarAsync`, all through interfaces.

### Query example (read model)

```csharp
using Sumeru.Flex;

public sealed class ListActiveUsers
{
    private readonly IFlexDapperRepository _db;

    public ListActiveUsers(IFlexDapperRepository db) => _db = db;

    public Task<IReadOnlyList<UserListItemDto>> FetchAsync()
    {
        FlexDapperSql sql = "SELECT Id, UserName FROM Users WHERE IsActive = 1 ORDER BY UserName";
        return _db.QueryAsync<UserListItemDto>(sql);
    }
}

public sealed class UserListItemDto
{
    public string Id { get; set; }
    public string UserName { get; set; }
}
```

### Handler example (command)

```csharp
using Sumeru.Flex;

public sealed class CreateUserHandler
{
    private readonly IFlexDapperRepository _db;

    public CreateUserHandler(IFlexDapperRepository db) => _db = db;

    public Task<int?> ExecuteAsync(CreateUserCommand cmd)
    {
        FlexDapperSql sql = """
            INSERT INTO Users (UserName, Email, IsActive)
            VALUES (@UserName, @Email, 1);
            SELECT CAST(SCOPE_IDENTITY() as int);
            """;

        return _db.ExecuteScalarAsync<int>(sql, new { cmd.UserName, cmd.Email });
    }
}

public sealed record CreateUserCommand(string UserName, string Email);
```

## Common Patterns

### Custom SQL (Provider-Agnostic)

Use `ProviderSqlMap` + `FlexDapperSql.FromProviderMap(...)` to keep provider differences in one place.

```csharp
using Sumeru.Flex;

public sealed class ListRecentAccounts
{
    private readonly IFlexDapperRepository _db;

    public ListRecentAccounts(IFlexDapperRepository db) => _db = db;

    public Task<IReadOnlyList<Accountability>> FetchAsync(int take)
    {
        var sql = FlexDapperSql.FromProviderMap(
            ProviderSqlMap.Create(map =>
                map.ForSqlServer($"SELECT TOP {take} * FROM Accountabilities ORDER BY CreatedDate DESC")
                   .ForPostgres($"SELECT * FROM \"Accountabilities\" ORDER BY \"CreatedDate\" DESC LIMIT {take}")));

        return _db.QueryAsync<Accountability>(sql);
    }
}
```

### Paging

For custom queries, use `QueryPageAsync` with `FlexDapperPagedQuery`:

```csharp
public sealed class GetUsersPaged
{
    private readonly IFlexDapperRepository _db;

    public GetUsersPaged(IFlexDapperRepository db) => _db = db;

    public Task<FlexDapperPagedResult<User>> FetchAsync(int pageNumber, int pageSize)
    {
        var query = new FlexDapperPagedQuery(
            dataSql: "SELECT * FROM Users ORDER BY Id OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY",
            countSql: "SELECT COUNT(1) FROM Users",
            pageNumber: pageNumber,
            pageSize: pageSize);

        return _db.QueryPageAsync<User>(query);
    }
}
```

### Transactions

Use `WithTransactionAsync` to ensure atomic multi-statement work.

```csharp
await _db.WithTransactionAsync(async (connection, tx) =>
{
    await connection.ExecuteAsync("update ...", transaction: tx);
    await connection.ExecuteAsync("insert ...", transaction: tx);
    return true;
});
```

### Soft Delete Filter

* Enable filtering with `FlexDapperRepositoryOptions.EnableSoftDeleteFilter` and set `SoftDeleteColumnName` (commonly `IsDeleted`).
* `FlexDapperTableRepository<TEntity>` automatically appends the soft-delete predicate when the filter is enabled.
* To temporarily include soft-deleted rows:

```csharp
using (_db.SuppressSoftDeleteFilter())
{
    var all = await _db.QueryAsync<MyEntity>("SELECT * FROM MyEntities");
}
```

## Testing

* For unit tests, inject a fake `IFlexDapperConnectionFactory` and/or assert SQL text + parameters.
* For integration tests, use a real database (local/container) and reuse the same repository registrations.

## See Also

* [Relational Database Overview](/data-and-providers/relational-db)
* [Entity Framework Core](/data-and-providers/relational-db/entity-framework-core)
* [Provider SQL Map](https://github.com/sumeru-flexbase/flexbase-docs/blob/main/ReferenceDocs/README_ProviderSqlMap.md)
* [Full-Text Search](/data-and-providers/data-stores/search-store-full-text)


# Data Stores

FlexBase provides a comprehensive set of data store abstractions for modern application development. Each store type is designed for specific use cases and provides a unified interface across multiple provider implementations.

## Available Data Stores

### Core Data Stores

| Store Type                                                                     | Description                      | Providers                                              |
| ------------------------------------------------------------------------------ | -------------------------------- | ------------------------------------------------------ |
| [**Vector Store**](/data-and-providers/data-stores/vector-store)               | Semantic search, RAG, embeddings | SQL Server 2025, Azure AI Search, pgvector, OpenSearch |
| [**Full-Text Search**](/data-and-providers/data-stores/search-store-full-text) | Keyword search with ranking      | SQL Server, PostgreSQL, MySQL, Elasticsearch           |
| **Document Store**                                                             | JSON document storage            | MongoDB, CosmosDB, DynamoDB, RavenDB                   |
| **File Store**                                                                 | Binary file storage              | AWS S3, Azure Blob, GCP Storage, Disk                  |
| **Graph Store**                                                                | Relationship networks            | Neo4j, Cosmos Gremlin                                  |
| **Time Series Store**                                                          | Time-based metrics               | InfluxDB, TimescaleDB, Azure Data Explorer             |

### When to Use Each Store

| Use Case                | Recommended Store                                  |
| ----------------------- | -------------------------------------------------- |
| **Semantic search**     | Vector Store                                       |
| **Keyword search**      | Full-Text Search                                   |
| **Document management** | Document Store                                     |
| **File uploads**        | File Store                                         |
| **Social networks**     | Graph Store                                        |
| **IoT/Metrics**         | Time Series Store                                  |
| **Structured data**     | [Relational DB](/data-and-providers/relational-db) |

## Quick Start

### Automatic Setup via Flex Studio

Data Store providers are automatically added to your application through **Flex Studio**. When you add a data store provider:

1. **Provider files are created** in `Infrastructure/Providers/{YourApplication}.DataStoreProviders/{Category}/{Provider}/`
2. **NuGet package is referenced** automatically
3. **Default configuration** is added to `Application/EndPoints/{YourApplication}.EndPoint.CommonConfigs/AppSettings/DataStores/{Category}/{Provider}.json`
4. **README documentation** is included in the provider folder

You can find all provider files, configuration examples, and documentation in the generated infrastructure folder.

### 1. Choose Your Store

Select the appropriate store type based on your use case. Each store has specific strengths:

* **Vector Store** - When you need AI-powered semantic search or RAG
* **Full-Text Search** - When you need fast keyword search with ranking
* **Document Store** - When you need flexible schema and JSON storage
* **File Store** - When you need to store and serve binary files

### 2. Add Provider via Flex Studio

In Flex Studio, select the data store category and provider you want to use. Flex Studio will:

* Create the provider infrastructure folder
* Reference the appropriate NuGet package
* Generate default configuration files
* Include provider-specific documentation

### 3. Configure and Use

After adding via Flex Studio:

1. **Update configuration** in the generated `AppSettings/DataStores/{Category}/{Provider}.json` file
2. **Review registration examples** in the provider folder's README
3. **Register in DI** using the extension methods shown in the README
4. **Inject and use** in your services

```csharp
// Example: After adding Vector Store provider via Flex Studio
public class MyService
{
    private readonly IFlexVectorStore _vectorStore;
    
    public MyService(IFlexVectorStore vectorStore)
    {
        _vectorStore = vectorStore;  // Automatically available after Flex Studio setup
    }
    
    public async Task IndexDocumentAsync(string id, string content)
    {
        // Use the store - configuration already set up
        await _vectorStore.UpsertAsync(id, embedding, content: content);
    }
}
```

## Featured: Vector Store + AI

The **Vector Store** is particularly powerful when combined with **AI Providers** for implementing RAG (Retrieval-Augmented Generation):

```csharp
public class RAGService
{
    private readonly IFlexVectorStore _vectorStore;
    private readonly IFlexAIProvider _aiProvider;

    public async Task<string> AskQuestionAsync(string question)
    {
        // 1. Generate query embedding
        var queryEmbedding = await _aiProvider.EmbedAsync(question);

        // 2. Search for relevant context
        var results = await _vectorStore.SearchAsync(
            queryVector: queryEmbedding,
            topK: 5,
            minScore: 0.75f);

        // 3. Build context
        var context = string.Join("\n\n", results.Select(r => r.Content));

        // 4. Get AI response with context
        var prompt = $"""
            Answer based on this context:
            {context}
            
            Question: {question}
            """;

        return await _aiProvider.ChatAsync(prompt);
    }
}
```

## Hybrid Approaches

### Vector + Full-Text Search

Combine semantic and keyword search for best results:

```csharp
// 1. Full-text for keyword matches
var keywordResults = await _fullTextSearch.SearchAsync(query);

// 2. Vector search for semantic matches
var semanticResults = await _vectorStore.SearchAsync(queryEmbedding);

// 3. Merge and rank
var combined = MergeAndRankResults(keywordResults, semanticResults);
```

### SQL Server 2025: All-in-One

SQL Server 2025 supports both relational data AND vector search in one database:

```sql
-- Store business data + embeddings together
CREATE TABLE Products (
    Id INT PRIMARY KEY,
    Name NVARCHAR(200),
    Description NVARCHAR(MAX),
    Price DECIMAL(10,2),
    -- Vector column for semantic search
    DescriptionEmbedding VECTOR(1536)
);

-- Combine relational queries with vector search
SELECT TOP 10 p.*
FROM Products p
WHERE p.Category = 'Electronics'
  AND p.Price BETWEEN 100 AND 500
ORDER BY VECTOR_DISTANCE('cosine', p.DescriptionEmbedding, @queryVector);
```

## Provider-Agnostic Design

All FlexBase data stores follow a consistent pattern:

1. **Unified Interface** - Same API across all providers
2. **Provider-Specific Features** - Access advanced features when needed
3. **Easy Migration** - Switch providers with configuration changes
4. **Testing Support** - Mock implementations for unit tests

```csharp
// Works with ANY vector store provider
public class DocumentService
{
    private readonly IFlexVectorStore _vectorStore;  // Could be SQL Server, pgvector, etc.
    
    public async Task IndexAsync(string id, string content)
    {
        var embedding = await _aiProvider.EmbedAsync(content);
        await _vectorStore.UpsertAsync(id, embedding, content: content);
    }
}
```

## Integration with FlexBase Features

All data stores integrate seamlessly with FlexBase features:

* **Dependency Injection** - Standard IOptions pattern
* **Logging** - Structured logging built-in
* **Health Checks** - Test connectivity on startup
* **Configuration** - appsettings.json support
* **Multi-tenancy** - Tenant isolation support
* **Caching** - Integration with FlexCache

## Best Practices

1. **Start Simple** - Use what you need, add complexity later
2. **Test Locally** - Use in-memory or local providers for development
3. **Monitor Performance** - Track query times and costs
4. **Implement Caching** - Cache frequently accessed data
5. **Plan for Scale** - Consider growth from the start
6. **Use Hybrid** - Combine stores for optimal results

## Advanced Usage Examples

### Vector Store

Vector stores are used for semantic search and retrieval-augmented generation (RAG). Below is an example:

```csharp
public class SemanticSearchService
{
    private readonly IFlexVectorStore _vectorStore;

    public SemanticSearchService(IFlexVectorStore vectorStore)
    {
        _vectorStore = vectorStore;
    }

    public async Task<IEnumerable<SearchResult>> SearchAsync(string query)
    {
        return await _vectorStore.SearchAsync(query, topK: 10);
    }
}
```

### Full-Text Search

Full-text search stores are optimized for keyword-based search. Below is an example:

```csharp
public class KeywordSearchService
{
    private readonly IFlexSearchStore _searchStore;

    public KeywordSearchService(IFlexSearchStore searchStore)
    {
        _searchStore = searchStore;
    }

    public async Task<IEnumerable<SearchResult>> SearchAsync(string keyword)
    {
        return await _searchStore.SearchAsync(keyword);
    }
}
```

### Document Store

Document stores are ideal for JSON-based storage. Below is an example:

```csharp
public class DocumentService
{
    private readonly IFlexDocumentStore _documentStore;

    public DocumentService(IFlexDocumentStore documentStore)
    {
        _documentStore = documentStore;
    }

    public async Task SaveDocumentAsync(string id, object document)
    {
        await _documentStore.SaveAsync(id, document);
    }

    public async Task<object> GetDocumentAsync(string id)
    {
        return await _documentStore.GetAsync(id);
    }
}
```

### File Store

File stores are used for binary file storage. Below is an example:

```csharp
public class FileStorageService
{
    private readonly IFlexFileStore _fileStore;

    public FileStorageService(IFlexFileStore fileStore)
    {
        _fileStore = fileStore;
    }

    public async Task UploadFileAsync(string path, Stream fileStream)
    {
        await _fileStore.UploadAsync(path, fileStream);
    }

    public async Task<Stream> DownloadFileAsync(string path)
    {
        return await _fileStore.DownloadAsync(path);
    }
}
```

## See Also

* [Relational Databases](/data-and-providers/relational-db) - EF Core and Dapper
* [AI Providers](/data-and-providers/providers/ai-providers) - Generate embeddings for vector search
* [Email Providers](/data-and-providers/providers/e-mail) - Send transactional emails
* [Message Providers](/data-and-providers/providers/text-message) - SMS and push notifications


# Document Db

## Description

Document stores register through `IFlexDocumentStore<TDocument>` (and `IFlexDocumentStore` for multi-collection scenarios). Your application code stays provider-agnostic while Cosmos DB, DynamoDB, MongoDB, and RavenDB handle persistence.

## Configuration in DI

Register only the provider store(s) you need.

```csharp
// Pick ONE provider and register the document types you use.
services.AddFlexCosmosDocumentStore<CustomerProfile>(configuration);
// services.AddFlexMongoDocumentStore<CustomerProfile>(configuration);
// services.AddFlexDynamoDocumentStore<CustomerProfile>(configuration);
// services.AddFlexRavenDocumentStore<CustomerProfile>(configuration);
```

## appsettings.json

Document DB configuration is read from `FlexBase:DataStores:Document:<Provider>`.

```json
{
  "FlexBase": {
    "DataStores": {
      "Document": {
        "CosmosDb": {
          "Endpoint": "https://...",
          "AccountKey": "<store-in-secrets>",
          "DatabaseName": "{YourApplication}",
          "ContainerName": "CustomerProfiles"
        }
      }
    }
  }
}
```

## Sample usage ({YourApplication})

```csharp
public class CustomerOnboarding
{
	private readonly IFlexDocumentStore<CustomerProfile> _customerProfiles;

	public CustomerOnboarding(IFlexDocumentStore<CustomerProfile> customerProfiles)
		=> _customerProfiles = customerProfiles;

	public async Task MarkSeenAsync(string id)
	{
		var profile = await _customerProfiles.GetAsync(id);
		if (profile is null) return;

		profile.LastSeen = DateTime.UtcNow;
		await _customerProfiles.UpsertAsync(profile);
	}
}
```

## Provider pages

* Cosmos DB: `document-db/cosmos-db.md`
* DynamoDB: `document-db/dynamo-db.md`
* MongoDB: `document-db/mongo-db.md`
* RavenDB: `document-db/raven-db.md`

## Provider considerations

* Keep secrets (keys/connection strings) out of source control.
* For Cosmos DB, set partition keys consistently with your model and access patterns.


# Mongo Db

## Description

MongoDB is used as a **Document DB provider** through the shared Flex document-store abstraction (`IFlexDocumentStore`). Generated code keeps your application code provider-agnostic: your queries/handlers talk to `IFlexDocumentStore`, and the provider wiring decides whether that’s MongoDB, Cosmos DB, Dynamo DB, etc.

## Important Concepts

* **Query/Handler pattern**: reads happen in `.../Queries`, writes happen in `.../Handlers`.
* **AppContext is mandatory**: always call `dto.GetAppContext()` in queries/handlers (the templates mark it as “do not remove”).
* **Provider is hidden behind interfaces**: your code depends on `IFlexDocumentStore`, not Mongo SDK types.

## Configuration in DI (where to add)

Provider wiring is generated in your Infrastructure project (under a `...DataStoreProviders/Document/MongoDb` folder). You typically do **not** register individual queries/handlers here — Flex generates and wires those.

If you are wiring Mongo manually, add the **document-store provider** registration where you configure infrastructure services (often in `Program.cs` or an Infrastructure DI module):

```csharp
// Infrastructure (example)
services.AddFlexMongoDocumentStore<InvoiceDocument>(
    configuration,
    collectionName: "Invoices");
```

> Where to put business registrations? Use your EndPoints “common configs” area (like `OtherApplicationServicesConfig`) for registering *your own* application services. The MongoDB provider itself is registered in Infrastructure.

## appsettings.json

```json
{
	"FlexBase": {
		"DataStores": {
			"Document": {
				"MongoDb": {
					"ConnectionString": "mongodb://...",
					"DatabaseName": "{YourApplication}",
					"EnableSSL": true,
					"ConnectionTimeout": "00:00:30",
					"MaxConnectionPoolSize": 100
				}
			}
		}
  }
}
```

## Examples (from the generated templates)

The generator uses the same shape for all Document DB providers; only the provider wiring changes.

### Handler example (Create)

This follows the template in `PostBusHandler/DocumentDataStore/DocumentStoreHandlerTemplate_Create.cs`.

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Threading.Tasks;

public interface ICreateInvoiceHandler : IAmFlexCommandHandler<CreateInvoiceCommand> { }

public partial class CreateInvoiceHandler : ICreateInvoiceHandler
{
	protected string EventCondition = "";

	protected readonly ILogger<CreateInvoiceHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexDocumentStore _documentStore;
	protected readonly IInvoiceMapper _mapper;

	protected InvoiceDocument? _model;
	protected FlexAppContextBridge? _flexAppContext;

	public CreateInvoiceHandler(
		ILogger<CreateInvoiceHandler> logger,
		IFlexHost flexHost,
		IFlexDocumentStore documentStore,
		IInvoiceMapper mapper)
	{
		_logger = logger;
		_flexHost = flexHost;
		_documentStore = documentStore;
		_mapper = mapper;
	}

	public virtual async Task Execute(CreateInvoiceCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		_flexAppContext = cmd.Dto.GetAppContext(); // do not remove

		_model = _mapper.MapToDocument(cmd.Dto);
		var created = await _documentStore.CreateAsync<InvoiceDocument>(_model);

		// TODO: set EventCondition based on business logic (example: CONDITION_ONSUCCESS)
		await this.Fire(EventCondition, serviceBusContext);
	}
}
```

### Query example (Get-by-id)

This follows the template in `Query/DocumentDataStore/DocumentStoreQueryGetByIdTemplate.cs`.

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

public class GetInvoiceById : FlexiQueryBridgeAsync<InvoiceDto>
{
	protected readonly ILogger<GetInvoiceById> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexDocumentStore _documentStore;
	protected GetInvoiceByIdParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public GetInvoiceById(ILogger<GetInvoiceById> logger, IFlexHost flexHost, IFlexDocumentStore documentStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_documentStore = documentStore;
	}

	public virtual GetInvoiceById AssignParameters(GetInvoiceByIdParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<InvoiceDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		var doc = await _documentStore.GetByIdAsync<InvoiceDocument>(_params.Id);
		return doc == null ? null : new InvoiceDto { Id = doc.Id, Status = doc.Status };
	}
}

public class GetInvoiceByIdParams : DtoBridge
{
	public Guid Id { get; set; }
}
```

### Query example (Simple list)

This follows the template in `Query/DocumentDataStore/DocumentStoreQueryGetEnumerableTemplate.cs`.

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

public class ListInvoices : FlexiQueryEnumerableBridgeAsync<InvoiceDto>
{
	protected readonly ILogger<ListInvoices> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexDocumentStore _documentStore;
	protected ListInvoicesParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public ListInvoices(ILogger<ListInvoices> logger, IFlexHost flexHost, IFlexDocumentStore documentStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_documentStore = documentStore;
	}

	public virtual ListInvoices AssignParameters(ListInvoicesParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<IEnumerable<InvoiceDto>> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		Expression<Func<InvoiceDocument, bool>> filter = x => x.CustomerId == _params.CustomerId;
		var docs = await _documentStore.GetManyAsync<InvoiceDocument>(filter);

		// TODO: map documents to DTOs
		return docs == null
			? Array.Empty<InvoiceDto>()
			: docs.Select(d => new InvoiceDto { Id = d.Id, Status = d.Status });
	}
}

public class ListInvoicesParams : DtoBridge
{
	public string CustomerId { get; set; } = "";
}
```

## Provider-specific considerations

* **Replica sets**: prefer replica-set aware connection strings for failover.
* **Indexing**: define the “must have” indexes for your hot queries in configuration so deployments stay consistent.
* **Read preferences**: align read preference with your consistency needs (primary vs preferred).


# Cosmos Db

## Description

Cosmos DB is used as a **Document DB provider** behind `IFlexDocumentStore`. Generated apps keep document reads/writes in the standard Query/Handler pattern while Cosmos-specific concerns (partition keys, throughput, retry/backoff) are handled in the provider wiring.

## Important Concepts

* **Container mapping is config-driven**: logical store/container names and partition keys live in configuration.
* **AppContext is mandatory**: always call `dto.GetAppContext()` in generated queries/handlers.
* **Provider-agnostic code**: your business logic depends on `IFlexDocumentStore`, not the Cosmos SDK.

## Configuration in DI (where to add)

Provider wiring is generated in your Infrastructure project (under a `...DataStoreProviders/Document/CosmosDb` folder). You typically do **not** register individual queries/handlers here — Flex generates and wires those.

If you are wiring Cosmos manually, add the **document-store provider** registration where you configure infrastructure services:

```csharp
// Infrastructure (example)
services.AddFlexCosmosDocumentStore<CustomerProfileDocument>(configuration);
```

## appsettings.json

```json
{
	"FlexBase": {
		"DataStores": {
			"Document": {
				"CosmosDb": {
					"Endpoint": "https://...documents.azure.com:443/",
					"AccountKey": "<from-secrets>",
					"DatabaseName": "{YourApplication}",
					"ContainerName": "CustomerProfiles",
					"PartitionKeyPath": "/id",
					"ThroughputRUs": 400
				}
			}
	}
  }
}
```

## Examples (from the generated templates)

Cosmos uses the same generated shapes as other Document DB providers.

### Handler example (Create)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Threading.Tasks;

public interface ICreateCustomerProfileHandler : IAmFlexCommandHandler<CreateCustomerProfileCommand> { }

public partial class CreateCustomerProfileHandler : ICreateCustomerProfileHandler
{
	protected string EventCondition = "";

	protected readonly ILogger<CreateCustomerProfileHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexDocumentStore _documentStore;
	protected readonly ICustomerProfileMapper _mapper;

	protected CustomerProfileDocument? _model;
	protected FlexAppContextBridge? _flexAppContext;

	public CreateCustomerProfileHandler(
		ILogger<CreateCustomerProfileHandler> logger,
		IFlexHost flexHost,
		IFlexDocumentStore documentStore,
		ICustomerProfileMapper mapper)
	{
		_logger = logger;
		_flexHost = flexHost;
		_documentStore = documentStore;
		_mapper = mapper;
	}

	public virtual async Task Execute(CreateCustomerProfileCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		_flexAppContext = cmd.Dto.GetAppContext(); // do not remove

		_model = _mapper.MapToDocument(cmd.Dto);
		await _documentStore.CreateAsync<CustomerProfileDocument>(_model);

		// TODO: set EventCondition (example: CONDITION_ONSUCCESS)
		await this.Fire(EventCondition, serviceBusContext);
	}
}
```

### Query example (Get-by-id)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

public class GetCustomerProfileById : FlexiQueryBridgeAsync<CustomerProfileDto>
{
	protected readonly ILogger<GetCustomerProfileById> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexDocumentStore _documentStore;
	protected GetCustomerProfileByIdParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public GetCustomerProfileById(ILogger<GetCustomerProfileById> logger, IFlexHost flexHost, IFlexDocumentStore documentStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_documentStore = documentStore;
	}

	public virtual GetCustomerProfileById AssignParameters(GetCustomerProfileByIdParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<CustomerProfileDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		var doc = await _documentStore.GetByIdAsync<CustomerProfileDocument>(_params.Id);
		return doc == null ? null : new CustomerProfileDto { Id = doc.Id };
	}
}

public class GetCustomerProfileByIdParams : DtoBridge
{
	public Guid Id { get; set; }
}
```

## Provider-specific considerations

* **Partition keys**: model your access patterns around the partition key to avoid cross-partition scans.
* **Throughput**: keep RU/autoscale settings in config so environments can tune independently.
* **Retries/backoff**: rely on the provider’s retry policies for throttling (429) behavior.


# Raven Db

## Description

RavenDB is used as a **Document DB provider** behind `IFlexDocumentStore`. Generated infrastructure manages cluster URLs, certificates, and conventions while your handlers/queries stay consistent across providers.

## Important Concepts

* **Cluster/conventions are centralized**: provider wiring handles the Raven document store configuration.
* **AppContext is mandatory**: always call `dto.GetAppContext()`.
* **Provider-agnostic business code**: you depend on `IFlexDocumentStore`.

## Configuration in DI (where to add)

Provider wiring is generated in your Infrastructure project (under a `...DataStoreProviders/Document/RavenDb` folder). You typically do **not** register individual queries/handlers here — Flex generates and wires those.

If you are wiring Raven manually, add the **document-store provider** registration where you configure infrastructure services:

```csharp
// Infrastructure (example)
services.AddFlexRavenDocumentStore<TicketDocument>(configuration);
```

## appsettings.json

```json
{
	"FlexBase": {
		"DataStores": {
			"Document": {
				"RavenDb": {
					"Urls": ["https://raven1.company.local", "https://raven2.company.local"],
					"DatabaseName": "{YourApplication}",
					"CertificatePath": "<optional path>",
					"CertificatePassword": "<optional password>",
					"UseOptimisticConcurrency": true
				}
			}
		}
  }
}
```

## Examples (from the generated templates)

Raven uses the standard DocumentStore templates.

### Query example (Get-by-id)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

public class GetTicketById : FlexiQueryBridgeAsync<TicketDto>
{
	protected readonly ILogger<GetTicketById> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexDocumentStore _documentStore;
	protected GetTicketByIdParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public GetTicketById(ILogger<GetTicketById> logger, IFlexHost flexHost, IFlexDocumentStore documentStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_documentStore = documentStore;
	}

	public virtual GetTicketById AssignParameters(GetTicketByIdParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<TicketDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();
		var doc = await _documentStore.GetByIdAsync<TicketDocument>(_params.Id);
		return doc == null ? null : new TicketDto { Id = doc.Id, Status = doc.Status };
	}
}

public class GetTicketByIdParams : DtoBridge
{
	public Guid Id { get; set; }
}
```

## Provider-specific considerations

* **Certificates**: keep cert material in your secrets provider; only reference names/paths in config.
* **Cluster URLs**: prefer multiple URLs for failover.
* **Indexes**: predefine key indexes so queries don’t rely on ad-hoc index creation.


# Dynamo Db

## Description

DynamoDB is used as a **Document DB provider** behind the Flex abstraction (`IFlexDocumentStore`). Generated wiring maps your logical document models to Dynamo tables, and your business logic stays consistent across providers.

## Important Concepts

* **Table metadata is config-driven**: partition key / sort key and table names are configured.
* **Queries/handlers remain provider-agnostic**: you use `IFlexDocumentStore`.
* **AppContext is mandatory**: always call `dto.GetAppContext()`.

## Configuration in DI (where to add)

Provider wiring is generated in your Infrastructure project (under a `...DataStoreProviders/Document/DynamoDb` folder). You typically do **not** register individual queries/handlers here — Flex generates and wires those.

If you are wiring DynamoDB manually, add the **document-store provider** registration where you configure infrastructure services:

```csharp
// Infrastructure (example)
services.AddFlexDynamoDocumentStore<OrderDocument>(configuration);
```

## appsettings.json

```json
{
	"FlexBase": {
		"DataStores": {
			"Document": {
				"DynamoDb": {
					"Region": "us-east-1",
					"AccessKeyId": "<from-secrets>",
					"SecretAccessKey": "<from-secrets>",
					"TableName": "Orders",
					"PartitionKeyName": "id",
					"UseLocalStack": false,
					"ServiceUrl": null
				}
			}
		}
	}
}
```

## Examples (from the generated templates)

Dynamo uses the same generated shapes as other Document DB providers.

### Query example (Get-by-id)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

public class GetOrderById : FlexiQueryBridgeAsync<OrderDto>
{
		protected readonly ILogger<GetOrderById> _logger;
		protected readonly IFlexHost _flexHost;
		protected readonly IFlexDocumentStore _documentStore;
		protected GetOrderByIdParams _params;
		protected FlexAppContextBridge _flexAppContext;

		public GetOrderById(ILogger<GetOrderById> logger, IFlexHost flexHost, IFlexDocumentStore documentStore)
		{
				_logger = logger;
				_flexHost = flexHost;
				_documentStore = documentStore;
		}

		public virtual GetOrderById AssignParameters(GetOrderByIdParams @params)
		{
				_params = @params;
				return this;
		}

		public virtual async Task<OrderDto?> Fetch()
		{
				_flexAppContext = _params.GetAppContext();
				var doc = await _documentStore.GetByIdAsync<OrderDocument>(_params.Id);
				return doc == null ? null : new OrderDto { Id = doc.Id, Status = doc.Status };
		}
}

public class GetOrderByIdParams : DtoBridge
{
		public Guid Id { get; set; }
}
```

## Provider-specific considerations

* **Keys**: design your partition/sort keys around your read patterns.
* **Capacity mode**: provisioned vs on-demand is an environment choice; keep it in configuration.
* **TTL/Streams**: enable TTL for lifecycle cleanup and streams when you need change capture.


# Search Store (Full Text)

## Description

Full-text search providers register through `IFlexSearchStore`. Your application code stays provider-agnostic while the selected provider handles indexing and query execution.

## Infrastructure arrangement

When you add a full-text search provider through **Flex Studio**, Flex generates the provider infrastructure and configuration:

1. Provider files under `Infrastructure/Providers/{YourApplication}.DataStoreProviders/Search/{Provider}/`
2. Default configuration under `Application/EndPoints/{YourApplication}.EndPoint.CommonConfigs/AppSettings/DataStores/Search/{Provider}.json`

Flex auto-wires generated Queries/Handlers/Plugins that use `IFlexSearchStore`—you only register the provider.

## Configuration in DI

Register only the provider search store you need.

```csharp
// Pick ONE provider.
services.AddFlexSqlServerSearchStore(configuration);
// services.AddFlexPostgreSqlSearchStore(configuration);
// services.AddFlexElasticsearchStore(configuration);
```

## appsettings.json

Full-text search configuration is read from `FlexBase:DataStores:Search:<Provider>`.

```json
{
  "FlexBase": {
    "DataStores": {
      "Search": {
        "SqlServer": {
          "ConnectionString": "Server=...;Database=...;User Id=...;Password=<store-in-secrets>;TrustServerCertificate=True",
          "TableName": "dbo.Articles",
          "IdColumn": "Id",
          "SearchableColumns": [ "Title", "Body" ]
        }
      }
    }
  }
}
```

## Sample usage ({YourApplication})

```csharp
public class PolicySearch
{
	private readonly IFlexSearchStore _searchStore;

	public PolicySearch(IFlexSearchStore searchStore)
		=> _searchStore = searchStore;

	public Task<IReadOnlyList<PolicySearchDocument>> SearchAsync(string query)
		=> _searchStore.SearchAsync<PolicySearchDocument>(query, take: 25);
}

public class PolicySearchDocument
{
	public string Id { get; set; }
}
```

## Provider pages

* SQL Server: `search-store-full-text/sql-server-full-text-search.md`
* PostgreSQL: `search-store-full-text/postgre-sql-full-text-search.md`
* Elasticsearch: `search-store-full-text/elastic-search.md`

## Provider considerations

* Use full-text search for keyword-based scenarios (known terms, filters, “contains” style queries).
* If you need provider-specific SQL fragments, use `ProviderSqlMap` inside generated plugins/queries.
* For semantic search, use the Vector Store and keep full-text as a complementary filter.


# Elastic Search

## Description

Elasticsearch can be used as the backing implementation for Flex full-text search. Your application code should depend on `IFlexSearchStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexSearchStore` is the contract**: app code performs searches and indexing through the shared interface, not Elastic SDK types.
* **Indexing + searching**: generated plugins typically call `IndexAsync<TDocument>(document)`, and generated queries call `SearchAsync<TDocument>(query, skip, take)`.
* **Provider bridge**: the Elasticsearch implementation is exposed via an `IFlexSearchStoreBridge` internally, but most consumers only need `IFlexSearchStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexSearchStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers Elasticsearch as the IFlexSearchStore bridge.
		// Flex auto-wires generated Queries/Plugins that *use* IFlexSearchStore.
		services.AddFlexElasticsearchSearchStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:Search:Elasticsearch`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "Search": {
		"Elasticsearch": {
		  "NodeUri": "http://localhost:9200",
		  "Username": null,
		  "Password": null,
		  "ApiKey": null,
		  "IndexName": "your-index-name"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBus plugin templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers/Plugins automatically.

### Search a single document (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Linq;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Search;

public class SearchArticlesGetSingle : FlexiQueryBridgeAsync<ArticleDto>
{
	protected readonly ILogger<SearchArticlesGetSingle> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected SearchArticlesGetSingleParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public SearchArticlesGetSingle(ILogger<SearchArticlesGetSingle> logger, IFlexHost flexHost, IFlexSearchStore searchStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_searchStore = searchStore;
	}

	public virtual SearchArticlesGetSingle AssignParameters(SearchArticlesGetSingleParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<ArticleDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		var results = await _searchStore.SearchAsync<ArticleSearchDocument>(
			_params.Query,
			take: 1);

		var first = results.FirstOrDefault();
		// TODO: map ArticleSearchDocument -> ArticleDto
		return first as ArticleDto;
	}
}

public class SearchArticlesGetSingleParams : DtoBridge
{
	public string Query { get; set; }
}

public class ArticleSearchDocument
{
	public string Id { get; set; }
}
```

### Index a document (PostBus plugin)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Threading.Tasks;

namespace {YourApplication}.PostBus.Search;

public partial class IndexArticleInSearchPlugin : FlexiPluginBase, IFlexiPlugin<IndexArticlePostBusPacket>
{
	protected string EventCondition = "";

	protected readonly ILogger<IndexArticleInSearchPlugin> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected readonly IArticleSearchMapper _mapper;

	protected ArticleSearchDocument? _model;
	protected FlexAppContextBridge? _flexAppContext;

	public IndexArticleInSearchPlugin(
		ILogger<IndexArticleInSearchPlugin> logger,
		IFlexHost flexHost,
		IFlexSearchStore searchStore,
		IArticleSearchMapper mapper)
	{
		_logger = logger;
		_flexHost = flexHost;
		_searchStore = searchStore;
		_mapper = mapper;
	}

	public virtual async Task Execute(IndexArticlePostBusPacket packet)
	{
		_flexAppContext = packet.Cmd.Dto.GetAppContext();  //do not remove this line

		_model = _mapper.MapToSearchDocument(packet.Cmd.Dto);
		await _searchStore.IndexAsync<ArticleSearchDocument>(_model);

		await this.Fire(EventCondition, packet.FlexServiceBusContext);
	}
}

public interface IArticleSearchMapper
{
	ArticleSearchDocument MapToSearchDocument(object dto);
}
```

## Elasticsearch considerations

* Configure exactly one authentication approach: `ApiKey` or `Username`/`Password`.
* `IndexName` should be a stable physical index name (consider aliases/rollovers operationally).


# Sql Server Full Text Search

## Description

SQL Server full-text search can be used as the backing implementation for Flex search operations. Your application code should depend on `IFlexSearchStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexSearchStore` is the contract**: app code performs searches and indexing through the shared interface.
* **Table + column configuration**: SQL Server full-text search requires a target table, an ID column, and searchable columns.
* **Provider bridge**: the SQL Server implementation is exposed via an `IFlexSearchStoreBridge` internally, but most consumers only need `IFlexSearchStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexSearchStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers SQL Server full-text search as the IFlexSearchStore bridge.
		// Flex auto-wires generated Queries/Plugins that *use* IFlexSearchStore.
		services.AddFlexSqlServerSearchStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:Search:SqlServer`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "Search": {
		"SqlServer": {
		  "ConnectionString": "Server=...;Database=...;User Id=...;Password=...;TrustServerCertificate=True;",
		  "TableName": "dbo.Articles",
		  "IdColumn": "Id",
		  "SearchableColumns": [ "Title", "Body" ],
		  "FullTextCatalog": "FlexSearchCatalog",
		  "Language": "English"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBus plugin templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers/Plugins automatically.

### Search a single document (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Linq;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Search;

public class SearchPoliciesGetSingle : FlexiQueryBridgeAsync<PolicyDto>
{
	protected readonly ILogger<SearchPoliciesGetSingle> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected SearchPoliciesGetSingleParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public SearchPoliciesGetSingle(ILogger<SearchPoliciesGetSingle> logger, IFlexHost flexHost, IFlexSearchStore searchStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_searchStore = searchStore;
	}

	public virtual SearchPoliciesGetSingle AssignParameters(SearchPoliciesGetSingleParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<PolicyDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		var results = await _searchStore.SearchAsync<PolicySearchDocument>(
			_params.Query,
			take: 1);

		var first = results.FirstOrDefault();
		// TODO: map PolicySearchDocument -> PolicyDto
		return first as PolicyDto;
	}
}

public class SearchPoliciesGetSingleParams : DtoBridge
{
	public string Query { get; set; }
}

public class PolicySearchDocument
{
	public string Id { get; set; }
}
```

## SQL Server considerations

* Ensure SQL Server Full-Text Search is installed/enabled for the instance.
* The configured database identity must be able to query the full-text catalog and underlying table(s).


# Postgre Sql Full Text Search

## Description

PostgreSQL full-text search can be used as the backing implementation for Flex search operations. Your application code should depend on `IFlexSearchStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexSearchStore` is the contract**: app code performs searches and indexing through the shared interface.
* **Search configuration**: PostgreSQL uses a text search configuration (for example `english`) to control tokenization and stemming.
* **Provider bridge**: the PostgreSQL implementation is exposed via an `IFlexSearchStoreBridge` internally, but most consumers only need `IFlexSearchStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexSearchStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers PostgreSQL full-text search as the IFlexSearchStore bridge.
		// Flex auto-wires generated Queries/Plugins that *use* IFlexSearchStore.
		services.AddFlexPostgreSqlSearchStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:Search:PostgreSql`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "Search": {
		"PostgreSql": {
		  "ConnectionString": "Host=...;Database=...;Username=...;Password=...",
		  "SearchConfiguration": "english"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBus plugin templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers/Plugins automatically.

### Search a paged list (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Search;

public class SearchArticlesPaged : FlexiQueryPagedListBridgeAsync<SearchArticlesPagedParams, ArticleDto, FlexAppContextBridge>
{
	protected readonly ILogger<SearchArticlesPaged> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected SearchArticlesPagedParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public SearchArticlesPaged(ILogger<SearchArticlesPaged> logger, IFlexHost flexHost, IFlexSearchStore searchStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_searchStore = searchStore;
	}

	public virtual SearchArticlesPaged AssignParameters(SearchArticlesPagedParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<PagedResult<ArticleDto>> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		var skip = (_params.PageNumber - 1) * _params.PageSize;
		var results = await _searchStore.SearchAsync<ArticleSearchDocument>(
			_params.Query,
			skip: skip,
			take: _params.PageSize);

		var list = results.ToList();
		// TODO: map ArticleSearchDocument -> ArticleDto, and compute true totalCount if supported
		return new PagedResult<ArticleDto>
		{
			Items = list as IEnumerable<ArticleDto>,
			TotalCount = list.Count,
			PageNumber = _params.PageNumber,
			PageSize = _params.PageSize
		};
	}
}

public class SearchArticlesPagedParams : DtoBridge
{
	public string Query { get; set; }
	public int PageNumber { get; set; } = 1;
	public int PageSize { get; set; } = 20;
}

public class ArticleSearchDocument
{
	public string Id { get; set; }
}
```

## PostgreSQL considerations

* Ensure your database/table setup supports full-text indexes for your data shape.
* `SearchConfiguration` should match the language/analyzer behavior you expect (for example `simple` vs `english`).


# File Store

## Description

File stores register through `IFlexFileStore` (and optional `IFlexFileStoreWithUrls` / `IFlexFileStoreWithDirectories`). Your application code stays provider-agnostic while AWS S3, Azure Blob, and GCP Cloud Storage handle object storage.

## Configuration in DI

Register only the provider.

```csharp
// Pick ONE
services.AddFlexAwsS3FileStore(configuration);
// services.AddFlexAzureBlobFileStore(configuration);
// services.AddFlexGcpCloudStorageFileStore(configuration);
```

## appsettings.json

File store configuration is read from `FlexBase:DataStores:File:<Provider>`.

```json
{
  "FlexBase": {
    "DataStores": {
      "File": {
        "AwsS3": {
          "AccessKeyId": "<store-in-secrets>",
          "SecretAccessKey": "<store-in-secrets>",
          "Region": "us-east-1"
        }
      }
    }
  }
}
```

## Sample usage ({YourApplication})

```csharp
public class BackupUploader
{
	private readonly IFlexFileStore _fileStore;

	public BackupUploader(IFlexFileStore fileStore)
		=> _fileStore = fileStore;

	public Task UploadAsync(Stream payload, CancellationToken ct = default)
		=> _fileStore.WriteAsync(
			container: "backups",
			path: "daily/backup.zip",
			content: payload,
			contentType: "application/zip",
			ct: ct);
}
```

## Provider pages

* AWS S3: `file-store/aws-s3.md`
* Azure Blob: `file-store/azure-blob.md`
* GCP Cloud Storage: `file-store/gcp-cloud-storage.md`

## Provider considerations

* Treat `container` as bucket/container/root folder, and `path` as a forward-slash key.
* Keep credentials in secrets.


# Disk

## Description

For local development, single-node deployments, or simple on-prem scenarios, you can back `IFlexFileStore` with the local filesystem using `LocalFileStore`.

## Important concepts

* **`LocalFileStore` is a core implementation**: it lives in `Sumeru.Flex.Core` and does not require a cloud SDK.
* **Base path scoping**: all operations are relative to a configured `BasePath`.
* **Permissions matter**: the host process must have read/write access to the base directory.

## Configuration in DI

Unlike cloud providers, `LocalFileStore` is wired directly (there isn’t a generated `AddFlex...FileStore(...)` extension for it).

Add this in your DI composition root (commonly `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs`).

```csharp
using Sumeru.Flex;
using Microsoft.Extensions.Options;

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		services.Configure<LocalFileStoreOptions>(
			configuration.GetSection("FlexBase:DataStores:File:LocalFileSystem"));

		services.AddSingleton<IFlexFileStore>(sp =>
		{
			var options = sp.GetRequiredService<IOptions<LocalFileStoreOptions>>().Value;
			return new LocalFileStore(options);
		});

		return services;
	}
}
```

## appsettings.json

You can choose any section name; this example uses `FlexBase:DataStores:File:LocalFileSystem`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "File": {
		"LocalFileSystem": {
		  "BasePath": "D:/Data/{YourApplication}/files",
		  "CreateDirectoriesOnWrite": true
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Upload file (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Files;

public partial class UploadFileHandler : IAmFlexCommandHandler<UploadFileCommand>
{
	protected string EventCondition = "";
	protected readonly ILogger<UploadFileHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;

	public UploadFileHandler(ILogger<UploadFileHandler> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual async Task Execute(UploadFileCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		var appContext = cmd.Dto.GetAppContext(); // do not remove this line
		var model = _flexHost.GetDomainModel<FileModel>().Create(cmd);

		var fileId = await _fileStore.UploadAsync(cmd.Dto.Stream, cmd.Dto.FileName, cmd.Dto.ContentType, cmd.Dto.Metadata);
		await this.Fire(EventCondition, serviceBusContext);
	}
}

public class UploadFileCommand : FlexCommandBridge<UploadFileDto> { }
public class UploadFileDto : DtoBridge
{
	public Stream Stream { get; set; }
	public string FileName { get; set; }
	public string ContentType { get; set; }
	public IDictionary<string, string>? Metadata { get; set; }
}
public class FileModel : FlexDomainModelBridge { }
```

### Download file (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Files;

public class DownloadFileQuery : FlexiQueryBridgeAsync<FileDownloadOutput>
{
	protected readonly IFlexFileStore _fileStore;
	protected DownloadFileParams _params;

	public DownloadFileQuery(ILogger<DownloadFileQuery> logger, IFlexHost flexHost, IFlexFileStore fileStore)
		=> _fileStore = fileStore;

	public virtual DownloadFileQuery AssignParameters(DownloadFileParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<FileDownloadOutput?> Fetch()
	{
		var appContext = _params.GetAppContext();
		var stream = await _fileStore.DownloadAsync(_params.FileId);
		if (stream == null) return default;
		return new FileDownloadOutput { FileId = _params.FileId, Stream = stream };
	}
}

public class DownloadFileParams : DtoBridge { public string FileId { get; set; } }
public class FileDownloadOutput : DtoBridge { public string FileId { get; set; } public Stream Stream { get; set; } }
```

## Library-specific considerations

* **Path + permissions**: pick an absolute `BasePath` and ensure the app identity can read/write.
* **Multi-instance**: local disk is not shared across nodes; use a cloud provider if you need horizontal scale.


# Azure Blob

## Description

Azure Blob Storage can be used as the backing implementation for Flex file operations. Your application code should depend on `IFlexFileStore`, while Flex provides the Azure Blob implementation and wiring.

## Important concepts

* **`IFlexFileStore` is the contract**: uploads/downloads are done through a shared abstraction.
* **Streaming**: uploads use a `Stream`; downloads return a `Stream?` (handle `null` if the file doesn’t exist).
* **Container scoping**: the provider typically writes into a configured container.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs`).

```csharp
public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers Azure Blob as the IFlexFileStore bridge.
		services.AddFlexAzureBlobFileStore(configuration);
		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:File:AzureBlob`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "File": {
		"AzureBlob": {
		  "ConnectionString": "...",
		  "ContainerName": "your-container",
		  "CreateContainerIfNotExists": true
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Upload file (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Files;

public partial class UploadFileHandler : IAmFlexCommandHandler<UploadFileCommand>
{
	protected string EventCondition = "";
	protected readonly ILogger<UploadFileHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;

	public UploadFileHandler(ILogger<UploadFileHandler> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual async Task Execute(UploadFileCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		_logger.LogDebug("Starting Upload for {EntityType}", nameof(FileModel));
		var appContext = cmd.Dto.GetAppContext(); // do not remove this line

		var model = _flexHost.GetDomainModel<FileModel>().Create(cmd);

		var fileId = await _fileStore.UploadAsync(
			cmd.Dto.Stream,
			cmd.Dto.FileName,
			cmd.Dto.ContentType,
			cmd.Dto.Metadata);

		await this.Fire(EventCondition, serviceBusContext);
		_logger.LogDebug("Completed Upload for {EntityType} {FileId}, Event: {EventCondition}", nameof(FileModel), fileId, EventCondition);
	}
}

public class UploadFileCommand : FlexCommandBridge<UploadFileDto> { }
public class UploadFileDto : DtoBridge
{
	public Stream Stream { get; set; }
	public string FileName { get; set; }
	public string ContentType { get; set; }
	public IDictionary<string, string>? Metadata { get; set; }
}
public class FileModel : FlexDomainModelBridge { }
```

### Download file (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Files;

public class DownloadFileQuery : FlexiQueryBridgeAsync<FileDownloadOutput>
{
	protected readonly ILogger<DownloadFileQuery> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;
	protected DownloadFileParams _params;

	public DownloadFileQuery(ILogger<DownloadFileQuery> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual DownloadFileQuery AssignParameters(DownloadFileParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<FileDownloadOutput?> Fetch()
	{
		var appContext = _params.GetAppContext();
		var stream = await _fileStore.DownloadAsync(_params.FileId);
		if (stream == null) return default;

		return new FileDownloadOutput { FileId = _params.FileId, Stream = stream };
	}
}

public class DownloadFileParams : DtoBridge { public string FileId { get; set; } }
public class FileDownloadOutput : DtoBridge
{
	public string FileId { get; set; }
	public Stream Stream { get; set; }
}
```

## Library-specific considerations

* **Connection string**: store it in a secret manager and inject via configuration.
* **Container creation**: `CreateContainerIfNotExists=true` is convenient for dev; production setups often pre-provision containers.


# AWS S3

## Description

AWS S3 can be used as the backing implementation for Flex file operations. Your application code should depend on `IFlexFileStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexFileStore` is the contract**: app code uploads/downloads using the shared interface rather than AWS SDK types.
* **Files are streamed**: uploads use a `Stream`; downloads return a `Stream?` (when a file doesn’t exist, you should handle `null`).
* **Provider bridge**: the AWS implementation is exposed via an `IFlexFileStoreBridge` internally, but most consumers only need `IFlexFileStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexFileStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers AWS S3 as the IFlexFileStore bridge.
		// Flex auto-wires generated Queries/Handlers that *use* IFlexFileStore.
		services.AddFlexAwsS3FileStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:File:AwsS3`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "File": {
		"AwsS3": {
		  "AccessKeyId": "...",
		  "SecretAccessKey": "...",
		  "Region": "us-east-1",
		  "BucketName": "your-bucket-name",
		  "ServiceUrl": null
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Upload file (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Files;

public partial class UploadFileHandler : IAmFlexCommandHandler<UploadFileCommand>
{
	protected string EventCondition = "";

	protected readonly ILogger<UploadFileHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;

	public UploadFileHandler(ILogger<UploadFileHandler> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual async Task Execute(UploadFileCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		_logger.LogDebug("Starting Upload for {EntityType}", nameof(FileModel));

		var appContext = cmd.Dto.GetAppContext(); // do not remove this line

		var model = _flexHost.GetDomainModel<FileModel>().Create(cmd);

		var fileId = await _fileStore.UploadAsync(
			cmd.Dto.Stream,
			cmd.Dto.FileName,
			cmd.Dto.ContentType,
			cmd.Dto.Metadata);

		// Example:
		// EventCondition = UploadFileEvents.CONDITION_ONSUCCESS;
		await this.Fire(EventCondition, serviceBusContext);

		_logger.LogDebug("Completed Upload for {EntityType} {FileId}, Event: {EventCondition}", nameof(FileModel), fileId, EventCondition);
	}
}

public class UploadFileCommand : FlexCommandBridge<UploadFileDto> { }

public class UploadFileDto : DtoBridge
{
	public Stream Stream { get; set; }
	public string FileName { get; set; }
	public string ContentType { get; set; }
	public IDictionary<string, string>? Metadata { get; set; }
}

public class FileModel : FlexDomainModelBridge { }
```

### Download file (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Files;

public class DownloadFileQuery : FlexiQueryBridgeAsync<FileDownloadOutput>
{
	protected readonly ILogger<DownloadFileQuery> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;
	protected DownloadFileParams _params;

	public DownloadFileQuery(ILogger<DownloadFileQuery> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual DownloadFileQuery AssignParameters(DownloadFileParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<FileDownloadOutput?> Fetch()
	{
		var appContext = _params.GetAppContext();

		var stream = await _fileStore.DownloadAsync(_params.FileId);
		if (stream == null)
		{
			return default;
		}

		return new FileDownloadOutput
		{
			FileId = _params.FileId,
			Stream = stream
		};
	}
}

public class DownloadFileParams : DtoBridge
{
	public string FileId { get; set; }
}

public class FileDownloadOutput : DtoBridge
{
	public string FileId { get; set; }
	public Stream Stream { get; set; }
	public string? FileName { get; set; }
	public string? ContentType { get; set; }
}
```

## Library-specific considerations

* **Credentials**: prefer environment/secret manager injection; avoid committing `AccessKeyId` / `SecretAccessKey` to source control.
* **Bucket policy**: the executing identity typically needs `s3:GetObject`, `s3:PutObject`, and `s3:ListBucket`.
* **`ServiceUrl`**: useful for S3-compatible endpoints (for example LocalStack or MinIO).


# Gcp Cloud Storage (Google)

## Description

Google Cloud Storage can be used as the backing implementation for Flex file operations. Your application code should depend on `IFlexFileStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexFileStore` is the contract**: your code uploads/downloads through a shared abstraction.
* **Streaming**: uploads use a `Stream`; downloads return a `Stream?`.
* **Credentials**: prefer service accounts; keep credentials out of source control.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs`).

```csharp
public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers GCP Cloud Storage as the IFlexFileStore bridge.
		services.AddFlexGcpCloudStorageFileStore(configuration);
		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:File:GcpCloudStorage`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "File": {
		"GcpCloudStorage": {
		  "ProjectId": "your-gcp-project-id",
		  "BucketName": "your-bucket-name",
		  "CredentialsJsonPath": "C:/secrets/gcp-service-account.json"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Upload file (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Files;

public partial class UploadFileHandler : IAmFlexCommandHandler<UploadFileCommand>
{
	protected string EventCondition = "";
	protected readonly ILogger<UploadFileHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexFileStore _fileStore;

	public UploadFileHandler(ILogger<UploadFileHandler> logger, IFlexHost flexHost, IFlexFileStore fileStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_fileStore = fileStore;
	}

	public virtual async Task Execute(UploadFileCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		var appContext = cmd.Dto.GetAppContext(); // do not remove this line
		var model = _flexHost.GetDomainModel<FileModel>().Create(cmd);

		var fileId = await _fileStore.UploadAsync(cmd.Dto.Stream, cmd.Dto.FileName, cmd.Dto.ContentType, cmd.Dto.Metadata);
		await this.Fire(EventCondition, serviceBusContext);
	}
}

public class UploadFileCommand : FlexCommandBridge<UploadFileDto> { }
public class UploadFileDto : DtoBridge
{
	public Stream Stream { get; set; }
	public string FileName { get; set; }
	public string ContentType { get; set; }
	public IDictionary<string, string>? Metadata { get; set; }
}
public class FileModel : FlexDomainModelBridge { }
```

### Download file (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.IO;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Files;

public class DownloadFileQuery : FlexiQueryBridgeAsync<FileDownloadOutput>
{
	protected readonly IFlexFileStore _fileStore;
	protected DownloadFileParams _params;

	public DownloadFileQuery(ILogger<DownloadFileQuery> logger, IFlexHost flexHost, IFlexFileStore fileStore)
		=> _fileStore = fileStore;

	public virtual DownloadFileQuery AssignParameters(DownloadFileParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<FileDownloadOutput?> Fetch()
	{
		var appContext = _params.GetAppContext();
		var stream = await _fileStore.DownloadAsync(_params.FileId);
		if (stream == null) return default;
		return new FileDownloadOutput { FileId = _params.FileId, Stream = stream };
	}
}

public class DownloadFileParams : DtoBridge { public string FileId { get; set; } }
public class FileDownloadOutput : DtoBridge { public string FileId { get; set; } public Stream Stream { get; set; } }
```

## Library-specific considerations

* **Service account permissions**: grant `storage.objects.create`, `storage.objects.get`, and `storage.objects.list` on the bucket.
* **Credentials path**: prefer mounting the JSON file at runtime (or use workload identity where available).


# Time Series Store

## Description

Time-series providers register through `IFlexTimeSeriesStore`. Your application code stays provider-agnostic while the selected provider handles ingestion, querying, and retention.

## Infrastructure arrangement

When you add a time-series provider through **Flex Studio**, Flex generates the provider infrastructure and configuration:

1. Provider files under `Infrastructure/Providers/{YourApplication}.DataStoreProviders/TimeSeries/{Provider}/`
2. Default configuration under `Application/EndPoints/{YourApplication}.EndPoint.CommonConfigs/AppSettings/DataStores/TimeSeries/{Provider}.json`

Flex auto-wires generated Queries/Handlers/Plugins that use `IFlexTimeSeriesStore`—you only register the provider.

## Configuration in DI

Register only the provider time-series store you need.

```csharp
// Pick ONE provider.
services.AddFlexAzureDataExplorerTimeSeriesStore(configuration);
// services.AddFlexInfluxDBTimeSeriesStore(configuration);
// services.AddFlexTimescaleDBTimeSeriesStore(configuration);
```

## appsettings.json

Time-series configuration is read from `FlexBase:DataStores:TimeSeries:<Provider>`.

```json
{
  "FlexBase": {
    "DataStores": {
      "TimeSeries": {
        "InfluxDB": {
          "Url": "http://localhost:8086",
          "Token": "<store-in-secrets>",
          "Organization": "your-org",
          "Bucket": "your-bucket"
        }
      }
    }
  }
}
```

## Sample usage ({YourApplication})

```csharp
public class MetricReporter
{
	private readonly IFlexTimeSeriesStore _timeSeries;

	public MetricReporter(IFlexTimeSeriesStore timeSeries)
		=> _timeSeries = timeSeries;

	public Task RecordAsync(MetricPoint point)
		=> _timeSeries.WriteAsync<MetricPoint>(point);
}

public class MetricPoint
{
	public string SeriesId { get; set; }
	public DateTime Timestamp { get; set; }
}
```

## Provider pages

* Azure Data Explorer (Kusto): `time-series-store/azure-data-explorer.md`
* InfluxDB: `time-series-store/influx-db.md`
* TimescaleDB: `time-series-store/timescale-db.md`

## Provider considerations

* Keep secrets (tokens/credentials/connection strings) out of source control.
* Configure retention and batching in the provider section to match your telemetry volume.


# Influx Db

## Description

InfluxDB can be used as the backing implementation for Flex time-series operations. Your application code should depend on `IFlexTimeSeriesStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexTimeSeriesStore` is the contract**: app code writes and queries time-series data via a shared interface.
* **Bucket-based storage**: InfluxDB typically stores points into a bucket (configured in appsettings).
* **Provider bridge**: the InfluxDB implementation is exposed via an `IFlexTimeSeriesStoreBridge` internally, but most consumers only need `IFlexTimeSeriesStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexTimeSeriesStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers InfluxDB as the IFlexTimeSeriesStore bridge.
		// Flex auto-wires generated Queries/Handlers that *use* IFlexTimeSeriesStore.
		services.AddFlexInfluxDBTimeSeriesStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:TimeSeries:InfluxDB`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "TimeSeries": {
		"InfluxDB": {
		  "Url": "http://localhost:8086",
		  "Token": "...",
		  "Organization": "your-org",
		  "Bucket": "your-bucket"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Get points in a time range (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.TimeSeries;

public class TelemetryGetRange : FlexiQueryEnumerableBridgeAsync<TelemetryPointDto>
{
	protected readonly ILogger<TelemetryGetRange> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexTimeSeriesStore _timeSeriesStore;
	protected TelemetryGetRangeParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public TelemetryGetRange(ILogger<TelemetryGetRange> logger, IFlexHost flexHost, IFlexTimeSeriesStore timeSeriesStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_timeSeriesStore = timeSeriesStore;
	}

	public virtual TelemetryGetRange AssignParameters(TelemetryGetRangeParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<IEnumerable<TelemetryPointDto>> Fetch()
	{
		_flexAppContext = _params.GetAppContext();
		var points = await _timeSeriesStore.QueryAsync<TelemetryPoint>(_params.SeriesId, _params.StartTime, _params.EndTime);
		// TODO: map TelemetryPoint -> TelemetryPointDto
		return points as IEnumerable<TelemetryPointDto>;
	}
}

public class TelemetryGetRangeParams : DtoBridge
{
	public string SeriesId { get; set; }
	public DateTime StartTime { get; set; }
	public DateTime EndTime { get; set; }
}
```

## InfluxDB considerations

* Keep `Token` in a secrets provider (don’t commit it to source control).
* Ensure `Bucket` exists and the token has access to read/write it.


# Azure Data Explorer

## Description

Azure Data Explorer (Kusto) can be used as the backing implementation for Flex time-series operations. Your application code should depend on `IFlexTimeSeriesStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexTimeSeriesStore` is the contract**: app code writes and queries time-series data via a shared interface.
* **Write + query patterns**: generated handlers typically call `WriteAsync<TPoint>(point)`, and generated queries use `GetLatestAsync<TPoint>(seriesId)` / `QueryAsync<TPoint>(seriesId, start, end)`.
* **Provider bridge**: the Azure Data Explorer implementation is exposed via an `IFlexTimeSeriesStoreBridge` internally, but most consumers only need `IFlexTimeSeriesStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexTimeSeriesStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers Azure Data Explorer as the IFlexTimeSeriesStore bridge.
		// Flex auto-wires generated Queries/Handlers that *use* IFlexTimeSeriesStore.
		services.AddFlexAzureDataExplorerTimeSeriesStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:TimeSeries:AzureDataExplorer`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "TimeSeries": {
		"AzureDataExplorer": {
		  "ClusterUri": "https://yourcluster.region.kusto.windows.net",
		  "Database": "your-database",
		  "ClientId": null,
		  "ClientSecret": null,
		  "TenantId": null
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Write a data point (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.TimeSeries;

public partial class WriteTelemetryPointHandler : IAmFlexCommandHandler<WriteTelemetryPointCommand>
{
	protected string EventCondition = "";

	protected readonly ILogger<WriteTelemetryPointHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexTimeSeriesStore _timeSeriesStore;

	protected TelemetryPoint? _model;
	protected FlexAppContextBridge? _flexAppContext;

	public WriteTelemetryPointHandler(
		ILogger<WriteTelemetryPointHandler> logger,
		IFlexHost flexHost,
		IFlexTimeSeriesStore timeSeriesStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_timeSeriesStore = timeSeriesStore;
	}

	public virtual async Task Execute(WriteTelemetryPointCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		_logger.LogDebug("Starting Write for {EntityType}", nameof(TelemetryPoint));
		_flexAppContext = cmd.Dto.GetAppContext();  //do not remove this line

		_model = _flexHost.GetDomainModel<TelemetryPoint>().Create(cmd);
		await _timeSeriesStore.WriteAsync<TelemetryPoint>(_model);

		await this.Fire(EventCondition, serviceBusContext);
	}
}

public class TelemetryPoint
{
	public string SeriesId { get; set; }
	public DateTime Timestamp { get; set; }
}
```

### Get the latest point (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.TimeSeries;

public class TelemetryGetLatest : FlexiQueryBridgeAsync<TelemetryPointDto>
{
	protected readonly ILogger<TelemetryGetLatest> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexTimeSeriesStore _timeSeriesStore;
	protected TelemetryGetLatestParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public TelemetryGetLatest(ILogger<TelemetryGetLatest> logger, IFlexHost flexHost, IFlexTimeSeriesStore timeSeriesStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_timeSeriesStore = timeSeriesStore;
	}

	public virtual TelemetryGetLatest AssignParameters(TelemetryGetLatestParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<TelemetryPointDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();
		var latest = await _timeSeriesStore.GetLatestAsync<TelemetryPoint>(_params.SeriesId);
		// TODO: map TelemetryPoint -> TelemetryPointDto
		return latest as TelemetryPointDto;
	}
}

public class TelemetryGetLatestParams : DtoBridge
{
	public string SeriesId { get; set; }
}
```

## Azure Data Explorer considerations

* `ClusterUri` and `Database` are required for cluster mode.
* If you need custom authentication behavior (managed identity vs app registration), handle it via environment/Azure identity configuration or by overriding the generated bridge in your application.


# Timescale Db

## Description

TimescaleDB (PostgreSQL extension) can be used as the backing implementation for Flex time-series operations. Your application code should depend on `IFlexTimeSeriesStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexTimeSeriesStore` is the contract**: app code writes and queries time-series data via a shared interface.
* **PostgreSQL connection + schema**: TimescaleDB is accessed through a Postgres connection string and optional schema.
* **Provider bridge**: the TimescaleDB implementation is exposed via an `IFlexTimeSeriesStoreBridge` internally, but most consumers only need `IFlexTimeSeriesStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexTimeSeriesStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers TimescaleDB as the IFlexTimeSeriesStore bridge.
		// Flex auto-wires generated Queries/Handlers that *use* IFlexTimeSeriesStore.
		services.AddFlexTimescaleDBTimeSeriesStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:TimeSeries:TimescaleDB`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "TimeSeries": {
		"TimescaleDB": {
		  "ConnectionString": "Host=...;Database=...;Username=...;Password=...",
		  "Schema": "public",
		  "TableName": "telemetry_points",
		  "TimeColumn": "time"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Get the latest point (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.TimeSeries;

public class SensorGetLatest : FlexiQueryBridgeAsync<SensorPointDto>
{
	protected readonly ILogger<SensorGetLatest> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexTimeSeriesStore _timeSeriesStore;
	protected SensorGetLatestParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public SensorGetLatest(ILogger<SensorGetLatest> logger, IFlexHost flexHost, IFlexTimeSeriesStore timeSeriesStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_timeSeriesStore = timeSeriesStore;
	}

	public virtual SensorGetLatest AssignParameters(SensorGetLatestParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<SensorPointDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();
		var latest = await _timeSeriesStore.GetLatestAsync<SensorPoint>(_params.SeriesId);
		// TODO: map SensorPoint -> SensorPointDto
		return latest as SensorPointDto;
	}
}

public class SensorGetLatestParams : DtoBridge
{
	public string SeriesId { get; set; }
}
```

## TimescaleDB considerations

* Make sure the TimescaleDB extension is installed/enabled in your Postgres instance.
* Store `ConnectionString` securely (Key Vault / secret provider).


# Graph Store

## Description

Graph stores register through `IFlexGraphStore`, providing a provider-agnostic API for node/edge CRUD and traversals.

## Configuration in DI

Register only the provider.

```csharp
// Pick ONE
services.AddFlexNeo4jGraphStore(configuration);
// services.AddFlexCosmosGremlinGraphStore(configuration);
```

## appsettings.json

Graph store configuration is read from `FlexBase:DataStores:Graph:<Provider>`.

```json
{
	"FlexBase": {
		"DataStores": {
			"Graph": {
				"Neo4j": {
					"Uri": "bolt://localhost:7687",
					"Username": "neo4j",
					"Password": "<store-in-secrets>"
				}
			}
		}
	}
}
```

## Sample usage ({YourApplication})

```csharp
public class ConnectionFinder
{
	private readonly IFlexGraphStore _graphStore;

	public ConnectionFinder(IFlexGraphStore graphStore)
		=> _graphStore = graphStore;

	public Task<IReadOnlyList<FlexGraphNode>> FindPeopleAsync(CancellationToken ct = default)
		=> _graphStore.FindNodesAsync(label: "Person", limit: 50, ct: ct);
}
```

## Provider pages

* Neo4j: `graph-store/neo4j.md`
* Cosmos Gremlin: `graph-store/cosmos-gremlin.md`

## Provider considerations

* Graph providers vary in query language; prefer the structured `IFlexGraphStore` APIs for portability.


# Neo4j

## Description

Neo4j can be used as the backing implementation for Flex graph operations. Your application code should depend on `IFlexGraphStore`, while Flex provides the Neo4j implementation and wiring.

## Important concepts

* **`IFlexGraphStore` is the contract**: your app uses a shared graph abstraction rather than Neo4j driver APIs.
* **Nodes are models**: graph operations typically read/write node models (domain models) through the store.
* **Generated flow**: generated handlers/queries use `cmd.Dto.GetAppContext()` / `params.GetAppContext()` and then call `IFlexGraphStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs`).

```csharp
public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers Neo4j as the IFlexGraphStore bridge.
		// Flex auto-wires generated Queries/Handlers that use IFlexGraphStore.
		services.AddFlexNeo4jGraphStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:Graph:Neo4j`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "Graph": {
		"Neo4j": {
		  "Uri": "bolt://localhost:7687",
		  "Username": "neo4j",
		  "Password": "...",
		  "Database": "neo4j"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Create node (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Graph;

public partial class CreateUserNodeHandler : IAmFlexCommandHandler<CreateUserNodeCommand>
{
	protected string EventCondition = "";

	protected readonly ILogger<CreateUserNodeHandler> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexGraphStore _graphStore;

	public CreateUserNodeHandler(ILogger<CreateUserNodeHandler> logger, IFlexHost flexHost, IFlexGraphStore graphStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_graphStore = graphStore;
	}

	public virtual async Task Execute(CreateUserNodeCommand cmd, IFlexServiceBusContext serviceBusContext)
	{
		_logger.LogDebug("Starting Create Node for {EntityType}", nameof(UserNodeModel));

		var appContext = cmd.Dto.GetAppContext(); // do not remove this line

		var model = _flexHost.GetDomainModel<UserNodeModel>().Create(cmd);
		await _graphStore.CreateNodeAsync(model);

		// Example:
		// EventCondition = CreateUserNodeEvents.CONDITION_ONSUCCESS;
		await this.Fire(EventCondition, serviceBusContext);
	}
}

public class CreateUserNodeCommand : FlexCommandBridge<CreateUserNodeDto> { }

public class CreateUserNodeDto : DtoBridge
{
	public Guid Id { get; set; }
	public string UserName { get; set; }
}

public class UserNodeModel : FlexDomainModelBridge
{
	public Guid Id { get; set; }
	public string UserName { get; set; }
}
```

### Get node by ID (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Graph;

public class GetUserNodeByIdQuery : FlexiQueryBridgeAsync<UserNodeDto>
{
	protected readonly ILogger<GetUserNodeByIdQuery> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexGraphStore _graphStore;
	protected GetUserNodeByIdParams _params;

	public GetUserNodeByIdQuery(ILogger<GetUserNodeByIdQuery> logger, IFlexHost flexHost, IFlexGraphStore graphStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_graphStore = graphStore;
	}

	public virtual GetUserNodeByIdQuery AssignParameters(GetUserNodeByIdParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<UserNodeDto?> Fetch()
	{
		var appContext = _params.GetAppContext();

		var node = await _graphStore.GetNodeByIdAsync<UserNodeModel>(_params.Id);
		if (node == null) return default;

		return new UserNodeDto { Id = node.Id, UserName = node.UserName };
	}
}

public class GetUserNodeByIdParams : DtoBridge
{
	public Guid Id { get; set; }
}

public class UserNodeDto : DtoBridge
{
	public Guid Id { get; set; }
	public string UserName { get; set; }
}
```

## Library-specific considerations

* **Secrets**: store Neo4j passwords in a secret manager and inject via configuration.
* **Connection URI**: use `bolt+s://` (or your cluster’s required scheme) when connecting over TLS.


# Cosmos Gremlin

## Description

Azure Cosmos DB Gremlin can be used as the backing implementation for Flex graph operations. Your application code should depend on `IFlexGraphStore`, while Flex provides the Cosmos Gremlin implementation and wiring.

## Important concepts

* **`IFlexGraphStore` is the contract**: your code uses a shared store abstraction.
* **Gremlin vs. model operations**: generated templates typically show model-oriented operations (create node / get by id). Provider-specific traversal helpers may exist, but start with the shared operations first.
* **Partitioning matters**: Cosmos performance depends heavily on partition key selection.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs`).

```csharp
public static class OtherApplicationServicesConfig
{
		public static IServiceCollection AddOtherApplicationServices(
				this IServiceCollection services,
				IConfiguration configuration)
		{
				// Registers Cosmos Gremlin as the IFlexGraphStore bridge.
				// Flex auto-wires generated Queries/Handlers that use IFlexGraphStore.
				services.AddFlexCosmosGremlinGraphStore(configuration);

				return services;
		}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:Graph:CosmosGremlin`.

```json
{
	"FlexBase": {
		"DataStores": {
			"Graph": {
				"CosmosGremlin": {
					"Hostname": "your-account.gremlin.cosmos.azure.com",
					"Port": 443,
					"Database": "your-database",
					"Container": "your-graph-container",
					"PrimaryKey": "...",
					"PartitionKey": "pk"
				}
			}
		}
	}
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBusHandler templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers automatically.

### Create node (PostBusHandler)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

namespace {YourApplication}.Handlers.Graph;

public partial class CreateUserNodeHandler : IAmFlexCommandHandler<CreateUserNodeCommand>
{
		protected string EventCondition = "";
		protected readonly ILogger<CreateUserNodeHandler> _logger;
		protected readonly IFlexHost _flexHost;
		protected readonly IFlexGraphStore _graphStore;

		public CreateUserNodeHandler(ILogger<CreateUserNodeHandler> logger, IFlexHost flexHost, IFlexGraphStore graphStore)
		{
				_logger = logger;
				_flexHost = flexHost;
				_graphStore = graphStore;
		}

		public virtual async Task Execute(CreateUserNodeCommand cmd, IFlexServiceBusContext serviceBusContext)
		{
				var appContext = cmd.Dto.GetAppContext(); // do not remove this line
				var model = _flexHost.GetDomainModel<UserNodeModel>().Create(cmd);

				await _graphStore.CreateNodeAsync(model);
				await this.Fire(EventCondition, serviceBusContext);
		}
}

public class CreateUserNodeCommand : FlexCommandBridge<CreateUserNodeDto> { }
public class CreateUserNodeDto : DtoBridge { public string Id { get; set; } public string UserName { get; set; } }
public class UserNodeModel : FlexDomainModelBridge { public string Id { get; set; } public string UserName { get; set; } }
```

### Get node by ID (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Graph;

public class GetUserNodeByIdQuery : FlexiQueryBridgeAsync<UserNodeDto>
{
		protected readonly IFlexGraphStore _graphStore;
		protected GetUserNodeByIdParams _params;

		public GetUserNodeByIdQuery(ILogger<GetUserNodeByIdQuery> logger, IFlexHost flexHost, IFlexGraphStore graphStore)
				=> _graphStore = graphStore;

		public virtual GetUserNodeByIdQuery AssignParameters(GetUserNodeByIdParams @params)
		{
				_params = @params;
				return this;
		}

		public virtual async Task<UserNodeDto?> Fetch()
		{
				var appContext = _params.GetAppContext();
				var node = await _graphStore.GetNodeByIdAsync<UserNodeModel>(_params.Id);
				if (node == null) return default;

				return new UserNodeDto { Id = node.Id, UserName = node.UserName };
		}
}

public class GetUserNodeByIdParams : DtoBridge { public string Id { get; set; } }
public class UserNodeDto : DtoBridge { public string Id { get; set; } public string UserName { get; set; } }
public class UserNodeModel : FlexDomainModelBridge { public string Id { get; set; } public string UserName { get; set; } }
```

## Library-specific considerations

* **Primary key**: `PrimaryKey` should be treated like a secret; store it securely.
* **Partition key**: keep `PartitionKey` stable once data is written; changing it later is typically a migration.
* **Networking**: Cosmos Gremlin is commonly locked down with firewall/VNet rules—ensure your app host can reach `Hostname:Port`.




---

[Next Page](https://docs.flexbase.in/llms-full.txt/1)

