Code Examples

Learn RedBase by example. Browse working code samples for LINQ queries, bulk operations, tree structures, and more.

Data Model - EmployeeProps Click to view data model used in all examples
Tag with priority for categorization.
/// <summary>
/// Tag with priority for categorization.
/// </summary>
public class Tag
{
    public string Name { get; set; } = string.Empty;
    public int Priority { get; set; }
    public string? Description { get; set; }
}

/// <summary>
/// Project metrics for analytics.
/// </summary>
[RedbScheme("ProjectMetrics")]
public class ProjectMetricsProps
{
    public long ProjectId { get; set; }
    public long? TasksCompleted { get; set; }
    public long? TasksTotal { get; set; }
    public long? BugsFixed { get; set; }
    public double? Budget { get; set; }
    public long? TeamSize { get; set; }
    public Tag[]? Tags { get; set; }
    public string[]? Technologies { get; set; }
}

/// <summary>
/// Address with city, street and building details.
/// </summary>
public class Address
{
    public string City { get; set; } = string.Empty;
    public string Street { get; set; } = string.Empty;
    public BuildingInfo? Building { get; set; }
}

/// <summary>
/// Building information with floor and amenities.
/// </summary>
public class BuildingInfo
{
    public int Floor { get; set; }
    public string Name { get; set; } = string.Empty;
    public string[]? Amenities { get; set; }
    public int[]? AccessCodes { get; set; }
    public string[]? ParkingSpots { get; set; }
    public int[]? ElevatorFloors { get; set; }
}

/// <summary>
/// Contact detail key-value pair.
/// </summary>
public class ContactDetail
{
    public string Label { get; set; } = string.Empty;
    public string Value { get; set; } = string.Empty;
}

/// <summary>
/// Contact information (email, phone, etc).
/// </summary>
public class Contact
{
    public string Type { get; set; } = string.Empty;
    public string Value { get; set; } = string.Empty;
    public bool IsVerified { get; set; }
    public int[]? NotificationHours { get; set; }
    public ContactDetail[]? Metadata { get; set; }
}

/// <summary>
/// Department info with tags, metrics and nested budget data.
/// </summary>
public class Department
{
    public string Name { get; set; } = string.Empty;
    public int HeadCount { get; set; }
    public string[] Projects { get; set; } = [];
    public Tag[] Leaders { get; set; } = [];
    public Dictionary<string, int>? BudgetByYear { get; set; }
}

/// <summary>
/// Employee props - main model for examples.
/// Demonstrates all supported types:
/// - Simple types (int, string, DateTime, long, decimal)
/// - Arrays (string[], int[])
/// - Business classes (Address with nested BuildingInfo)
/// - Array of business classes (Contact[])
/// - RedbObject references (CurrentProject, PastProjects[])
/// - Dictionary types (various key and value types)
/// </summary>
[RedbScheme("Employee")]
public class EmployeeProps
{
    // Basic info
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public int Age { get; set; }
    public DateTime HireDate { get; set; }
    public string Position { get; set; } = string.Empty;
    public decimal Salary { get; set; }
    public string Department { get; set; } = string.Empty;
    public string? EmployeeCode { get; set; }

    // Skills and certifications (arrays)
    public string[]? Skills { get; set; }
    public int[]? SkillLevels { get; set; }
    public string[]? Certifications { get; set; }
    public int[]? CertificationYears { get; set; }

    // Addresses (business classes)
    public Address? HomeAddress { get; set; }
    public Address? WorkAddress { get; set; }
    public Address? EmergencyAddress { get; set; }

    // Contacts (array of business classes)
    public Contact[]? Contacts { get; set; }

    // Project references (RedbObject)
    public RedbObject<ProjectMetricsProps>? CurrentProject { get; set; }
    public RedbObject<ProjectMetricsProps>[]? PastProjects { get; set; }

    // Phone directory: extension -> phone number
    public Dictionary<string, string>? PhoneDirectory { get; set; }

    // Office locations by city
    public Dictionary<string, Address>? OfficeLocations { get; set; }

    // Bonus history by year
    public Dictionary<int, decimal>? BonusByYear { get; set; }

    // Department details with complex nested data (Pro)
    public Dictionary<string, Department>? DepartmentHistory { get; set; }

    // Composite key: (year, quarter) -> performance score (Pro)
    public Dictionary<(int Year, string Quarter), string>? PerformanceReviews { get; set; }

    // Project metrics by code (Pro)
    public Dictionary<string, RedbObject<ProjectMetricsProps>>? ProjectMetrics { get; set; }
}

/// <summary>
/// Department props for tree examples (corporate hierarchy).
/// Used with TreeRedbObject for organizational structure.
/// Similar to CategoryTestProps in ConsoleTest.
/// </summary>
[RedbScheme("Department")]
public class DepartmentProps
{
    /// <summary>Department name (e.g. "IT Department Moscow").</summary>
    public string Name { get; set; } = string.Empty;

