From 400e1a7341dba9f3214f872925da25eb15aeae3b Mon Sep 17 00:00:00 2001 From: Martin Vu Date: Mon, 27 Jan 2025 17:02:15 +0100 Subject: [PATCH] Finished core + 1/2 extensions --- .gitignore | 1 + exercise.pizzashopapi/DTO/CustomerDTO.cs | 10 + exercise.pizzashopapi/DTO/OrderDTO.cs | 15 ++ exercise.pizzashopapi/DTO/OrderPost.cs | 10 + exercise.pizzashopapi/DTO/OrderToppingsDTO.cs | 8 + .../DTO/OrderToppingsPost.cs | 8 + exercise.pizzashopapi/DTO/PizzaDTO.cs | 9 + exercise.pizzashopapi/DTO/PizzaPost.cs | 8 + exercise.pizzashopapi/DTO/ToppingsDTO.cs | 8 + exercise.pizzashopapi/Data/DataContext.cs | 16 ++ exercise.pizzashopapi/Data/Seeder.cs | 24 ++- .../EndPoints/PizzaShopApi.cs | 187 +++++++++++++++++- exercise.pizzashopapi/Models/Customer.cs | 8 +- .../Models/DeliveryDrivers.cs | 6 + exercise.pizzashopapi/Models/Order.cs | 40 +++- exercise.pizzashopapi/Models/OrderToppings.cs | 18 ++ exercise.pizzashopapi/Models/Pizza.cs | 11 +- exercise.pizzashopapi/Models/Toppings.cs | 17 ++ exercise.pizzashopapi/Program.cs | 4 +- .../Repository/IRepository.cs | 17 +- .../Repository/Repository.cs | 94 ++++++++- exercise.pizzashopapi/Tools/MappingProfile.cs | 18 ++ .../exercise.pizzashopapi.csproj | 1 + 23 files changed, 516 insertions(+), 22 deletions(-) create mode 100644 exercise.pizzashopapi/DTO/CustomerDTO.cs create mode 100644 exercise.pizzashopapi/DTO/OrderDTO.cs create mode 100644 exercise.pizzashopapi/DTO/OrderPost.cs create mode 100644 exercise.pizzashopapi/DTO/OrderToppingsDTO.cs create mode 100644 exercise.pizzashopapi/DTO/OrderToppingsPost.cs create mode 100644 exercise.pizzashopapi/DTO/PizzaDTO.cs create mode 100644 exercise.pizzashopapi/DTO/PizzaPost.cs create mode 100644 exercise.pizzashopapi/DTO/ToppingsDTO.cs create mode 100644 exercise.pizzashopapi/Models/DeliveryDrivers.cs create mode 100644 exercise.pizzashopapi/Models/OrderToppings.cs create mode 100644 exercise.pizzashopapi/Models/Toppings.cs create mode 100644 exercise.pizzashopapi/Tools/MappingProfile.cs diff --git a/.gitignore b/.gitignore index a62e968..5d91997 100644 --- a/.gitignore +++ b/.gitignore @@ -482,3 +482,4 @@ $RECYCLE.BIN/ */**/obj/Release /exercise.pizzashopapi/appsettings.json /exercise.pizzashopapi/appsettings.Development.json +*/Migrations diff --git a/exercise.pizzashopapi/DTO/CustomerDTO.cs b/exercise.pizzashopapi/DTO/CustomerDTO.cs new file mode 100644 index 0000000..e926022 --- /dev/null +++ b/exercise.pizzashopapi/DTO/CustomerDTO.cs @@ -0,0 +1,10 @@ +using exercise.pizzashopapi.Models; + +namespace exercise.pizzashopapi.DTO +{ + public class CustomerDTO + { + public string Name { get; set; } + public List Orders { get; set; } = new List(); + } +} diff --git a/exercise.pizzashopapi/DTO/OrderDTO.cs b/exercise.pizzashopapi/DTO/OrderDTO.cs new file mode 100644 index 0000000..070c7c0 --- /dev/null +++ b/exercise.pizzashopapi/DTO/OrderDTO.cs @@ -0,0 +1,15 @@ +using exercise.pizzashopapi.Models; + +namespace exercise.pizzashopapi.DTO +{ + public class OrderDTO + { + public int Id { get; set; } + public int CustomerId { get; set; } + public int PizzaId { get; set; } + public string PizzaName { get; set; } + public List Toppings { get; set; } + public DateTime CreatedAt { get; set; } + public string Status { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/OrderPost.cs b/exercise.pizzashopapi/DTO/OrderPost.cs new file mode 100644 index 0000000..862546a --- /dev/null +++ b/exercise.pizzashopapi/DTO/OrderPost.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace exercise.pizzashopapi.DTO +{ + public class OrderPost + { + public int CustomerId { get; set; } + public int PizzaId { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/OrderToppingsDTO.cs b/exercise.pizzashopapi/DTO/OrderToppingsDTO.cs new file mode 100644 index 0000000..6ace140 --- /dev/null +++ b/exercise.pizzashopapi/DTO/OrderToppingsDTO.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.DTO +{ + public class OrderToppingsDTO + { + public int OrderId { get; set; } + public int ToppingsId { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/OrderToppingsPost.cs b/exercise.pizzashopapi/DTO/OrderToppingsPost.cs new file mode 100644 index 0000000..f607da7 --- /dev/null +++ b/exercise.pizzashopapi/DTO/OrderToppingsPost.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.DTO +{ + public class OrderToppingsPost + { + public int OrderId { get; set; } + public int ToppingsId { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/PizzaDTO.cs b/exercise.pizzashopapi/DTO/PizzaDTO.cs new file mode 100644 index 0000000..3cec1eb --- /dev/null +++ b/exercise.pizzashopapi/DTO/PizzaDTO.cs @@ -0,0 +1,9 @@ +namespace exercise.pizzashopapi.DTO +{ + public class PizzaDTO + { + public int Id { get; set; } + public string Name { get; set; } + public int Price { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/PizzaPost.cs b/exercise.pizzashopapi/DTO/PizzaPost.cs new file mode 100644 index 0000000..4a8a523 --- /dev/null +++ b/exercise.pizzashopapi/DTO/PizzaPost.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.DTO +{ + public class PizzaPost + { + public string Name { get; set; } + public int Price { get; set; } + } +} diff --git a/exercise.pizzashopapi/DTO/ToppingsDTO.cs b/exercise.pizzashopapi/DTO/ToppingsDTO.cs new file mode 100644 index 0000000..ad8b318 --- /dev/null +++ b/exercise.pizzashopapi/DTO/ToppingsDTO.cs @@ -0,0 +1,8 @@ +namespace exercise.pizzashopapi.DTO +{ + public class ToppingsDTO + { + public int Id { get; set; } + public string Name { get; set; } + } +} diff --git a/exercise.pizzashopapi/Data/DataContext.cs b/exercise.pizzashopapi/Data/DataContext.cs index 129199e..c3b3600 100644 --- a/exercise.pizzashopapi/Data/DataContext.cs +++ b/exercise.pizzashopapi/Data/DataContext.cs @@ -11,6 +11,20 @@ public DataContext() var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); connectionString = configuration.GetValue("ConnectionStrings:DefaultConnectionString"); + } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity() + .HasKey(o => new { o.OrderId, o.ToppingsId }); + + modelBuilder.Entity() + .HasMany(o => o.Toppings) + .WithMany(t => t.Order) + .UsingEntity(); + + } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -24,5 +38,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) public DbSet Pizzas { get; set; } public DbSet Customers { get; set; } public DbSet Orders { get; set; } + public DbSet Toppings { get; set; } + public DbSet OrderToppings { get; set; } } } diff --git a/exercise.pizzashopapi/Data/Seeder.cs b/exercise.pizzashopapi/Data/Seeder.cs index f87fbef..1fa223a 100644 --- a/exercise.pizzashopapi/Data/Seeder.cs +++ b/exercise.pizzashopapi/Data/Seeder.cs @@ -10,18 +10,34 @@ public async static void SeedPizzaShopApi(this WebApplication app) { if(!db.Customers.Any()) { - db.Add(new Customer() { Name="Nigel" }); + db.Add(new Customer() { Name = "Nigel" }); db.Add(new Customer() { Name = "Dave" }); + db.Add(new Customer() { Name = "Martin" }); await db.SaveChangesAsync(); } if(!db.Pizzas.Any()) { - db.Add(new Pizza() { Name = "Cheese & Pineapple" }); - db.Add(new Pizza() { Name = "Vegan Cheese Tastic" }); + db.Add(new Pizza() { Name = "Cheese & Pineapple", Price = 10 }); + db.Add(new Pizza() { Name = "Vegan Cheese Tastic", Price = 10 }); + db.Add(new Pizza() { Name = "Vegan Supreme", Price = 11}); await db.SaveChangesAsync(); } - + if(!db.Orders.Any()) + { + db.Add(new Order() { CustomerId = 1, PizzaId = 2, CreatedAt = new DateTime(2025, 1, 27, 12, 0, 0, DateTimeKind.Utc), Status = OrderStatus.Preparing }); + db.Add(new Order() { CustomerId = 2, PizzaId = 1, CreatedAt = new DateTime(2025, 1, 27, 12, 0, 0, DateTimeKind.Utc), Status = OrderStatus.Preparing }); + db.Add(new Order() { CustomerId = 3, PizzaId = 3, CreatedAt = new DateTime(2025, 1, 26, 12, 0, 0, DateTimeKind.Utc), Status = OrderStatus.Delivered }); + await db.SaveChangesAsync(); + } + if(!db.Toppings.Any()) + { + db.Add(new Toppings() { Name = "Mushrooms"}); + db.Add(new Toppings() { Name = "Onions" }); + db.Add(new Toppings() { Name = "Green Peppers" }); + db.Add(new Toppings() { Name = "Pineapple" }); + await db.SaveChangesAsync(); + } //order data if(1==1) { diff --git a/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs b/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs index f8be2b0..7480d8d 100644 --- a/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs +++ b/exercise.pizzashopapi/EndPoints/PizzaShopApi.cs @@ -1,5 +1,9 @@ -using exercise.pizzashopapi.Repository; +using AutoMapper; +using exercise.pizzashopapi.DTO; +using exercise.pizzashopapi.Models; +using exercise.pizzashopapi.Repository; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; namespace exercise.pizzashopapi.EndPoints { @@ -7,9 +11,186 @@ public static class PizzaShopApi { public static void ConfigurePizzaShopApi(this WebApplication app) { - + + + app.MapGet("/orders", GetOrders); + app.MapGet("/orders/customer/{id}",GetOrdersByCustomerId); + app.MapPost("/orders/toppings", AddToppingToOrder); + app.MapPost("/orders", CreateOrder); + app.MapGet("/orders/{id}", GetOrderById); + app.MapPut("/orders/delivered/{id}", SetOrderDelivered); + + app.MapGet("/customers", GetCustomers); + + app.MapGet("/pizzas", GetPizzas); + app.MapPost("/pizzas", CreatePizza); + + + app.MapGet("/toppings", GetToppings); + + } + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetOrders(IRepository repo, IMapper mapper) + { + var orders = await repo.GetWithNestedIncludes( + query => query + .Include(o => o.Pizza) + .Include(o => o.Customer) + .Include(o => o.OrderToppings).ThenInclude(ot => ot.Toppings) + ); + var orderDTOs = mapper.Map>(orders); + return TypedResults.Ok(orderDTOs); + } + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetCustomers(IRepository repo, IMapper mapper) + { + var customers = await repo.GetWithNestedIncludes( + query => query + .Include(c => c.Orders) + .ThenInclude(o => o.Pizza) + ); + var dtos = mapper.Map>(customers); + return TypedResults.Ok(dtos); + + } + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetOrdersByCustomerId(IRepository repo, int id, IMapper mapper) + { + var orders = await repo.GetByIdWithNestedIncludes(c => c.Id == id, + query => query + .Include(c => c.Orders) + .ThenInclude(o => o.Pizza) + ); + var customerDTO = mapper.Map(orders); + return TypedResults.Ok(customerDTO); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetPizzas(IRepository repo, IMapper mapper) + { + var pizzas = await repo.Get(); + var pizzaDTOs = mapper.Map>(pizzas); + return TypedResults.Ok(pizzaDTOs); + } + [ProducesResponseType(StatusCodes.Status201Created)] + public static async Task CreatePizza(IRepository repo, IMapper mapper, PizzaPost model) + { + try + { + var newPizza = new Pizza() + { + Name = model.Name, + Price = model.Price + }; + + var create = await repo.Insert(newPizza); + var dto = mapper.Map(newPizza); + return TypedResults.Created($"/{create.Id}", dto); + } + catch (Exception ex) + { + return TypedResults.Problem(ex.Message); + } } - + [ProducesResponseType(StatusCodes.Status201Created)] + public static async Task CreateOrder(IRepository repo, IMapper mapper, OrderPost model) + { + try + { + var newOrder = new Order() + { + CustomerId = model.CustomerId, + PizzaId = model.PizzaId, + CreatedAt = DateTime.UtcNow, + }; + + var create = await repo.Insert(newOrder); + var result = await repo.GetByIdWithNestedIncludes(o => o.Id == create.Id, + query => query + .Include(o => o.Pizza)); + var dto = mapper.Map(newOrder); + return TypedResults.Created($"/{create.Id}", dto); + } + catch (Exception ex) + { + return TypedResults.Problem(ex.Message); + } + } + + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task AddToppingToOrder( + IRepository repo, + IMapper mapper, + OrderToppingsPost model) + { + try + { + var newOt = new OrderToppings() + { + OrderId = model.OrderId, + ToppingsId = model.ToppingsId + }; + + await repo.Insert(newOt); + var dto = mapper.Map(newOt); + return TypedResults.Ok(dto); + } + catch (Exception ex) + { + return TypedResults.Problem(ex.Message); + } + } + + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetToppings(IRepository repo, IMapper mapper) + { + var toppings = await repo.Get(); + var dto = mapper.Map>(toppings); + return TypedResults.Ok(dto); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetOrderById(IRepository repo, IMapper mapper, int id) + { + try + { + var order = await repo.GetByIdWithNestedIncludes(o => o.Id == id, + query => query + .Include(o => o.Pizza) + .Include(o => o.Customer) + .Include(o => o.OrderToppings).ThenInclude(ot => ot.Toppings) + ); + + var currentStatus = Order.GetOrderStatus(order.CreatedAt, DateTime.UtcNow); + if (order.Status != currentStatus || order.Status != OrderStatus.Delivered) + { + order.Status = currentStatus; + await repo.Update(order); + } + + var dto = mapper.Map(order); + return TypedResults.Ok(dto); + } + catch (Exception ex) + { + return TypedResults.Problem(ex.Message); + } + } + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task SetOrderDelivered(IRepository repo, IMapper mapper, int id) + { + + var order = await repo.GetById(id); + + if (order.Status == OrderStatus.Delivered) return TypedResults.Ok("Order already delivered"); + order.Status = OrderStatus.Delivered; + await repo.Update(order); + return TypedResults.Ok(new + { + Order = order.Id, + Status = OrderStatus.Delivered.ToString() + }); + } } } diff --git a/exercise.pizzashopapi/Models/Customer.cs b/exercise.pizzashopapi/Models/Customer.cs index 2ca83bd..559dfc2 100644 --- a/exercise.pizzashopapi/Models/Customer.cs +++ b/exercise.pizzashopapi/Models/Customer.cs @@ -1,10 +1,16 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; namespace exercise.pizzashopapi.Models { + [Table("customers")] public class Customer { + [Key] + [Column("id")] public int Id { get; set; } + [Column("name")] public string Name { get; set; } + public List Orders { get; set; } = new List(); } } diff --git a/exercise.pizzashopapi/Models/DeliveryDrivers.cs b/exercise.pizzashopapi/Models/DeliveryDrivers.cs new file mode 100644 index 0000000..b775d47 --- /dev/null +++ b/exercise.pizzashopapi/Models/DeliveryDrivers.cs @@ -0,0 +1,6 @@ +namespace exercise.pizzashopapi.Models +{ + public class DeliveryDrivers + { + } +} diff --git a/exercise.pizzashopapi/Models/Order.cs b/exercise.pizzashopapi/Models/Order.cs index fbe6113..3510fbf 100644 --- a/exercise.pizzashopapi/Models/Order.cs +++ b/exercise.pizzashopapi/Models/Order.cs @@ -1,10 +1,44 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; namespace exercise.pizzashopapi.Models { + [Table("order")] public class Order { - - + [Key] + [Column("id")] + public int Id { get; set; } + [Column("customer_id")] + public int CustomerId { get; set; } + [Column("pizza_id")] + public int PizzaId { get; set; } + public Customer Customer { get; set; } + public Pizza Pizza { get; set; } + public List OrderToppings { get; set; } + public List Toppings { get; set; } = []; + public DateTime CreatedAt { get; set; } + public OrderStatus Status { get; set; } + public static OrderStatus GetOrderStatus(DateTime createdAt, DateTime currentTime) + { + var elapsedMinutes = (currentTime - createdAt).TotalMinutes; + + if (elapsedMinutes <= 3) + return OrderStatus.Preparing; + else if (elapsedMinutes <= 15) + return OrderStatus.Cooking; + else + return OrderStatus.Ready; + } } + + public enum OrderStatus + { + Preparing, + Cooking, + Ready, + Delivered + } + + } diff --git a/exercise.pizzashopapi/Models/OrderToppings.cs b/exercise.pizzashopapi/Models/OrderToppings.cs new file mode 100644 index 0000000..c92563d --- /dev/null +++ b/exercise.pizzashopapi/Models/OrderToppings.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace exercise.pizzashopapi.Models +{ + [Table("order_toppings")] + public class OrderToppings + { + [Column("order_id")] + [ForeignKey("orders")] + + public int OrderId { get; set; } + [Column("topping_id")] + [ForeignKey("toppings")] + public int ToppingsId { get; set; } + public Order Order { get; set; } + public Toppings Toppings { get; set; } + } +} diff --git a/exercise.pizzashopapi/Models/Pizza.cs b/exercise.pizzashopapi/Models/Pizza.cs index 5c085ec..39f7dcd 100644 --- a/exercise.pizzashopapi/Models/Pizza.cs +++ b/exercise.pizzashopapi/Models/Pizza.cs @@ -1,12 +1,17 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; namespace exercise.pizzashopapi.Models { - + [Table("pizzas")] public class Pizza - { + { + [Key] + [Column("id")] public int Id { get; set; } + [Column("name")] public string Name { get; set; } + [Column("price")] public decimal Price { get; set; } } } \ No newline at end of file diff --git a/exercise.pizzashopapi/Models/Toppings.cs b/exercise.pizzashopapi/Models/Toppings.cs new file mode 100644 index 0000000..4cd7133 --- /dev/null +++ b/exercise.pizzashopapi/Models/Toppings.cs @@ -0,0 +1,17 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace exercise.pizzashopapi.Models +{ + [Table("toppings")] + public class Toppings + { + [Key] + [Column("id")] + public int Id { get; set; } + [Column("name")] + public string Name { get; set; } + public List OrderToppings { get; set; } + public List Order { get; set; } = []; + } +} diff --git a/exercise.pizzashopapi/Program.cs b/exercise.pizzashopapi/Program.cs index c04a440..10de4d2 100644 --- a/exercise.pizzashopapi/Program.cs +++ b/exercise.pizzashopapi/Program.cs @@ -1,13 +1,15 @@ using exercise.pizzashopapi.Data; using exercise.pizzashopapi.EndPoints; using exercise.pizzashopapi.Repository; +using exercise.pizzashopapi.Tools; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); -builder.Services.AddScoped(); +builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>)); +builder.Services.AddAutoMapper(typeof(MappingProfile)); builder.Services.AddDbContext(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/exercise.pizzashopapi/Repository/IRepository.cs b/exercise.pizzashopapi/Repository/IRepository.cs index b114ea8..1911114 100644 --- a/exercise.pizzashopapi/Repository/IRepository.cs +++ b/exercise.pizzashopapi/Repository/IRepository.cs @@ -1,11 +1,20 @@ using exercise.pizzashopapi.Models; +using System.Linq.Expressions; namespace exercise.pizzashopapi.Repository { - public interface IRepository + public interface IRepository { - Task> GetOrdersByCustomer(int id); - - + Task> Get(); + Task> GetWithNestedIncludes(Func, IQueryable> configureQuery); + Task Insert(T entity); + Task> InsertRange(IEnumerable entities); + Task Update(T entity); + Task Delete(object id); + Task Save(); + Task GetById(params object[] keyValues); + Task> GetWithIncludes(params Expression>[] includes); + Task GetByIdWithIncludes(Expression> predicate, params Expression>[] includes); + Task GetByIdWithNestedIncludes(Expression> predicate, Func, IQueryable> configureQuery); } } diff --git a/exercise.pizzashopapi/Repository/Repository.cs b/exercise.pizzashopapi/Repository/Repository.cs index e109fce..4c3fe20 100644 --- a/exercise.pizzashopapi/Repository/Repository.cs +++ b/exercise.pizzashopapi/Repository/Repository.cs @@ -1,14 +1,102 @@ using exercise.pizzashopapi.Data; using exercise.pizzashopapi.Models; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore; namespace exercise.pizzashopapi.Repository { - public class Repository : IRepository + public class Repository : IRepository where T : class { private DataContext _db; - public Task> GetOrdersByCustomer(int id) + private DbSet _table = null!; + + public Repository(DataContext dataContext) + { + _db = dataContext; + _table = _db.Set(); + } + + public async Task> Get() + { + return await _table.ToListAsync(); + } + + public async Task> GetWithNestedIncludes(Func, IQueryable> configureQuery) + { + IQueryable query = _table; + + query = configureQuery(query); + + return await query.ToListAsync(); + } + + public async Task Insert(T entity) + { + _table.Add(entity); + _db.SaveChanges(); + return entity; + } + + public async Task> InsertRange(IEnumerable entities) + { + _table.AddRange(entities); + _db.SaveChanges(); + return entities; + } + public async Task Update(T entity) + { + _table.Attach(entity); + _db.Entry(entity).State = EntityState.Modified; + _db.SaveChanges(); + return entity; + } + + public async Task Delete(object id) + { + T entity = _table.Find(id); + _table.Remove(entity); + _db.SaveChanges(); + return entity; + } + + public async Task GetById(params object[] keyValues) + { + return _table.Find(keyValues); + } + public async Task> GetWithIncludes(params Expression>[] includes) + { + IQueryable query = _table; + foreach (var include in includes) + { + query = query.Include(include); + } + return await query.ToListAsync(); + } + + public async Task GetByIdWithIncludes(Expression> predicate, params Expression>[] includes) + { + IQueryable query = _table; + foreach (var include in includes) + { + query = query.Include(include); + } + return await query.FirstOrDefaultAsync(predicate); + } + + public async Task GetByIdWithNestedIncludes( + Expression> predicate, + Func, IQueryable> configureQuery) + { + IQueryable query = _table; + + query = configureQuery(query); + + return await query.FirstOrDefaultAsync(predicate); + } + public async Task Save() { - throw new NotImplementedException(); + _db.SaveChangesAsync(); } } } diff --git a/exercise.pizzashopapi/Tools/MappingProfile.cs b/exercise.pizzashopapi/Tools/MappingProfile.cs new file mode 100644 index 0000000..e0efdd9 --- /dev/null +++ b/exercise.pizzashopapi/Tools/MappingProfile.cs @@ -0,0 +1,18 @@ +using System; +using AutoMapper; +using exercise.pizzashopapi.DTO; +using exercise.pizzashopapi.Models; +namespace exercise.pizzashopapi.Tools +{ + public class MappingProfile : Profile + { + public MappingProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} diff --git a/exercise.pizzashopapi/exercise.pizzashopapi.csproj b/exercise.pizzashopapi/exercise.pizzashopapi.csproj index 624203b..4a3bdd5 100644 --- a/exercise.pizzashopapi/exercise.pizzashopapi.csproj +++ b/exercise.pizzashopapi/exercise.pizzashopapi.csproj @@ -11,6 +11,7 @@ + all