#:package MySqlConnector@2.3.7 using System.Text; using MySqlConnector; // ── Config ──────────────────────────────────────────────────────────────────── const string DSN = "Server=127.0.0.1;Port=13306;Database=hotel_reservations;Uid=root;Pwd=ewc2025root;AllowLoadLocalInfile=true;"; const int HOTEL_COUNT = 200; const int GUEST_COUNT = 100_000; const int BOOKING_COUNT = 500_000; const int BATCH = 500; const int SEED = 42; var rng = new Random(SEED); // ── DB helpers ──────────────────────────────────────────────────────────────── await using var conn = new MySqlConnection(DSN); await conn.OpenAsync(); Console.WriteLine("Connected."); async Task Exec(string sql) { await using var cmd = new MySqlCommand(sql, conn); cmd.CommandTimeout = 300; await cmd.ExecuteNonQueryAsync(); } async Task ExecScalar(string sql) { await using var cmd = new MySqlCommand(sql, conn); return Convert.ToInt64(await cmd.ExecuteScalarAsync()); } // Bulk insert: builds a single INSERT ... VALUES (...),(...),... async Task BulkInsert(string table, string columns, List valueTuples) { for (int i = 0; i < valueTuples.Count; i += BATCH) { var batch = valueTuples.Skip(i).Take(BATCH); await Exec($"INSERT INTO {table} ({columns}) VALUES {string.Join(',', batch)}"); } } string S(string? s) => s == null ? "NULL" : $"'{s.Replace("'", "''")}'"; string N(object? n) => n == null ? "NULL" : n.ToString()!; string D(DateTime d) => $"'{d:yyyy-MM-dd}'"; string DT(DateTime d) => $"'{d:yyyy-MM-dd HH:mm:ss}'"; // ── Reference data ──────────────────────────────────────────────────────────── // ── 1. hotel_chain ──────────────────────────────────────────────────────────── Console.WriteLine("[1/8] hotel_chain"); var chains = new (string Code, string Name)[] { ("HLT", "Hilton Worldwide"), ("MRT", "Marriott International"), ("HYT", "Hyatt Hotels Corporation"), ("IHG", "InterContinental Hotels Group"), ("WYN", "Wyndham Hotels & Resorts"), ("ACC", "Accor"), ("BW", "Best Western Hotels"), ("RAD", "Radisson Hotels"), ("MEL", "Meliá Hotels International"), ("NH", "NH Hotel Group"), }; await BulkInsert("hotel_chain", "code, name", chains.Select(c => $"({S(c.Code)},{S(c.Name)})").ToList()); var chainIds = new Dictionary(); { await using var cmd = new MySqlCommand("SELECT hotel_chain_id, code FROM hotel_chain", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) chainIds[r.GetString(1)] = r.GetInt32(0); } // ── 2. country ──────────────────────────────────────────────────────────────── Console.WriteLine("[2/8] country"); var countries = new (string Code, string Name, string Currency)[] { ("GB","United Kingdom","GBP"), ("FR","France","EUR"), ("DE","Germany","EUR"), ("ES","Spain","EUR"), ("IT","Italy","EUR"), ("PT","Portugal","EUR"), ("NL","Netherlands","EUR"), ("BE","Belgium","EUR"), ("AT","Austria","EUR"), ("CH","Switzerland","CHF"), ("SE","Sweden","SEK"), ("NO","Norway","NOK"), ("DK","Denmark","DKK"), ("PL","Poland","PLN"), ("CZ","Czech Republic","CZK"), ("HU","Hungary","HUF"), ("HR","Croatia","EUR"), ("GR","Greece","EUR"), ("TR","Turkey","TRY"), ("US","United States","USD"), ("CA","Canada","CAD"), ("MX","Mexico","MXN"), ("BR","Brazil","BRL"), ("AR","Argentina","ARS"), ("AU","Australia","AUD"), ("NZ","New Zealand","NZD"), ("JP","Japan","JPY"), ("CN","China","CNY"), ("KR","South Korea","KRW"), ("SG","Singapore","SGD"), ("TH","Thailand","THB"), ("AE","United Arab Emirates","AED"), ("SA","Saudi Arabia","SAR"), ("EG","Egypt","EGP"), ("ZA","South Africa","ZAR"), ("IN","India","INR"), ("MA","Morocco","MAD"), ("TN","Tunisia","TND"), ("ID","Indonesia","IDR"), ("MY","Malaysia","MYR"), }; await BulkInsert("country", "code, name, currency", countries.Select(c => $"({S(c.Code)},{S(c.Name)},{S(c.Currency)})").ToList()); var countryIds = new Dictionary(); { await using var cmd = new MySqlCommand("SELECT country_id, code FROM country", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) countryIds[r.GetString(1)] = r.GetInt32(0); } // ── 3. star_rating ──────────────────────────────────────────────────────────── Console.WriteLine("[3/8] star_rating"); await BulkInsert("star_rating", "code, description", Enumerable.Range(1, 5).Select(i => $"({i},{S(i + " Star")})").ToList()); var starIds = new Dictionary(); { await using var cmd = new MySqlCommand("SELECT star_rating_id, code FROM star_rating", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) starIds[r.GetInt32(1)] = r.GetInt32(0); } // ── 4. hotel_characteristic ─────────────────────────────────────────────────── Console.WriteLine("[4/8] hotel_characteristic"); var characteristics = new (string Code, string Desc)[] { ("WIFI", "Free WiFi"), ("POOL", "Swimming Pool"), ("GYM", "Fitness Center"), ("SPA", "Spa & Wellness"), ("RESTAURANT", "On-site Restaurant"), ("BAR", "Hotel Bar"), ("PARKING", "Free Parking"), ("VALET", "Valet Parking"), ("CONFERENCE", "Conference Rooms"), ("SHUTTLE", "Airport Shuttle"), ("ROOM_SVC", "Room Service"), ("PETS", "Pet Friendly"), }; await BulkInsert("hotel_characteristic", "code, description", characteristics.Select(c => $"({S(c.Code)},{S(c.Desc)})").ToList()); var charIds = new Dictionary(); { await using var cmd = new MySqlCommand("SELECT characteristic_id, code FROM hotel_characteristic", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) charIds[r.GetString(1)] = r.GetInt32(0); } // ── 5. room_type + rate_period + period_room_rate ───────────────────────────── Console.WriteLine("[5/8] room_type / rate_period / period_room_rate"); var roomTypes = new (string Code, string Desc, decimal BaseRate, bool Smoking)[] { ("SINGLE", "Single Room", 80m, false), ("DOUBLE", "Double Room", 120m, false), ("TWIN", "Twin Room", 115m, false), ("DELUXE", "Deluxe Double", 180m, false), ("SUITE", "Junior Suite", 280m, false), ("EXEC", "Executive Suite", 450m, false), ("FAMILY", "Family Room", 200m, false), }; await BulkInsert("room_type", "code, description, standard_rate, smoking_yn", roomTypes.Select(rt => $"({S(rt.Code)},{S(rt.Desc)},{rt.BaseRate},0)").ToList()); var roomTypeIds = new Dictionary(); { await using var cmd = new MySqlCommand("SELECT room_type_id, code FROM room_type", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) roomTypeIds[r.GetString(1)] = r.GetInt32(0); } // Seasons: month → multiplier var ratePeriods = new (string Code, string Desc, int MonthFrom, int MonthTo, decimal Multiplier)[] { ("PEAK", "Peak Season (Jun-Aug)", 6, 8, 1.5m), ("HIGH", "High Season (Mar-May)", 3, 5, 1.2m), ("AUTUMN", "Autumn Season (Sep-Nov)", 9, 11, 1.1m), ("WINTER", "Winter Season (Dec-Feb)", 12, 2, 0.9m), }; await BulkInsert("rate_period", "code, description, month_from, month_to", ratePeriods.Select(rp => $"({S(rp.Code)},{S(rp.Desc)},{rp.MonthFrom},{rp.MonthTo})").ToList()); var ratePeriodIds = new Dictionary(); { await using var cmd = new MySqlCommand("SELECT rate_period_id, code FROM rate_period", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) ratePeriodIds[r.GetString(1)] = r.GetInt32(0); } // period_room_rate: rate = base_rate * season_multiplier var prrRows = new List(); foreach (var rt in roomTypes) foreach (var rp in ratePeriods) { var rate = Math.Round(rt.BaseRate * rp.Multiplier, 2); prrRows.Add($"({roomTypeIds[rt.Code]},{ratePeriodIds[rp.Code]},{rate})"); } await BulkInsert("period_room_rate", "room_type_id, rate_period_id, rate", prrRows); // Build month → rate lookup in memory var monthToRatePeriodId = new Dictionary(); foreach (var rp in ratePeriods) { if (rp.MonthFrom <= rp.MonthTo) for (int m = rp.MonthFrom; m <= rp.MonthTo; m++) monthToRatePeriodId[m] = ratePeriodIds[rp.Code]; else // wraps year (Dec-Feb) { for (int m = rp.MonthFrom; m <= 12; m++) monthToRatePeriodId[m] = ratePeriodIds[rp.Code]; for (int m = 1; m <= rp.MonthTo; m++) monthToRatePeriodId[m] = ratePeriodIds[rp.Code]; } } // Build (room_type_id, rate_period_id) → rate lookup var rateMap = new Dictionary<(int, int), decimal>(); foreach (var rt in roomTypes) foreach (var rp in ratePeriods) rateMap[(roomTypeIds[rt.Code], ratePeriodIds[rp.Code])] = Math.Round(rt.BaseRate * rp.Multiplier, 2); // ── 6. hotel + hotel_room + hotel_hotel_characteristic ──────────────────────── Console.WriteLine("[6/8] hotel / hotel_room / hotel_hotel_characteristic"); var hotelCities = new (string City, string Country)[] { ("London","GB"), ("Manchester","GB"), ("Edinburgh","GB"), ("Paris","FR"), ("Lyon","FR"), ("Nice","FR"), ("Berlin","DE"), ("Munich","DE"), ("Hamburg","DE"), ("Madrid","ES"), ("Barcelona","ES"), ("Seville","ES"), ("Rome","IT"), ("Milan","IT"), ("Florence","IT"), ("Lisbon","PT"), ("Porto","PT"), ("Amsterdam","NL"), ("Vienna","AT"), ("Zurich","CH"), ("Geneva","CH"), ("Stockholm","SE"), ("Oslo","NO"), ("Copenhagen","DK"), ("Warsaw","PL"), ("Prague","CZ"), ("Budapest","HU"), ("Athens","GR"), ("Istanbul","TR"), ("New York","US"), ("Los Angeles","US"), ("Miami","US"), ("Chicago","US"), ("Toronto","CA"), ("Vancouver","CA"), ("Sydney","AU"), ("Melbourne","AU"), ("Tokyo","JP"), ("Osaka","JP"), ("Singapore","SG"), ("Bangkok","TH"), ("Dubai","AE"), ("Mumbai","IN"), ("Cape Town","ZA"), ("Marrakech","MA"), ("Cairo","EG"), ("Cancun","MX"), ("Rio de Janeiro","BR"), ("Seoul","KR"), ("Kuala Lumpur","MY"), }; // Star rating distribution: 3★ most common, 5★ rarest int[] starWeights = [0, 5, 10, 40, 30, 15]; // index = star, value = weight int PickStar() { int roll = rng.Next(100); int cum = 0; for (int s = 1; s <= 5; s++) { cum += starWeights[s]; if (roll < cum) return s; } return 3; } var hotelRows = new List(); var roomRows = new List(); var hotelCharRows = new List(); var charCodes = characteristics.Select(c => c.Code).ToArray(); // Track room_type per hotel_room for later rate lookups (in-memory) // hotel_room gets an auto-increment ID; we'll load them after insert // So store: hotel index → list of (room_number, room_type_code) var hotelRoomTypes = new List<(int hotelIndex, string roomNumber, string roomTypeCode)>(); string[] streetNames = ["Main St","Park Ave","King Rd","Grand Blvd","Lake Dr", "Ocean Blvd","Hill Rd","Market St","Central Ave","Palace Rd"]; for (int h = 0; h < HOTEL_COUNT; h++) { var (city, ctryCode) = hotelCities[h % hotelCities.Length]; int chainIndex = rng.Next(chains.Length); // 20% of hotels are independent (no chain) int? chainId = rng.Next(100) < 20 ? null : chainIds[chains[chainIndex].Code]; int star = PickStar(); int starId = starIds[star]; int ctryId = countryIds[ctryCode]; string code = $"HTL{h+1:D4}"; string name = chainId == null ? $"The {city} Hotel" : $"{chains[chainIndex].Name.Split(' ')[0]} {city}"; string addr = $"{rng.Next(1, 200)} {streetNames[rng.Next(streetNames.Length)]}"; string url = $"https://www.{code.ToLower()}.example.com"; hotelRows.Add($"({N(chainId)},{ctryId},{starId},{S(code)},{S(name)},{S(addr)},{S("00000")},{S(city)},{S(url)})"); // Characteristics: 5★ gets all, lower stars get fewer int charCount = star switch { 5 => 11, 4 => 8, 3 => 6, 2 => 4, _ => 3 }; var shuffled = charCodes.OrderBy(_ => rng.Next()).Take(charCount).ToArray(); // Store char codes for later — we need hotel_id from DB first // Mark with h as placeholder; we'll match after insert foreach (var cc in shuffled) hotelCharRows.Add($"__HOTEL_{h}__,{charIds[cc]}"); // Rooms: more rooms for higher star hotels int roomCount = star switch { 5 => rng.Next(40, 60), 4 => rng.Next(25, 40), 3 => rng.Next(15, 25), 2 => rng.Next(8, 15), _ => rng.Next(5, 10) }; // Room type distribution per star rating string[] typePool = star switch { 5 => ["DOUBLE","DOUBLE","DELUXE","DELUXE","SUITE","SUITE","EXEC","FAMILY"], 4 => ["SINGLE","DOUBLE","DOUBLE","DELUXE","SUITE","FAMILY"], 3 => ["SINGLE","SINGLE","DOUBLE","DOUBLE","TWIN","FAMILY"], 2 => ["SINGLE","SINGLE","DOUBLE","TWIN"], _ => ["SINGLE","SINGLE","DOUBLE"], }; for (int r = 0; r < roomCount; r++) { int floor = r / 10 + 1; string rnum = $"{floor}{(r % 10 + 1):D2}"; string rtype = typePool[rng.Next(typePool.Length)]; // Store for later (after we get real hotel IDs from DB) hotelRoomTypes.Add((h, rnum, rtype)); } } await BulkInsert("hotel", "hotel_chain_id, country_id, star_rating_id, code, name, address, postcode, city, url", hotelRows); // Load hotel IDs in order var hotelIds = new List(); { await using var cmd = new MySqlCommand("SELECT hotel_id FROM hotel ORDER BY hotel_id", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) hotelIds.Add(r.GetInt32(0)); } // Now build hotel_room rows with real hotel IDs foreach (var (hIdx, rnum, rtype) in hotelRoomTypes) roomRows.Add($"({hotelIds[hIdx]},{roomTypeIds[rtype]},{S(rnum)},{rnum[0] - '0'})"); await BulkInsert("hotel_room", "hotel_id, room_type_id, room_number, floor", roomRows); // hotel_hotel_characteristic — replace placeholder with real hotel_id var hhcRows = hotelCharRows .Select(row => { var parts = row.Split(','); var hIdx = int.Parse(parts[0].Replace("__HOTEL_", "").Replace("__", "")); var charId = parts[1]; return $"({hotelIds[hIdx]},{charId})"; }) .Distinct() .ToList(); await BulkInsert("hotel_hotel_characteristic", "hotel_id, characteristic_id", hhcRows); // Load rooms into memory: hotel_id → list of (room_id, room_type_id) var hotelRooms = new Dictionary>(); { await using var cmd = new MySqlCommand("SELECT room_id, hotel_id, room_type_id FROM hotel_room", conn); await using var r = await cmd.ExecuteReaderAsync(); while (await r.ReadAsync()) { int rid = r.GetInt32(0), hid = r.GetInt32(1), rtid = r.GetInt32(2); if (!hotelRooms.ContainsKey(hid)) hotelRooms[hid] = []; hotelRooms[hid].Add((rid, rtid)); } } // ── 7. guest ────────────────────────────────────────────────────────────────── Console.WriteLine("[7/8] guest"); string[] firstNames = [ "James","Mary","John","Patricia","Robert","Jennifer","Michael","Linda","William","Barbara", "David","Elizabeth","Richard","Susan","Joseph","Jessica","Thomas","Sarah","Charles","Karen", "Luca","Sofia","Marco","Giulia","Hans","Anna","Klaus","Maria","Pierre","Marie","Jean","Claire", "Miguel","Ana","Carlos","Carmen","Andrei","Ioana","Mihai","Elena","Tomasz","Agnieszka", "Dimitri","Eleni","Mehmet","Fatima","Yuki","Kenji","Haruto","Yuna","Wei","Fang","Li","Mei", "Ahmed","Layla","Omar","Nour","Raj","Priya","Arjun","Ananya","Lucas","Emma","Noah","Olivia", "Ethan","Ava","Mason","Isabella","Liam","Sophia","Oliver","Charlotte","Elijah","Amelia", ]; string[] lastNames = [ "Smith","Johnson","Williams","Brown","Jones","Garcia","Miller","Davis","Wilson","Moore", "Taylor","Anderson","Thomas","Jackson","White","Harris","Martin","Thompson","Young","Lee", "Rossi","Ferrari","Esposito","Romano","Müller","Schmidt","Fischer","Weber","Meyer","Wagner", "Dupont","Martin","Bernard","Petit","Dubois","Moreau","Laurent","Simon","Michel","Garcia", "Kowalski","Nowak","Wiśniewski","Wójcik","Kowalczyk","Kamiński","Lewandowski","Zieliński", "Papadopoulos","Georgiou","Yilmaz","Kaya","Tanaka","Sato","Suzuki","Watanabe","Ito","Yamamoto", "Wang","Li","Zhang","Liu","Chen","Yang","Huang","Zhao","Kim","Park","Lee","Choi","Patel", "Singh","Kumar","Sharma","Gupta","Ali","Hassan","Ahmed","Mohamed","Silva","Santos","Oliveira", ]; string[] guestCities = [ "London","Paris","Berlin","Madrid","Rome","Amsterdam","Vienna","Zurich","Brussels","Stockholm", "New York","Los Angeles","Chicago","Houston","Phoenix","Toronto","Vancouver","Sydney","Melbourne", "Tokyo","Seoul","Beijing","Shanghai","Singapore","Bangkok","Dubai","Mumbai","Cape Town", "Warsaw","Prague","Budapest","Athens","Istanbul","Lisbon","Oslo","Copenhagen","Helsinki", ]; var countryList = countries.Select(c => c.Code).ToArray(); var guestRows = new List(); for (int g = 0; g < GUEST_COUNT; g++) { string fn = firstNames[rng.Next(firstNames.Length)]; string ln = lastNames[rng.Next(lastNames.Length)]; string name = $"{fn} {ln}"; string email = $"{fn.ToLower()}.{ln.ToLower()}{rng.Next(100, 999)}@example.com"; string city = guestCities[rng.Next(guestCities.Length)]; int ctryId = countryIds[countryList[rng.Next(countryList.Length)]]; guestRows.Add($"({ctryId},{S(name)},{S(email)},{S(city)})"); } await BulkInsert("guest", "country_id, name, email, city", guestRows); var guestIdMin = (int)await ExecScalar("SELECT MIN(guest_id) FROM guest"); var guestIdMax = (int)await ExecScalar("SELECT MAX(guest_id) FROM guest"); // ── 8. booking + room_booking ───────────────────────────────────────────────── Console.WriteLine("[8/8] booking + room_booking"); var dateStart = new DateTime(2022, 1, 1); var dateEnd = new DateTime(2025, 12, 31); int dateRange = (dateEnd - dateStart).Days; // Seasonal weight: month → weight (higher = more bookings) int[] monthWeight = [0, 6, 5, 7, 9, 10, 14, 16, 15, 11, 9, 7, 11]; // Jan-Dec DateTime RandomCheckin() { // Rejection sampling to simulate seasonal distribution while (true) { var d = dateStart.AddDays(rng.Next(dateRange)); if (rng.Next(16) < monthWeight[d.Month]) return d; } } int RandomNights() => rng.Next(100) switch { < 30 => 1, < 55 => 2, < 75 => 3, < 85 => 4, < 92 => 5, < 96 => rng.Next(6, 8), _ => rng.Next(8, 15), }; string RandomStatus() => rng.Next(100) switch { < 80 => "completed", < 90 => "confirmed", < 97 => "cancelled", _ => "no_show", }; // 90% single room, 8% two rooms, 2% three rooms int RandomRoomCount() => rng.Next(100) switch { < 90 => 1, < 98 => 2, _ => 3 }; var bookingRows = new List(); var roomBookingRows = new List(); // We need booking_id for room_booking FK. // Strategy: flush bookings in batches, then read back the auto-increment IDs, // then insert room_bookings for that batch. int bookingsDone = 0; while (bookingsDone < BOOKING_COUNT) { int batchSize = Math.Min(BATCH, BOOKING_COUNT - bookingsDone); bookingRows.Clear(); roomBookingRows.Clear(); for (int b = 0; b < batchSize; b++) { int guestId = guestIdMin + rng.Next(guestIdMax - guestIdMin + 1); int hotelId = hotelIds[rng.Next(hotelIds.Count)]; DateTime checkin = RandomCheckin(); int nights = RandomNights(); DateTime checkout = checkin.AddDays(nights); string status = RandomStatus(); DateTime created = checkin.AddDays(-rng.Next(1, 180)); bookingRows.Add($"({guestId},{hotelId},{D(checkin)},{D(checkout)},{S(status)},{DT(created)})"); } // Insert bookings and get the first inserted ID long firstId = await ExecScalar("SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_schema='hotel_reservations' AND table_name='booking'"); await Exec($"INSERT INTO booking (guest_id, hotel_id, date_from, date_to, status, created_at) VALUES {string.Join(',', bookingRows)}"); // Re-derive checkin/nights from the same rng sequence is impossible after the fact, // so re-parse from inserted rows to build room_bookings // Simpler: re-read the batch back await using (var cmd = new MySqlCommand( $"SELECT booking_id, hotel_id, date_from, date_to, status FROM booking WHERE booking_id >= {firstId} ORDER BY booking_id", conn)) await using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { long bookingId = reader.GetInt64(0); int hid = reader.GetInt32(1); DateTime dfrom = reader.GetDateTime(2); DateTime dto = reader.GetDateTime(3); string status = reader.GetString(4); int nights = (dto - dfrom).Days; if (!hotelRooms.ContainsKey(hid) || hotelRooms[hid].Count == 0) continue; // Skip room_bookings for cancelled/no_show sometimes if (status == "cancelled" && rng.Next(100) < 60) continue; if (status == "no_show" && rng.Next(100) < 30) continue; int roomCount = RandomRoomCount(); var available = hotelRooms[hid].OrderBy(_ => rng.Next()).Take(roomCount).ToList(); foreach (var (roomId, roomTypeId) in available) { int ratePeriodId = monthToRatePeriodId[dfrom.Month]; decimal nightly = rateMap[(roomTypeId, ratePeriodId)]; decimal total = Math.Round(nightly * nights, 2); roomBookingRows.Add($"({bookingId},{roomId},{D(dfrom)},{D(dto)},{nightly},{total})"); } } } if (roomBookingRows.Count > 0) await Exec($"INSERT INTO room_booking (booking_id, room_id, date_from, date_to, nightly_rate, total_amount) VALUES {string.Join(',', roomBookingRows)}"); bookingsDone += batchSize; if (bookingsDone % 10_000 == 0) Console.WriteLine($" bookings: {bookingsDone:N0} / {BOOKING_COUNT:N0}"); } Console.WriteLine(); Console.WriteLine("── Row counts ───────────────────────────────"); foreach (var t in new[]{"hotel_chain","country","star_rating","hotel_characteristic", "room_type","rate_period","period_room_rate","hotel", "hotel_room","hotel_hotel_characteristic","guest","booking","room_booking"}) { long cnt = await ExecScalar($"SELECT COUNT(*) FROM {t}"); Console.WriteLine($" {t,-35} {cnt,10:N0}"); } Console.WriteLine("Done.");