    /// <summary>Description (e.g. "Software development team").</summary>
    public string Description { get; set; } = string.Empty;

    /// <summary>Is department active?</summary>
    public bool IsActive { get; set; } = true;

    /// <summary>Budget in USD.</summary>
    public decimal Budget { get; set; }

    /// <summary>Department code (e.g. "IT-MSK-DEV").</summary>
    public string Code { get; set; } = string.Empty;
}

/// <summary>
/// City props for list examples (linked objects).
/// Used as target object for RedbListItem.Object reference.
/// </summary>
[RedbScheme("City")]
public class CityProps
{
    /// <summary>City name.</summary>
    public string Name { get; set; } = string.Empty;
    
    /// <summary>Population count.</summary>
    public int Population { get; set; }
    
    /// <summary>Region or district.</summary>
    public string Region { get; set; } = string.Empty;
    
    /// <summary>Is capital city?</summary>
    public bool IsCapital { get; set; }
    
    /// <summary>GPS coordinates [lat, lon].</summary>
    public double[] Coordinates { get; set; } = [];
}

/// <summary>
/// Person props demonstrating ListItem fields.
/// Shows single ListItem and List of ListItems usage.
/// </summary>
[RedbScheme("Person")]
public class PersonProps
{
    /// <summary>Person name.</summary>
    public string Name { get; set; } = string.Empty;
    
    /// <summary>Age in years.</summary>
    public int Age { get; set; }
    
    /// <summary>Email address.</summary>
    public string Email { get; set; } = string.Empty;
    
    /// <summary>Single ListItem field (e.g. status from dictionary).</summary>
    public RedbListItem? Status { get; set; }
    
    /// <summary>Array of ListItems (e.g. roles from dictionary).</summary>
    public List<RedbListItem>? Roles { get; set; }
}

Bulk Insert - Complex Objects

Example: Bulk insert of complex employee records.
Classic ORM (EF Core) would require ~28 tables:
  • Employees - main table
  • EmployeeSkills - string[] Skills (FK)
  • EmployeeSkillLevels - int[] SkillLevels (FK)
  • EmployeeCertifications - string[] (FK)
  • EmployeeCertificationYears - int[] (FK)
  • Addresses - for Home/Work/Emergency (FK)
  • BuildingInfos - nested in Address (FK)
  • BuildingAmenities - string[] in BuildingInfo (FK)
  • BuildingAccessCodes - int[] in BuildingInfo (FK)
  • BuildingParkingSpots - string[] (FK)
  • BuildingElevatorFloors - int[] (FK)
  • Contacts - Contact[] (FK)
  • ContactNotificationHours - int[] in Contact (FK)
  • ContactMetadata - ContactDetail[] in Contact (FK)
  • ProjectMetrics - RedbObject reference
  • ProjectTags - Tag[] in ProjectMetrics (FK)
  • ProjectTechnologies - string[] in ProjectMetrics (FK)
  • EmployeePastProjects - many-to-many (2 FK)
  • PhoneDirectory - Dictionary (FK)
  • OfficeLocations - Dictionary + Address (2 FK)
  • BonusByYear - Dictionary (FK)
  • DepartmentHistory - Dictionary (FK)
  • Departments - nested class
  • DepartmentProjects - string[] (FK)
  • DepartmentLeaders - Tag[] (FK)
  • DepartmentBudgetByYear - nested Dictionary (FK)
  • PerformanceReviews - tuple key Dictionary (FK)
  • ProjectMetricsDict - Dictionary with RedbObject (2 FK)
INSERTs per employee: ~40-60 records across 28 tables with FK ordering.
For 100 employees: 4000-6000 INSERTs!
REDB: 2 tables (_objects + _values), ~3000 records, single BulkInsert via COPY.
var sw = Stopwatch.StartNew();
const int count = 100;

var employees = CreateEmployees(count);

// Bulk insert using COPY protocol (Pro feature)
var savedIds = await redb.SaveAsync(employees); 

sw.Stop();

