From 0d4f4ca54ec5e90e026a6d4e07d4ebfc23ec7c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 15:39:31 +0200 Subject: [PATCH 01/14] started database caching and dependency injection --- webapi/Program.cs | 3 +++ webapi/Services/RecipeService.cs | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 webapi/Services/RecipeService.cs diff --git a/webapi/Program.cs b/webapi/Program.cs index 7229f94..b1bb1e5 100644 --- a/webapi/Program.cs +++ b/webapi/Program.cs @@ -1,10 +1,13 @@ using Microsoft.EntityFrameworkCore; using webapi.Data; +using webapi.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. +builder.Services.Add(new ServiceDescriptor(typeof(RecipeService), ServiceLifetime.Singleton)); // I hope this is how you register the class to be dependency injected at startup + builder.Services.AddControllers(); builder.Services.AddDbContext(opt => { diff --git a/webapi/Services/RecipeService.cs b/webapi/Services/RecipeService.cs new file mode 100644 index 0000000..9ff8bba --- /dev/null +++ b/webapi/Services/RecipeService.cs @@ -0,0 +1,29 @@ +using webapi.Entities; + +namespace webapi.Services +{ + public class RecipeService + { + private readonly List recipes = new(); // store the db cache here + + public RecipeService() + { + // todo init, read db to memory + } + + public void SaveRecipe(Recipe recipe) + { + // todo save always goes to db and updates internal cache, avoid desync states + } + + public Recipe? GetRecipeById(int id) + { + return null; // todo + } + + public IReadOnlyCollection GetAllRecipes() + { + return new List(); // todo, but the pattern will be return empty list if not found for instance in filtered gets like getbyingredient + } + } +} From 48048e9a09afc07eb5aadb6705e2616435a5cb0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 16:22:32 +0200 Subject: [PATCH 02/14] add recipe getting to endpoint --- webapi/Controllers/RecipeController.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/webapi/Controllers/RecipeController.cs b/webapi/Controllers/RecipeController.cs index 413d619..36babe8 100644 --- a/webapi/Controllers/RecipeController.cs +++ b/webapi/Controllers/RecipeController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc; using webapi.Dtos; using webapi.Entities; +using webapi.Services; using webapi.Stuff; namespace webapi.Controllers @@ -11,7 +12,8 @@ public class RecipeController : Controller [Route("")] public IReadOnlyCollection? GetAllRecipes() { - return null; + var recipeService = new RecipeService(); + return recipeService.GetAllRecipes(); } [HttpGet] From 71ca5ca473be7816b7cb5ac6cefe6f3667b55737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 16:22:54 +0200 Subject: [PATCH 03/14] ignore extra db files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 492ee63..3c312df 100644 --- a/.gitignore +++ b/.gitignore @@ -397,3 +397,5 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml *.db +*.db-shm +*.db-wal From e31b8de5d6ca7089f7c0d72efb43747a03bc8904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 16:23:06 +0200 Subject: [PATCH 04/14] comment singleton registration --- webapi/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapi/Program.cs b/webapi/Program.cs index b1bb1e5..4f5ab80 100644 --- a/webapi/Program.cs +++ b/webapi/Program.cs @@ -6,7 +6,7 @@ // Add services to the container. -builder.Services.Add(new ServiceDescriptor(typeof(RecipeService), ServiceLifetime.Singleton)); // I hope this is how you register the class to be dependency injected at startup +//builder.Services.Add(new ServiceDescriptor(typeof(RecipeService), ServiceLifetime.Singleton)); // I hope this is how you register the class to be dependency injected at startup builder.Services.AddControllers(); builder.Services.AddDbContext(opt => From bb97ff469d05dda3f3b07fe43a810f6058215065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 16:23:17 +0200 Subject: [PATCH 05/14] attempt to fill recipe cache --- webapi/Services/RecipeService.cs | 41 +++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/webapi/Services/RecipeService.cs b/webapi/Services/RecipeService.cs index 9ff8bba..f6348e6 100644 --- a/webapi/Services/RecipeService.cs +++ b/webapi/Services/RecipeService.cs @@ -1,14 +1,32 @@ -using webapi.Entities; +using Microsoft.AspNetCore.HttpLogging; +using Microsoft.Data.Sqlite; +using webapi.Dtos; +using webapi.Entities; namespace webapi.Services { public class RecipeService { - private readonly List recipes = new(); // store the db cache here + private readonly List? recipes = new(); // store the db cache here - public RecipeService() + public RecipeService(string connectionString = "Data source = isCooking.db") // todo inherit project db path { - // todo init, read db to memory + using SqliteConnection connection = new(connectionString); + connection.Open(); + + const string sql = "SELECT * FROM Recipe"; + + var cmd = new SqliteCommand(sql, connection); + + var reader = cmd.ExecuteReader(); + + foreach (var item in reader) + { + Console.WriteLine(item.ToString()); + } + + //this.recipes = (List)cmd.ExecuteScalar(); // todo fill cache, how tf tho + connection.Close(); } public void SaveRecipe(Recipe recipe) @@ -21,9 +39,20 @@ public void SaveRecipe(Recipe recipe) return null; // todo } - public IReadOnlyCollection GetAllRecipes() + public IReadOnlyCollection? GetAllRecipes() { - return new List(); // todo, but the pattern will be return empty list if not found for instance in filtered gets like getbyingredient + if (this.recipes != null) + { + IReadOnlyCollection? result = this.recipes.Select(x => + { + return new RecipeDto(x.Id, x.Name, x.Description, x.Difficulty, x.MinutesToMake, x.Ingredients, x.Steps, x.ImageRoute); + }).ToList(); // todo maybe dont pass internal types in dto, make dto versions of step and ingredient too? + + return result; + } + + //the pattern will be return empty list if not found for instance in filtered gets like getbyingredient + return new List(); } } } From b0cf8317a294b414dc42d95b38180a5a8c2fe9b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 16:35:07 +0200 Subject: [PATCH 06/14] rm using --- webapi/Services/RecipeService.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webapi/Services/RecipeService.cs b/webapi/Services/RecipeService.cs index f6348e6..df49d33 100644 --- a/webapi/Services/RecipeService.cs +++ b/webapi/Services/RecipeService.cs @@ -1,5 +1,4 @@ -using Microsoft.AspNetCore.HttpLogging; -using Microsoft.Data.Sqlite; +using Microsoft.Data.Sqlite; using webapi.Dtos; using webapi.Entities; From 86ab99d8ec64d695a8e25a93957143e6f109f37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 23:33:57 +0200 Subject: [PATCH 07/14] added service registrations --- webapi/Program.cs | 5 +++-- webapi/ServiceRegistrations.cs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 webapi/ServiceRegistrations.cs diff --git a/webapi/Program.cs b/webapi/Program.cs index 4f5ab80..bac6cd2 100644 --- a/webapi/Program.cs +++ b/webapi/Program.cs @@ -5,14 +5,15 @@ var builder = WebApplication.CreateBuilder(args); // Add services to the container. +builder.Services.AddSingleton(typeof(RecipeProvider)); -//builder.Services.Add(new ServiceDescriptor(typeof(RecipeService), ServiceLifetime.Singleton)); // I hope this is how you register the class to be dependency injected at startup builder.Services.AddControllers(); builder.Services.AddDbContext(opt => { opt.UseSqlite(builder.Configuration.GetConnectionString("Default")); }); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -32,4 +33,4 @@ app.MapControllers(); -app.Run(); +app.Run(); \ No newline at end of file diff --git a/webapi/ServiceRegistrations.cs b/webapi/ServiceRegistrations.cs new file mode 100644 index 0000000..b093eb5 --- /dev/null +++ b/webapi/ServiceRegistrations.cs @@ -0,0 +1,14 @@ +using webapi.Services; + +namespace webapi +{ + public class ServiceRegistrations + { + public static void RegisterServices(WebApplicationBuilder builder) + { + builder.Services.AddSingleton(typeof(RecipeProvider)); + //builder.Services.AddSingleton(typeof(IngredientProvider)); + //builder.Services.AddSingleton(typeof(StepProvider)); + } + } +} From 562ef0eb663b0445c4e986214587f9992c2f3290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 23:34:24 +0200 Subject: [PATCH 08/14] rename revert --- webapi/Program.cs | 2 +- webapi/ServiceRegistrations.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webapi/Program.cs b/webapi/Program.cs index bac6cd2..ff1a895 100644 --- a/webapi/Program.cs +++ b/webapi/Program.cs @@ -5,7 +5,7 @@ var builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddSingleton(typeof(RecipeProvider)); +builder.Services.AddSingleton(typeof(RecipeService)); builder.Services.AddControllers(); diff --git a/webapi/ServiceRegistrations.cs b/webapi/ServiceRegistrations.cs index b093eb5..75924e8 100644 --- a/webapi/ServiceRegistrations.cs +++ b/webapi/ServiceRegistrations.cs @@ -6,7 +6,7 @@ public class ServiceRegistrations { public static void RegisterServices(WebApplicationBuilder builder) { - builder.Services.AddSingleton(typeof(RecipeProvider)); + builder.Services.AddSingleton(typeof(RecipeService)); //builder.Services.AddSingleton(typeof(IngredientProvider)); //builder.Services.AddSingleton(typeof(StepProvider)); } From cd2bb4e5e6a15af2af5230dd58a6b5b831ffa172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 23:34:34 +0200 Subject: [PATCH 09/14] add injection to controller --- webapi/Controllers/RecipeController.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/webapi/Controllers/RecipeController.cs b/webapi/Controllers/RecipeController.cs index 36babe8..a14f44c 100644 --- a/webapi/Controllers/RecipeController.cs +++ b/webapi/Controllers/RecipeController.cs @@ -8,12 +8,18 @@ namespace webapi.Controllers { public class RecipeController : Controller { + private readonly RecipeService _recipeService; + + public RecipeController(RecipeService recipeService) + { + _recipeService = recipeService ?? throw new ArgumentNullException(nameof(recipeService)); + } + [HttpGet] [Route("")] public IReadOnlyCollection? GetAllRecipes() { - var recipeService = new RecipeService(); - return recipeService.GetAllRecipes(); + return _recipeService.GetAllRecipes(); } [HttpGet] From 4448c8c9bc9fc75eff3195f04cbeb3f6ec4cd1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 23:47:13 +0200 Subject: [PATCH 10/14] rename stuff folder --- webapi/{Stuff => Structure}/Difficulty.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename webapi/{Stuff => Structure}/Difficulty.cs (100%) diff --git a/webapi/Stuff/Difficulty.cs b/webapi/Structure/Difficulty.cs similarity index 100% rename from webapi/Stuff/Difficulty.cs rename to webapi/Structure/Difficulty.cs From bd0a3d16df21c005ae9958791d99f9d15872cf78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 23:47:25 +0200 Subject: [PATCH 11/14] update usings --- webapi/Controllers/RecipeController.cs | 2 +- webapi/Dtos/RecipeDto.cs | 2 +- webapi/Entities/Recipe.cs | 2 +- webapi/Structure/Difficulty.cs | 2 +- webapi/webapi.csproj | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/webapi/Controllers/RecipeController.cs b/webapi/Controllers/RecipeController.cs index a14f44c..6d882fe 100644 --- a/webapi/Controllers/RecipeController.cs +++ b/webapi/Controllers/RecipeController.cs @@ -2,7 +2,7 @@ using webapi.Dtos; using webapi.Entities; using webapi.Services; -using webapi.Stuff; +using webapi.Structure; namespace webapi.Controllers { diff --git a/webapi/Dtos/RecipeDto.cs b/webapi/Dtos/RecipeDto.cs index a83f763..8a9630f 100644 --- a/webapi/Dtos/RecipeDto.cs +++ b/webapi/Dtos/RecipeDto.cs @@ -1,5 +1,5 @@ using webapi.Entities; -using webapi.Stuff; +using webapi.Structure; namespace webapi.Dtos { diff --git a/webapi/Entities/Recipe.cs b/webapi/Entities/Recipe.cs index f9feeb1..286439b 100644 --- a/webapi/Entities/Recipe.cs +++ b/webapi/Entities/Recipe.cs @@ -1,4 +1,4 @@ -using webapi.Stuff; +using webapi.Structure; namespace webapi.Entities { diff --git a/webapi/Structure/Difficulty.cs b/webapi/Structure/Difficulty.cs index d528b48..d27a55b 100644 --- a/webapi/Structure/Difficulty.cs +++ b/webapi/Structure/Difficulty.cs @@ -1,4 +1,4 @@ -namespace webapi.Stuff +namespace webapi.Structure { public enum Difficulty { diff --git a/webapi/webapi.csproj b/webapi/webapi.csproj index d697175..74d6ad3 100644 --- a/webapi/webapi.csproj +++ b/webapi/webapi.csproj @@ -21,6 +21,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + From c75c3105d50afb04e52982ebac15ca11f15cb264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Lov=C3=A1sz?= Date: Tue, 24 Oct 2023 23:48:48 +0200 Subject: [PATCH 12/14] minor cleanup --- webapi/Program.cs | 9 +++++---- webapi/ServiceRegistrations.cs | 6 +++++- webapi/Services/RecipeService.cs | 12 +++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/webapi/Program.cs b/webapi/Program.cs index ff1a895..3f67daa 100644 --- a/webapi/Program.cs +++ b/webapi/Program.cs @@ -1,11 +1,12 @@ using Microsoft.EntityFrameworkCore; +using webapi; using webapi.Data; -using webapi.Services; -var builder = WebApplication.CreateBuilder(args); +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddSingleton(typeof(RecipeService)); +ServiceRegistrations registrations = new(); +registrations.RegisterServices(builder); builder.Services.AddControllers(); @@ -18,7 +19,7 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -var app = builder.Build(); +WebApplication app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) diff --git a/webapi/ServiceRegistrations.cs b/webapi/ServiceRegistrations.cs index 75924e8..3e37a60 100644 --- a/webapi/ServiceRegistrations.cs +++ b/webapi/ServiceRegistrations.cs @@ -4,7 +4,11 @@ namespace webapi { public class ServiceRegistrations { - public static void RegisterServices(WebApplicationBuilder builder) + public ServiceRegistrations() + { + } + + public void RegisterServices(WebApplicationBuilder builder) { builder.Services.AddSingleton(typeof(RecipeService)); //builder.Services.AddSingleton(typeof(IngredientProvider)); diff --git a/webapi/Services/RecipeService.cs b/webapi/Services/RecipeService.cs index df49d33..3b78509 100644 --- a/webapi/Services/RecipeService.cs +++ b/webapi/Services/RecipeService.cs @@ -8,18 +8,20 @@ public class RecipeService { private readonly List? recipes = new(); // store the db cache here - public RecipeService(string connectionString = "Data source = isCooking.db") // todo inherit project db path + public RecipeService() // todo inherit project db path { + string connectionString = "Data source = isCooking.db"; // todo how to get this dynamically? + using SqliteConnection connection = new(connectionString); connection.Open(); const string sql = "SELECT * FROM Recipe"; - var cmd = new SqliteCommand(sql, connection); + SqliteCommand cmd = new(sql, connection); - var reader = cmd.ExecuteReader(); + SqliteDataReader reader = cmd.ExecuteReader(); - foreach (var item in reader) + foreach (object? item in reader) { Console.WriteLine(item.ToString()); } @@ -41,7 +43,7 @@ public void SaveRecipe(Recipe recipe) public IReadOnlyCollection? GetAllRecipes() { if (this.recipes != null) - { + { IReadOnlyCollection? result = this.recipes.Select(x => { return new RecipeDto(x.Id, x.Name, x.Description, x.Difficulty, x.MinutesToMake, x.Ingredients, x.Steps, x.ImageRoute); From 30755a269aaf785c9c7ef7abe9c043f09b65e302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lov=C3=A1sz=20=C3=81kos?= Date: Sat, 28 Oct 2023 14:44:41 +0200 Subject: [PATCH 13/14] separate entities from dtos --- webapi/Controllers/RecipeController.cs | 2 +- webapi/Dtos/IngredientDto.cs | 20 ++++++++++++++++++++ webapi/Dtos/StepDto.cs | 20 ++++++++++++++++++++ webapi/Services/RecipeService.cs | 2 +- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 webapi/Dtos/IngredientDto.cs create mode 100644 webapi/Dtos/StepDto.cs diff --git a/webapi/Controllers/RecipeController.cs b/webapi/Controllers/RecipeController.cs index 6d882fe..28fc8d9 100644 --- a/webapi/Controllers/RecipeController.cs +++ b/webapi/Controllers/RecipeController.cs @@ -38,7 +38,7 @@ public RecipeController(RecipeService recipeService) [HttpGet] [Route("ingredients")] - public IReadOnlyCollection? GetRecipesByIngredients([FromBody] IReadOnlyCollection availableIngredients) + public IReadOnlyCollection? GetRecipesByIngredients([FromBody] IReadOnlyCollection availableIngredients) { return null; } diff --git a/webapi/Dtos/IngredientDto.cs b/webapi/Dtos/IngredientDto.cs new file mode 100644 index 0000000..7fa7aba --- /dev/null +++ b/webapi/Dtos/IngredientDto.cs @@ -0,0 +1,20 @@ +namespace webapi; + +public class IngredientDto +{ + public IngredientDto(int id, string name, int count, string unit) + { + this.Id = id; + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.Count = count; + this.Unit = unit ?? throw new ArgumentNullException(nameof(unit)); + } + + public int Id { get; } + + public string Name { get; } + + public int Count { get; } + + public string Unit { get; } +} diff --git a/webapi/Dtos/StepDto.cs b/webapi/Dtos/StepDto.cs new file mode 100644 index 0000000..8a08df1 --- /dev/null +++ b/webapi/Dtos/StepDto.cs @@ -0,0 +1,20 @@ +namespace webapi; + +public class StepDto +{ + public StepDto(int id, int recipeId, int number, string descripton) + { + this.Id = id; + this.RecipeId = recipeId; + this.Number = number; + this.Descripton = descripton ?? throw new ArgumentNullException(nameof(descripton)); + } + + public int Id { get; } + + public int RecipeId { get; } + + public int Number { get; } + + public string Descripton { get; } +} diff --git a/webapi/Services/RecipeService.cs b/webapi/Services/RecipeService.cs index 3b78509..2da3e65 100644 --- a/webapi/Services/RecipeService.cs +++ b/webapi/Services/RecipeService.cs @@ -30,7 +30,7 @@ public RecipeService() // todo inherit project db path connection.Close(); } - public void SaveRecipe(Recipe recipe) + public void SaveRecipe(RecipeDto recipe) { // todo save always goes to db and updates internal cache, avoid desync states } From 04a1f9a7e8367d29818694ca577ed9e9b95ea734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lov=C3=A1sz=20=C3=81kos?= Date: Mon, 20 Nov 2023 20:03:12 +0100 Subject: [PATCH 14/14] added db reading --- webapi/Services/RecipeService.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/webapi/Services/RecipeService.cs b/webapi/Services/RecipeService.cs index 2da3e65..e4ae50c 100644 --- a/webapi/Services/RecipeService.cs +++ b/webapi/Services/RecipeService.cs @@ -12,21 +12,20 @@ public RecipeService() // todo inherit project db path { string connectionString = "Data source = isCooking.db"; // todo how to get this dynamically? - using SqliteConnection connection = new(connectionString); + var connection = new SqliteConnection(connectionString); connection.Open(); - const string sql = "SELECT * FROM Recipe"; + var command = connection.CreateCommand(); + command.CommandText = "SELECT * FROM Recipe"; - SqliteCommand cmd = new(sql, connection); - - SqliteDataReader reader = cmd.ExecuteReader(); - - foreach (object? item in reader) + using ( var reader = command.ExecuteReader() ) { - Console.WriteLine(item.ToString()); + while ( reader.Read() ) { + // todo cache + } + } - //this.recipes = (List)cmd.ExecuteScalar(); // todo fill cache, how tf tho connection.Close(); }