SkyFlow

18/02/2026 · Zascia Hugo · 6 min read

C#.NETSQL ServerConsole
On This Page

SkyFlow is a modern, console-based airport and airline management system. It was built as a 3rd year semester 1 project to demonstrate OOP principles, database integration, and structured software architecture using C# and .NET 8.

The system models the real operational flow of an airport: administrators manage flights and staff, while gate agents handle passenger check-in and boarding. Every action is logged, every state transition is controlled, and every piece of data persists across application restarts.

Why I Built SkyFlow

Airport operations are a natural fit for exploring object-oriented design. The domain has clear roles (admin, gate agent), well-defined entities (flights, passengers, bookings), and real state transitions (scheduled, boarding, departed). It is a problem space where clean architecture genuinely matters.

I wanted to build something that goes beyond a basic CRUD application. SkyFlow demonstrates:

  1. Role-based access control with distinct workflows per role.
  2. State machines for flight and booking status transitions.
  3. Database persistence using SQL Server with Dapper ORM.
  4. Audit logging for every mutating action in the system.

System Architecture

SkyFlow follows a layered architecture with clean project separation. Each project has a single responsibility, and dependencies flow in one direction: Console → Core ← Data.

Core - The Domain Layer

The domain layer has zero database dependencies. It defines the entities, enums, and contracts that the rest of the system depends on:

  • User is an abstract base class with UserId, Username, and Role. It defines the contract for dashboard display.
  • Admin extends User with flight management, staff creation, and audit log access.
  • GateAgent extends User with passenger check-in, flight manifest viewing, and boarding operations.
  • Flight holds flight data with encapsulated status transitions. Status changes go through controlled methods like DepartFlight() - you cannot set the status directly.
  • Passenger, Booking, Baggage, Aircraft, Airport, and FlightAssignment model the full airport domain.
  • AuditLog, FlightLog, and Notification handle system tracking and user communication.
  • FlightStatus (Scheduled, Boarding, Departed, Cancelled) and BookingStatus (Booked, CheckedIn, Boarded) are enums that enforce valid state transitions.
  • Repository interfaces (IUserRepository, IFlightRepository, IPassengerRepository, etc.) define data contracts without specifying implementation.

Data - The Persistence Layer

The data layer implements every repository interface using Dapper against SQL Server:

  • DapperContext provides a connection factory for SQL Server.
  • Each repository (UserRepository, FlightRepository, BookingRepository, etc.) maps SQL queries to domain objects using Dapper's lightweight ORM.
  • All queries use parameterised SQL to prevent injection.

Console - The Presentation Layer

The console layer handles authentication, menu flow, and user interaction:

  • AuthController manages the login screen with masked password input and BCrypt verification.
  • AdminDashboard drives the admin menu loop and dispatches actions.
  • GateAgentDashboard drives the gate agent menu loop and dispatches actions.
  • ConsoleTableEngine renders structured data as formatted ASCII tables with borders and alignment.
  • ConsoleHelper provides input prompts, colour formatting, and display utilities.

Key Features

Role-Based Authentication

Users authenticate with BCrypt-hashed credentials. The system recognises two roles:

  • Admin - Full system access: manage flights, view the master flight table, create staff accounts, and review audit logs.
  • Gate Agent - Operational access: view flight manifests, check in passengers, and manage the boarding gate.

Each role has a completely separate dashboard with distinct menu options.

Flight Management

Administrators create flight schedules, assign aircraft, and track real-time status. Flights move through a controlled lifecycle:

Scheduled  Boarding  Departed
          Cancelled

Status transitions are encapsulated within the Flight model itself. You cannot jump from Scheduled to Departed - the system enforces the correct order.

Passenger Check-In and Boarding

Gate agents search passengers by national ID or passport number, then update booking status through the check-in flow. Bookings move through a controlled lifecycle:

Booked  CheckedIn  Boarded

The boarding gate finalises flights and transitions passengers from CheckedIn to Boarded, then marks the flight as Departed. Status transitions are enforced - you cannot board a passenger who has not checked in.

Staff Management

Administrators can create new gate agent accounts directly from the admin dashboard. New accounts are created with BCrypt-hashed passwords and assigned the GateAgent role. This keeps account provisioning within the system rather than requiring direct database access.

System Oversight

The master flight table gives administrators a bird's-eye view of all flights with live occupancy percentages and capacity tracking. This is rendered using the custom ConsoleTableEngine for clean, readable ASCII output.

Audit Logging

Every mutating action is recorded with the user who performed it, a timestamp, and the affected entity. This means you can trace exactly who did what and when - a critical requirement in systems that manage operational data. Flight status changes are tracked separately in the FlightLog for granular lifecycle visibility.

Notifications

Gate agents receive notifications for events that affect their workflow - flight assignments, status changes, and system alerts. Notifications track read/unread state so agents can focus on what is new.

OOP Principles in Practice

SkyFlow was designed to demonstrate core OOP concepts in a meaningful context:

PrincipleImplementation
AbstractionIDataRepository interfaces separate database logic from business logic
InheritanceAdmin and GateAgent extend the abstract User base class
PolymorphismDisplayDashboard() dispatches role-specific menus at runtime
EncapsulationPrivate _status field with controlled transition methods like DepartFlight()

Technical Stack

  • Language: C# with .NET 8
  • Database: SQL Server (via Docker or local instance)
  • ORM: Dapper - lightweight SQL mapping for all CRUD operations
  • Security: BCrypt password hashing and verification
  • Architecture: Multi-project solution with Domain, Data, and UI layers
  • Cross-Platform: Docker Compose setup ensures compatibility across Windows and macOS (including Apple Silicon)

Database Design

The SQL scripts are versioned and ordered:

  1. 001-create-database.sql - Creates SkyFlowDB
  2. 002-create-tables.sql - Creates all relational tables
  3. 003-seed-data.sql - Inserts sample data for testing

The Docker Compose setup automatically runs all seed scripts on startup, so getting started requires just docker compose up -d followed by dotnet run.

What I Learned

Building SkyFlow reinforced several engineering disciplines:

  • Interface-driven design makes testing and refactoring significantly easier. Swapping from SQL Server to any other database would only require new repository implementations.
  • State machines are underrated. Encoding valid transitions in the domain model prevents an entire category of bugs.
  • Audit trails should be first-class concerns, not afterthoughts. Building them into the architecture from day one is far simpler than retrofitting.
  • Console applications can be elegant. The ConsoleTableEngine proved that a well-designed text UI can be just as readable as a graphical one for operational tools.

Where Can I Learn More?

  • Repository: GitHub Repo
  • Documentation: Full developer docs available in the docs/ folder