// Classic ORM: ~25 tables, ~5000 INSERTs with FK ordering
// REDB: 2 tables, ~3000 values, single BulkInsert
CreateEmployees
private static List<RedbObject<EmployeeProps>> CreateEmployees(int count)
    {
        var result = new List<RedbObject<EmployeeProps>>();
        var baseDate = DateTime.Today.AddYears(-5);

        for (int i = 0; i < count; i++)
        {
            var position = Positions[i % Positions.Length];
            var department = Departments[i % Departments.Length];
            var city = Cities[i % Cities.Length];

            // Age groups: 25-34, 35-44, 45-54, 55-64
            var age = 25 + (i % 4) * 10 + (i % 10);

            // Salary based on position and seniority
            var baseSalary = position switch
            {
                "Manager" => 90000m,
                "Developer" => 80000m,
                "Analyst" => 70000m,
                "Designer" => 65000m,
                _ => 55000m
            };
            var salary = baseSalary + (i % 20) * 1000;

            // Hire dates spread over 5 years
            var hireDate = baseDate.AddDays(i * 30);

            var emp = new RedbObject<EmployeeProps>
            {
                name = $"{position} - {department} #{i + 1}",
                Props = new EmployeeProps
                {
                    FirstName = $"John{i}",
                    LastName = $"Smith{i}",
                    Age = age,
                    Position = position,
                    Department = department,
                    Salary = salary,
                    HireDate = hireDate,
                    EmployeeCode = $"EMP-{i + 1:D4}",

                    // Skills based on position
                    Skills = GetSkillsForPosition(position, i),
                    SkillLevels = [3 + i % 3, 2 + i % 4, 4 + i % 2],

                    Certifications = i % 3 == 0 ? ["AWS", "Azure"] : i % 2 == 0 ? ["PMP"] : null,
                    CertificationYears = i % 3 == 0 ? [2022, 2023] : i % 2 == 0 ? [2021] : null,

                    // Home address
                    HomeAddress = new Address
                    {
                        City = city,
                        Street = $"{100 + i} Main Street",
                        Building = new BuildingInfo
                        {
                            Floor = 1 + i % 30,
                            Name = $"Tower {(char)('A' + i % 5)}",
                            Amenities = ["Parking", "Gym", "Cafe"],
                            AccessCodes = [1000 + i, 2000 + i]
                        }
                    },

                    // Work address
                    WorkAddress = new Address
                    {
                        City = city,
                        Street = $"{1 + i % 10} Corporate Plaza",
                        Building = new BuildingInfo
                        {
                            Floor = 5 + i % 20,
                            Name = "HQ Building",
                            Amenities = ["Conference Rooms", "Cafeteria"],
                            AccessCodes = [9000 + i]
                        }
                    },

                    // Contacts
                    Contacts =
                    [
                        new Contact
                        {
                            Type = "email",
                            Value = $"john{i}@company.com",
                            IsVerified = i % 2 == 0,
                            NotificationHours = [9, 12, 17],
                            Metadata = [new ContactDetail { Label = "domain", Value = "company.com" }]
                        },
                        new Contact
                        {
                            Type = "phone",
                            Value = $"+1-555-{1000 + i:D4}",
                            IsVerified = i % 3 == 0,
                            NotificationHours = [10, 15],
                            Metadata = [new ContactDetail { Label = "carrier", Value = "Verizon" }]
                        }
                    ],

                    // Phone directory
                    PhoneDirectory = new Dictionary<string, string>
                    {
                        ["desk"] = $"x{3000 + i}",
                        ["mobile"] = $"+1-555-{2000 + i:D4}"
                    },

                    // Bonus history
                    BonusByYear = new Dictionary<int, decimal>
                    {
                        [2022] = 5000m + i * 100,
                        [2023] = 6000m + i * 150,
                        [2024] = 7000m + i * 200
                    },

                    // Office locations (Dict<string, Address>)
                    OfficeLocations = new Dictionary<string, Address>
                    {
                        ["HQ"] = new Address
                        {
                            City = i % 5 == 0 ? "New York" : city,
                            Street = "1 Corporate Drive",
                            Building = new BuildingInfo { Floor = 1, Name = "Main HQ" }
                        }
                    },

                    // Performance reviews (Dict<(int,string), string>)
                    PerformanceReviews = new Dictionary<(int Year, string Quarter), string>
                    {
                        [(2024, "Q1")] = i % 3 == 0 ? "Excellent" : i % 2 == 0 ? "Good" : "Satisfactory",
                        [(2024, "Q2")] = i % 4 == 0 ? "Excellent" : "Good"
                    }
                }
            };

            result.Add(emp);
        }

        return result;
    }
GetSkillsForPosition
private static string[] GetSkillsForPosition(string position, int index)
    {
        var skills = position switch
        {
            "Developer" => new[] { "C#", "SQL", "Azure", "Docker" },
            "Designer" => new[] { "Figma", "Photoshop", "CSS" },
            "Analyst" => new[] { "SQL", "Excel", "Python" },
            "Manager" => new[] { "Leadership", "Agile", "Communication" },
            _ => new[] { "Communication", "Teamwork" }
        };
        var take = position == "Developer" ? 2 + index % 3 : 2 + index % 2;
        return skills.Take(Math.Min(take, skills.Length)).ToArray();
    }
