> For the complete documentation index, see [llms.txt](https://docs.flexbase.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flexbase.in/solution-structure/getting-started/features/crud/get-by-id-example.md).

# 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!** 🚀
