diff --git a/.idea/.idea.biergarten/.idea/.gitignore b/.idea/.idea.biergarten/.idea/.gitignore
deleted file mode 100644
index 611d03c..0000000
--- a/.idea/.idea.biergarten/.idea/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Rider ignored files
-/.idea.biergarten.iml
-/contentModel.xml
-/modules.xml
-/projectSettingsUpdater.xml
-# Ignored default folder with query files
-/queries/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/.idea/.idea.biergarten/.idea/.name b/.idea/.idea.biergarten/.idea/.name
deleted file mode 100644
index a1865e9..0000000
--- a/.idea/.idea.biergarten/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-biergarten
\ No newline at end of file
diff --git a/.idea/.idea.biergarten/.idea/dataSources.xml b/.idea/.idea.biergarten/.idea/dataSources.xml
deleted file mode 100644
index 7b8055e..0000000
--- a/.idea/.idea.biergarten/.idea/dataSources.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- sqlserver.jb
- true
- com.jetbrains.jdbc.sqlserver.SqlServerDriver
- Server=localhost;Database=Biergarten;TrustServerCertificate=True;
-
-
-
-
-
- $ProjectFileDir$
-
-
-
diff --git a/.idea/.idea.biergarten/.idea/data_source_mapping.xml b/.idea/.idea.biergarten/.idea/data_source_mapping.xml
deleted file mode 100644
index 3edede8..0000000
--- a/.idea/.idea.biergarten/.idea/data_source_mapping.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/.idea/.idea.biergarten/.idea/indexLayout.xml b/.idea/.idea.biergarten/.idea/indexLayout.xml
deleted file mode 100644
index 67b8dc9..0000000
--- a/.idea/.idea.biergarten/.idea/indexLayout.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/.idea/.idea.biergarten/.idea/sqldialects.xml b/.idea/.idea.biergarten/.idea/sqldialects.xml
deleted file mode 100644
index fb7c0dd..0000000
--- a/.idea/.idea.biergarten/.idea/sqldialects.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.biergarten/.idea/vcs.xml b/.idea/.idea.biergarten/.idea/vcs.xml
deleted file mode 100644
index dcb6b8c..0000000
--- a/.idea/.idea.biergarten/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/DBSeed/ISeeder.cs b/DBSeed/ISeeder.cs
new file mode 100644
index 0000000..4624827
--- /dev/null
+++ b/DBSeed/ISeeder.cs
@@ -0,0 +1,6 @@
+using Microsoft.Data.SqlClient;
+
+interface ISeeder
+{
+ Task SeedAsync(SqlConnection connection);
+}
\ No newline at end of file
diff --git a/DBSeed/LocationSeeder.cs b/DBSeed/LocationSeeder.cs
index 8c825ac..983921b 100644
--- a/DBSeed/LocationSeeder.cs
+++ b/DBSeed/LocationSeeder.cs
@@ -3,7 +3,7 @@ using Microsoft.Data.SqlClient;
namespace DBSeed;
-internal static class LocationSeeder
+class LocationSeeder : ISeeder
{
private static readonly IReadOnlyList<(
string CountryName,
@@ -244,7 +244,7 @@ internal static class LocationSeeder
("MX-ZAC", "Zacatecas"),
];
- internal static async Task SeedAsync(SqlConnection connection)
+ public async Task SeedAsync(SqlConnection connection)
{
foreach (var (countryName, countryCode) in Countries)
{
diff --git a/DBSeed/Program.cs b/DBSeed/Program.cs
index 59e3931..39640cd 100644
--- a/DBSeed/Program.cs
+++ b/DBSeed/Program.cs
@@ -16,11 +16,18 @@ try
Console.WriteLine("Connected to database.");
- await LocationSeeder.SeedAsync(connection);
- Console.WriteLine("Seeded locations.");
+ ISeeder[] seeders =
+ [
+ new LocationSeeder(),
+ new UserSeeder(),
+ ];
- await UserSeeder.SeedAsync(connection);
- Console.WriteLine("Seeded users.");
+ foreach (var seeder in seeders)
+ {
+ Console.WriteLine($"Seeding {seeder.GetType().Name}...");
+ await seeder.SeedAsync(connection);
+ Console.WriteLine($"{seeder.GetType().Name} seeded.");
+ }
Console.WriteLine("Seed completed successfully.");
return 0;
diff --git a/DBSeed/UserSeeder.cs b/DBSeed/UserSeeder.cs
index 26ca3fd..2918bff 100644
--- a/DBSeed/UserSeeder.cs
+++ b/DBSeed/UserSeeder.cs
@@ -7,114 +7,116 @@ using Microsoft.Data.SqlClient;
namespace DBSeed;
-internal static class UserSeeder
+class UserSeeder : ISeeder
{
- private static readonly IReadOnlyList<(string FirstName, string LastName)>
- SeedNames =
- [
- ("Aarya", "Mathews"),
- ("Aiden", "Wells"),
- ("Aleena", "Gonzalez"),
- ("Alessandra", "Nelson"),
- ("Amari", "Tucker"),
- ("Ameer", "Huff"),
- ("Amirah", "Hicks"),
- ("Analia", "Dominguez"),
- ("Anne", "Jenkins"),
- ("Apollo", "Davis"),
- ("Arianna", "White"),
- ("Aubree", "Moore"),
- ("Aubrielle", "Raymond"),
- ("Aydin", "Odom"),
- ("Bowen", "Casey"),
- ("Brock", "Huber"),
- ("Caiden", "Strong"),
- ("Cecilia", "Rosales"),
- ("Celeste", "Barber"),
- ("Chance", "Small"),
- ("Clara", "Roberts"),
- ("Collins", "Brandt"),
- ("Damir", "Wallace"),
- ("Declan", "Crawford"),
- ("Dennis", "Decker"),
- ("Dylan", "Lang"),
- ("Eliza", "Kane"),
- ("Elle", "Poole"),
- ("Elliott", "Miles"),
- ("Emelia", "Lucas"),
- ("Emilia", "Simpson"),
- ("Emmett", "Lugo"),
- ("Ethan", "Stephens"),
- ("Etta", "Woods"),
- ("Gael", "Moran"),
- ("Grant", "Benson"),
- ("Gwen", "James"),
- ("Huxley", "Chen"),
- ("Isabella", "Fisher"),
- ("Ivan", "Mathis"),
- ("Jamir", "McMillan"),
- ("Jaxson", "Shields"),
- ("Jimmy", "Richmond"),
- ("Josiah", "Flores"),
- ("Kaden", "Enriquez"),
- ("Kai", "Lawson"),
- ("Karsyn", "Adkins"),
- ("Karsyn", "Proctor"),
- ("Kayden", "Henson"),
- ("Kaylie", "Spears"),
- ("Kinslee", "Jones"),
- ("Kora", "Guerra"),
- ("Lane", "Skinner"),
- ("Laylani", "Christian"),
- ("Ledger", "Carroll"),
- ("Leilany", "Small"),
- ("Leland", "McCall"),
- ("Leonard", "Calhoun"),
- ("Levi", "Ochoa"),
- ("Lillie", "Vang"),
- ("Lola", "Sheppard"),
- ("Luciana", "Poole"),
- ("Maddox", "Hughes"),
- ("Mara", "Blackwell"),
- ("Marcellus", "Bartlett"),
- ("Margo", "Koch"),
- ("Maurice", "Gibson"),
- ("Maxton", "Dodson"),
- ("Mia", "Parrish"),
- ("Millie", "Fuentes"),
- ("Nellie", "Villanueva"),
- ("Nicolas", "Mata"),
- ("Nicolas", "Miller"),
- ("Oakleigh", "Foster"),
- ("Octavia", "Pierce"),
- ("Paisley", "Allison"),
- ("Quincy", "Andersen"),
- ("Quincy", "Frazier"),
- ("Raiden", "Roberts"),
- ("Raquel", "Lara"),
- ("Rudy", "McIntosh"),
- ("Salvador", "Stein"),
- ("Samantha", "Dickson"),
- ("Solomon", "Richards"),
- ("Sylvia", "Hanna"),
- ("Talia", "Trujillo"),
- ("Thalia", "Farrell"),
- ("Trent", "Mayo"),
- ("Trinity", "Cummings"),
- ("Ty", "Perry"),
- ("Tyler", "Romero"),
- ("Valeria", "Pierce"),
- ("Vance", "Neal"),
- ("Whitney", "Bell"),
- ("Wilder", "Graves"),
- ("William", "Logan"),
- ("Zara", "Wilkinson"),
- ("Zaria", "Gibson"),
- ("Zion", "Watkins"),
- ("Zoie", "Armstrong"),
- ];
+ private static readonly IReadOnlyList<(
+ string FirstName,
+ string LastName
+ )> SeedNames =
+ [
+ ("Aarya", "Mathews"),
+ ("Aiden", "Wells"),
+ ("Aleena", "Gonzalez"),
+ ("Alessandra", "Nelson"),
+ ("Amari", "Tucker"),
+ ("Ameer", "Huff"),
+ ("Amirah", "Hicks"),
+ ("Analia", "Dominguez"),
+ ("Anne", "Jenkins"),
+ ("Apollo", "Davis"),
+ ("Arianna", "White"),
+ ("Aubree", "Moore"),
+ ("Aubrielle", "Raymond"),
+ ("Aydin", "Odom"),
+ ("Bowen", "Casey"),
+ ("Brock", "Huber"),
+ ("Caiden", "Strong"),
+ ("Cecilia", "Rosales"),
+ ("Celeste", "Barber"),
+ ("Chance", "Small"),
+ ("Clara", "Roberts"),
+ ("Collins", "Brandt"),
+ ("Damir", "Wallace"),
+ ("Declan", "Crawford"),
+ ("Dennis", "Decker"),
+ ("Dylan", "Lang"),
+ ("Eliza", "Kane"),
+ ("Elle", "Poole"),
+ ("Elliott", "Miles"),
+ ("Emelia", "Lucas"),
+ ("Emilia", "Simpson"),
+ ("Emmett", "Lugo"),
+ ("Ethan", "Stephens"),
+ ("Etta", "Woods"),
+ ("Gael", "Moran"),
+ ("Grant", "Benson"),
+ ("Gwen", "James"),
+ ("Huxley", "Chen"),
+ ("Isabella", "Fisher"),
+ ("Ivan", "Mathis"),
+ ("Jamir", "McMillan"),
+ ("Jaxson", "Shields"),
+ ("Jimmy", "Richmond"),
+ ("Josiah", "Flores"),
+ ("Kaden", "Enriquez"),
+ ("Kai", "Lawson"),
+ ("Karsyn", "Adkins"),
+ ("Karsyn", "Proctor"),
+ ("Kayden", "Henson"),
+ ("Kaylie", "Spears"),
+ ("Kinslee", "Jones"),
+ ("Kora", "Guerra"),
+ ("Lane", "Skinner"),
+ ("Laylani", "Christian"),
+ ("Ledger", "Carroll"),
+ ("Leilany", "Small"),
+ ("Leland", "McCall"),
+ ("Leonard", "Calhoun"),
+ ("Levi", "Ochoa"),
+ ("Lillie", "Vang"),
+ ("Lola", "Sheppard"),
+ ("Luciana", "Poole"),
+ ("Maddox", "Hughes"),
+ ("Mara", "Blackwell"),
+ ("Marcellus", "Bartlett"),
+ ("Margo", "Koch"),
+ ("Maurice", "Gibson"),
+ ("Maxton", "Dodson"),
+ ("Mia", "Parrish"),
+ ("Millie", "Fuentes"),
+ ("Nellie", "Villanueva"),
+ ("Nicolas", "Mata"),
+ ("Nicolas", "Miller"),
+ ("Oakleigh", "Foster"),
+ ("Octavia", "Pierce"),
+ ("Paisley", "Allison"),
+ ("Quincy", "Andersen"),
+ ("Quincy", "Frazier"),
+ ("Raiden", "Roberts"),
+ ("Raquel", "Lara"),
+ ("Rudy", "McIntosh"),
+ ("Salvador", "Stein"),
+ ("Samantha", "Dickson"),
+ ("Solomon", "Richards"),
+ ("Sylvia", "Hanna"),
+ ("Talia", "Trujillo"),
+ ("Thalia", "Farrell"),
+ ("Trent", "Mayo"),
+ ("Trinity", "Cummings"),
+ ("Ty", "Perry"),
+ ("Tyler", "Romero"),
+ ("Valeria", "Pierce"),
+ ("Vance", "Neal"),
+ ("Whitney", "Bell"),
+ ("Wilder", "Graves"),
+ ("William", "Logan"),
+ ("Zara", "Wilkinson"),
+ ("Zaria", "Gibson"),
+ ("Zion", "Watkins"),
+ ("Zoie", "Armstrong"),
+ ];
- public static async Task SeedAsync(SqlConnection connection)
+ public async Task SeedAsync(SqlConnection connection)
{
var generator = new PasswordGenerator();
var random = new Random();
diff --git a/README.md b/README.md
index 5fda357..f29948f 100644
--- a/README.md
+++ b/README.md
@@ -5,10 +5,10 @@ This solution is a monolith-oriented Web API with a layered structure. The curre
## High-level projects
- `WebAPI/` - ASP.NET Core API endpoints (controllers) and application entrypoint.
-- `BusinessLayer/` - Intended home for domain/business logic (currently minimal).
+- `BusinessLayer/` - Intended home for domain/business logic
- `DataAccessLayer/` - Repository implementations, entities (POCOs), and SQL helpers.
-- `DataLayer/` - Database schema, seed scripts, and data sources.
-- `WebCrawler/` - Separate crawler executable.
+- `DataLayer/` - DbUp console app that applies embedded schema/functions/procedures.
+- `DBSeed/` - Console app for seeding locations and test user data.
- `DALTests/` - Data access tests.
## Data access architecture
@@ -16,12 +16,12 @@ This solution is a monolith-oriented Web API with a layered structure. The curre
- **Entities (POCOs)** live in `DataAccessLayer/Entities/`.
- **Repositories** live in `DataAccessLayer/Repositories/` and implement interfaces like `IUserAccountRepository`.
- **SQL execution** lives in `DataAccessLayer/Sql/`.
-- **Stored procedures** for CRUD live under `DataAccessLayer/Sql/crud/` and are invoked by repositories.
+- **Stored procedures** for CRUD live under `DataLayer/scripts/03-crud/` and are invoked by repositories.
Example flow:
```
-WebAPI Controller -> IUserAccountRepository -> UserAccountRepository -> stored procedure
+WebAPI Controller -> UserService -> UserAccountRepository -> stored procedure
```
The repositories are currently responsible for:
@@ -29,12 +29,13 @@ The repositories are currently responsible for:
- Executing stored procedures
- Mapping result sets to POCOs
-## Database schema and seed
+## Database schema and seed tooling
-- `DataLayer/schema.sql` contains the database schema definitions.
-- `DataLayer/database/` holds application functions and CRUD procedures.
-- `DataLayer/seed/` holds seed-only procedures and the `SeedDB.cs` entry point.
-- `SeedDB.cs` honors `SEED_MODE` (`database`, `seed`, or `all`) to control which scripts run.
+- `DataLayer/scripts/01-schema/schema.sql` contains the database schema definitions.
+- `DataLayer/scripts/02-functions/` holds application functions.
+- `DataLayer/scripts/03-crud/` holds CRUD stored procedures.
+- `DataLayer/Program.cs` runs DbUp to apply embedded scripts to the database.
+- `DBSeed/Program.cs` runs the location and user seeders using `DB_CONNECTION_STRING`.
## Key conventions