BulkInsertAddNewObjectsAsyncCOPY
MS 861ms(100)
MS Pro 1643ms(100)
PG 2003ms(100)
PG Pro 1723ms(100)

SaveAsync - Create Employee

Example: Create and save a new employee.
var sw = Stopwatch.StartNew();

var employee = new RedbObject<EmployeeProps>
{
    name = "New Developer",
    Props = new EmployeeProps
    {
        FirstName = "Alice",
        LastName = "Johnson",
        Age = 28,
        Position = "Developer",
        Department = "Engineering",
        Salary = 85000m,
        HireDate = DateTime.Today,
        EmployeeCode = "EMP-NEW-001",
        Skills = ["C#", "React", "SQL"]
    }
};

var id = await redb.SaveAsync(employee);
sw.Stop();
SaveAsyncCreateCRUD
MS 92ms
MS Pro 77ms
PG 118ms
PG Pro 124ms

LoadAsync - Load Employee by ID

Example: Load employee by ID.
var sw = Stopwatch.StartNew();

// Get any existing employee ID
var query = redb.Query<EmployeeProps>().Take(1);
var items = await query.ToListAsync();

if (items.Count == 0)
{
    sw.Stop();
    return Fail("E002", "LoadAsync - Load Employee by ID", ExampleTier.Free, sw.ElapsedMilliseconds,
        "No employees found. Run E000 first.");
}

var id = items[0].Id;
var loaded = await redb.LoadAsync<EmployeeProps>(id);

if (loaded != null)
{
    EmployeeProps? employee = (EmployeeProps)loaded;
}

sw.Stop();
LoadAsyncReadCRUD
MS 46ms
MS Pro 73ms
PG 82ms
PG Pro 64ms

Where - Filter by Salary

Example: Simple Where filter by salary.
var sw = Stopwatch.StartNew();

var query = redb.Query<EmployeeProps>()
    .Where(e => e.Salary > 75000m)
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereQueryFilterIRedbQueryable.WhereIRedbService.Query
MS 1636ms(100)
MS Pro 230ms(100)
PG 737ms(100)
PG Pro 194ms(100)

Where - AND Condition

Example: Where with AND - filter by age and salary.
var sw = Stopwatch.StartNew();

var query = redb.Query<EmployeeProps>()
    .Where(e => e.Age >= 30 && e.Salary > 70000m)
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereQueryAND
MS 1541ms(100)
MS Pro 164ms(100)
PG 768ms(100)
PG Pro 140ms(100)

Where - OR Condition

Filter employees using OR condition.
Find juniors (under 30) OR high earners (salary over 90k).
var sw = Stopwatch.StartNew();

var query = redb.Query<EmployeeProps>()
    .Where(e => e.Age < 30 || e.Salary > 90000m)
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereQueryOR
MS 1647ms(100)
MS Pro 146ms(100)
PG 626ms(100)
PG Pro 122ms(100)

Where - NOT Equal

Filter employees using NOT equal condition.
Find all non-managers.
var sw = Stopwatch.StartNew();

var query = redb.Query<EmployeeProps>()
    .Where(e => e.Position != "Manager")
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereQueryNOT
MS 1632ms(100)
MS Pro 151ms(100)
PG 551ms(100)
PG Pro 118ms(100)

Where - Range Condition

Filter employees by salary range.
Find mid-level earners between 60k and 90k.
var sw = Stopwatch.StartNew();

var query = redb.Query<EmployeeProps>()
    .Where(e => e.Salary >= 60000m && e.Salary < 90000m)
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereQueryRange
MS 1904ms(100)
MS Pro 144ms(100)
PG 592ms(100)
PG Pro 111ms(100)

Where - Triple AND

Filter employees using triple AND condition.
Find experienced developers with high salary.
var sw = Stopwatch.StartNew();

var query = redb.Query<EmployeeProps>()
    .Where(e => e.Position != "" && e.Age >= 30 && e.Salary > 70000m)
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereANDComplex
MS 1638ms(100)
MS Pro 125ms(100)
PG 706ms(100)
PG Pro 122ms(100)

Where - Chained Filters

Filter employees using chained Where() calls.
Each Where() adds another condition.
var sw = Stopwatch.StartNew();

// Chained Where() calls - equivalent to AND
var query = redb.Query<EmployeeProps>()
    .Where(e => e.Age >= 30)
    .Where(e => e.Salary > 60000m)
    .Where(e => e.Department != "Support")
    .Take(100);

// Uncomment to see generated SQL:
// var sql = await query.ToSqlStringAsync();
// Console.WriteLine(sql);

var result = await query.ToListAsync();
sw.Stop();
WhereChain
MS 1648ms(100)
MS Pro 111ms(100)
PG 725ms(100)
PG Pro 125ms(100)