diff --git a/NorthwindCRUD/Controllers/CustomersController.cs b/NorthwindCRUD/Controllers/CustomersController.cs index cc6dd77..e040572 100644 --- a/NorthwindCRUD/Controllers/CustomersController.cs +++ b/NorthwindCRUD/Controllers/CustomersController.cs @@ -120,6 +120,21 @@ public ActionResult GetCustomersCount() } } + [HttpGet("WithOrders")] + public ActionResult GetAllCustomersWithOrders() + { + try + { + var customers = this.customerService.GetAllCustomersWithOrders(); + return Ok(this.mapper.Map(customers)); + } + catch (Exception error) + { + logger.LogError(error.Message); + return StatusCode(500); + } + } + [HttpGet("{id}")] public ActionResult GetById(string id) { @@ -156,6 +171,21 @@ public ActionResult GetOrdersByCustomerId(string id) } } + [HttpGet("{id}/Orders/WithDetails")] + public ActionResult GetOrdersAndOrderDetailsByCustomerId(string id) + { + try + { + var orders = this.orderService.GetOrdersWithDetailsByCustomerId(id); + return Ok(this.mapper.Map(orders)); + } + catch (Exception error) + { + logger.LogError(error.Message); + return StatusCode(500); + } + } + [HttpPost] [Authorize] public ActionResult Create(CustomerDto model) diff --git a/NorthwindCRUD/Controllers/RegionsController.cs b/NorthwindCRUD/Controllers/RegionsController.cs index 29b6a50..0d16f13 100644 --- a/NorthwindCRUD/Controllers/RegionsController.cs +++ b/NorthwindCRUD/Controllers/RegionsController.cs @@ -141,7 +141,7 @@ public ActionResult GetById(int id) } [HttpGet("{id}/Territories")] - public ActionResult GetTerritoryByRegionId(int id) + public ActionResult GetTerritoryByRegionId(int id) { try { diff --git a/NorthwindCRUD/Helpers/MappingProfiles.cs b/NorthwindCRUD/Helpers/MappingProfiles.cs index 675a14c..65b2709 100644 --- a/NorthwindCRUD/Helpers/MappingProfiles.cs +++ b/NorthwindCRUD/Helpers/MappingProfiles.cs @@ -18,6 +18,8 @@ public MappingProfiles() CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); diff --git a/NorthwindCRUD/Models/DbModels/OrderDb.cs b/NorthwindCRUD/Models/DbModels/OrderDb.cs index 7ff3b5a..94e3b41 100644 --- a/NorthwindCRUD/Models/DbModels/OrderDb.cs +++ b/NorthwindCRUD/Models/DbModels/OrderDb.cs @@ -46,5 +46,7 @@ public OrderDb() public bool Completed { get; set; } public AddressDb? ShipAddress { get; set; } + + public ICollection OrderDetails { get; set; } } } diff --git a/NorthwindCRUD/Models/DbModels/ProductDb.cs b/NorthwindCRUD/Models/DbModels/ProductDb.cs index 9cab5d4..8277ddd 100644 --- a/NorthwindCRUD/Models/DbModels/ProductDb.cs +++ b/NorthwindCRUD/Models/DbModels/ProductDb.cs @@ -10,6 +10,8 @@ public class ProductDb : IProduct [DatabaseGenerated(DatabaseGeneratedOption.None)] public int ProductId { get; set; } + public string Productname { get; set; } + public int? SupplierId { get; set; } public SupplierDb? Supplier { get; set; } diff --git a/NorthwindCRUD/Models/Dtos/CustomerWithOrdersDto.cs b/NorthwindCRUD/Models/Dtos/CustomerWithOrdersDto.cs new file mode 100644 index 0000000..7ad35e4 --- /dev/null +++ b/NorthwindCRUD/Models/Dtos/CustomerWithOrdersDto.cs @@ -0,0 +1,9 @@ +using NorthwindCRUD.Models.Contracts; + +namespace NorthwindCRUD.Models.Dtos +{ + public class CustomerWithOrdersDto : CustomerDto, ICustomer + { + public OrderWithDetailsDto[] Orders { get; set; } + } +} diff --git a/NorthwindCRUD/Models/Dtos/OrderWithDetailsDto.cs b/NorthwindCRUD/Models/Dtos/OrderWithDetailsDto.cs new file mode 100644 index 0000000..4fda6e0 --- /dev/null +++ b/NorthwindCRUD/Models/Dtos/OrderWithDetailsDto.cs @@ -0,0 +1,9 @@ +using NorthwindCRUD.Models.Contracts; + +namespace NorthwindCRUD.Models.Dtos +{ + public class OrderWithDetailsDto : OrderDto, IOrder + { + public OrderDetailDto[] OrderDetails { get; set; } + } +} diff --git a/NorthwindCRUD/Models/Dtos/ProductDto.cs b/NorthwindCRUD/Models/Dtos/ProductDto.cs index 6159499..9cf8d37 100644 --- a/NorthwindCRUD/Models/Dtos/ProductDto.cs +++ b/NorthwindCRUD/Models/Dtos/ProductDto.cs @@ -6,6 +6,8 @@ public class ProductDto : IProduct { public int ProductId { get; set; } + public string ProductName { get; set; } + public int? SupplierId { get; set; } public int? CategoryId { get; set; } diff --git a/NorthwindCRUD/Providers/DbContextConfigurationProvider.cs b/NorthwindCRUD/Providers/DbContextConfigurationProvider.cs index 6df8705..992c3af 100644 --- a/NorthwindCRUD/Providers/DbContextConfigurationProvider.cs +++ b/NorthwindCRUD/Providers/DbContextConfigurationProvider.cs @@ -42,15 +42,19 @@ public void ConfigureOptions(DbContextOptionsBuilder options) var connectionString = this.GetSqlLiteConnectionString(tenantId); connection = new SqliteConnection(connectionString); memoryCache.Set(cacheKey, connection, GetCacheConnectionEntryOptions()); - } - // For SQLite in memory to be shared across multiple EF calls, we need to maintain a separate open connection. - // see post https://stackoverflow.com/questions/56319638/entityframeworkcore-sqlite-in-memory-db-tables-are-not-created - connection.Open(); + // For SQLite in memory to be shared across multiple EF calls, we need to maintain a separate open connection. + // see post https://stackoverflow.com/questions/56319638/entityframeworkcore-sqlite-in-memory-db-tables-are-not-created + connection.Open(); - options.UseSqlite(connection).EnableSensitiveDataLogging(); + options.UseSqlite(connection).EnableSensitiveDataLogging(); - SeedDb(options); + SeedDb(options); + } + else + { + options.UseSqlite(connection).EnableSensitiveDataLogging(); + } } } diff --git a/NorthwindCRUD/Resources/products.json b/NorthwindCRUD/Resources/products.json index b0a7223..aeb3459 100644 --- a/NorthwindCRUD/Resources/products.json +++ b/NorthwindCRUD/Resources/products.json @@ -253,7 +253,7 @@ }, { "productId": 22, - "productName": "Gustaf's Kn�ckebr�d", + "productName": "Gustaf's Knäckebröd", "supplierId": 9, "categoryId": 5, "quantityPerUnit": "24 - 500 g pkgs.", @@ -265,7 +265,7 @@ }, { "productId": 23, - "productName": "Tunnbr�d", + "productName": "Tunnbröd", "supplierId": 9, "categoryId": 5, "quantityPerUnit": "12 - 250 g pkgs.", @@ -277,7 +277,7 @@ }, { "productId": 24, - "productName": "Guaran� Fant�stica", + "productName": "Guaraná Fantástica", "supplierId": 10, "categoryId": 1, "quantityPerUnit": "12 - 355 ml cans", @@ -289,7 +289,7 @@ }, { "productId": 25, - "productName": "NuNuCa Nu�-Nougat-Creme", + "productName": "NuNuCa Nuß-Nougat-Creme", "supplierId": 11, "categoryId": 3, "quantityPerUnit": "20 - 450 g glasses", @@ -301,7 +301,7 @@ }, { "productId": 26, - "productName": "Gumb�r Gummib�rchen", + "productName": "Gumbär Gummibärchen", "supplierId": 11, "categoryId": 3, "quantityPerUnit": "100 - 250 g bags", @@ -325,7 +325,7 @@ }, { "productId": 28, - "productName": "R�ssle Sauerkraut", + "productName": "Rössle Sauerkraut", "supplierId": 12, "categoryId": 7, "quantityPerUnit": "25 - 825 g cans", @@ -337,7 +337,7 @@ }, { "productId": 29, - "productName": "Th�ringer Rostbratwurst", + "productName": "Thüringer Rostbratwurst", "supplierId": 12, "categoryId": 6, "quantityPerUnit": "50 bags x 30 sausgs.", @@ -445,7 +445,7 @@ }, { "productId": 38, - "productName": "C�te de Blaye", + "productName": "Côte de Blaye", "supplierId": 18, "categoryId": 1, "quantityPerUnit": "12 - 75 cl bottles", @@ -637,7 +637,7 @@ }, { "productId": 54, - "productName": "Tourti�re", + "productName": "Tourtière", "supplierId": 25, "categoryId": 6, "quantityPerUnit": "16 pies", @@ -649,7 +649,7 @@ }, { "productId": 55, - "productName": "P�t� chinois", + "productName": "Pâté chinois", "supplierId": 25, "categoryId": 6, "quantityPerUnit": "24 boxes x 2 pies", @@ -721,7 +721,7 @@ }, { "productId": 61, - "productName": "Sirop d'�rable", + "productName": "Sirop d'érable", "supplierId": 29, "categoryId": 2, "quantityPerUnit": "24 - 500 ml bottles", @@ -757,7 +757,7 @@ }, { "productId": 64, - "productName": "Wimmers gute Semmelkn�del", + "productName": "Wimmers gute Semmelknödel", "supplierId": 12, "categoryId": 5, "quantityPerUnit": "20 bags x 4 pieces", @@ -865,7 +865,7 @@ }, { "productId": 73, - "productName": "R�d Kaviar", + "productName": "Röd Kaviar", "supplierId": 17, "categoryId": 8, "quantityPerUnit": "24 - 150 g jars", @@ -889,7 +889,7 @@ }, { "productId": 75, - "productName": "Rh�nbr�u Klosterbier", + "productName": "Rhönbräu Klosterbier", "supplierId": 12, "categoryId": 1, "quantityPerUnit": "24 - 0.5 l bottles", @@ -901,7 +901,7 @@ }, { "productId": 76, - "productName": "Lakkalik��ri", + "productName": "Lakkalikööri", "supplierId": 23, "categoryId": 1, "quantityPerUnit": "500 ml", @@ -913,7 +913,7 @@ }, { "productId": 77, - "productName": "Original Frankfurter gr�ne So�e", + "productName": "Original Frankfurter grüne Soße", "supplierId": 12, "categoryId": 2, "quantityPerUnit": "12 boxes", diff --git a/NorthwindCRUD/Services/CustomerService.cs b/NorthwindCRUD/Services/CustomerService.cs index 98cc993..309be78 100644 --- a/NorthwindCRUD/Services/CustomerService.cs +++ b/NorthwindCRUD/Services/CustomerService.cs @@ -32,6 +32,16 @@ public IQueryable GetAllAsQueryable() .FirstOrDefault(c => c.CustomerId == id); } + public CustomerDb[] GetAllCustomersWithOrders() + { + return this.dataContext.Customers + .Include(c => c.Address) + .Include(c => c.Orders) + .ThenInclude(o => o.OrderDetails) + .AsNoTracking() + .ToArray(); + } + public CustomerDb Create(CustomerDb model) { var id = IdGenerator.CreateLetterId(6); diff --git a/NorthwindCRUD/Services/OrderService.cs b/NorthwindCRUD/Services/OrderService.cs index 0341e82..0697d31 100644 --- a/NorthwindCRUD/Services/OrderService.cs +++ b/NorthwindCRUD/Services/OrderService.cs @@ -54,6 +54,14 @@ public OrderDb[] GetOrdersByCustomerId(string id) .ToArray(); } + public OrderDb[] GetOrdersWithDetailsByCustomerId(string id) + { + return GetOrdersWithDetailsQuery() + .Where(o => o.CustomerId == id) + .AsNoTracking() + .ToArray(); + } + public OrderDb[] GetOrdersByEmployeeId(int id) { return GetOrdersQuery() @@ -192,5 +200,12 @@ private IQueryable GetOrdersQuery() return this.dataContext.Orders .Include(c => c.ShipAddress); } + + private IQueryable GetOrdersWithDetailsQuery() + { + return this.dataContext.Orders + .Include(c => c.OrderDetails) + .Include(c => c.ShipAddress); + } } }