diff --git a/exercise.webapi/DTO/AuthorGetDTO.cs b/exercise.webapi/DTO/AuthorGetDTO.cs new file mode 100644 index 0000000..a3819ed --- /dev/null +++ b/exercise.webapi/DTO/AuthorGetDTO.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; + +namespace exercise.webapi.DTO +{ + public class AuthorGetDTO + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public List? Books { get; set; } + public List? Publishers { get; set; } + } +} diff --git a/exercise.webapi/DTO/AuthorPostDTO.cs b/exercise.webapi/DTO/AuthorPostDTO.cs new file mode 100644 index 0000000..12d8a62 --- /dev/null +++ b/exercise.webapi/DTO/AuthorPostDTO.cs @@ -0,0 +1,11 @@ +namespace exercise.webapi.DTO +{ + public class AuthorPostDTO + { + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public List Books { get; set; } + } +} diff --git a/exercise.webapi/DTO/AuthorPutDTO.cs b/exercise.webapi/DTO/AuthorPutDTO.cs new file mode 100644 index 0000000..353f62e --- /dev/null +++ b/exercise.webapi/DTO/AuthorPutDTO.cs @@ -0,0 +1,10 @@ +namespace exercise.webapi.DTO +{ + public class AuthorPutDTO + { + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + public List Books { get; set; } + } +} diff --git a/exercise.webapi/DTO/AuthorReponseDTO.cs b/exercise.webapi/DTO/AuthorReponseDTO.cs new file mode 100644 index 0000000..8e1a1f1 --- /dev/null +++ b/exercise.webapi/DTO/AuthorReponseDTO.cs @@ -0,0 +1,18 @@ +using exercise.webapi.Models; +using System.Text.Json.Serialization; + +namespace exercise.webapi.DTO +{ + public class AuthorReponseDTO + { + public DateTime When { get; set; } = DateTime.Now; + public string Status { get; set; } = ""; + + public int Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string Email { get; set; } + + public List Books { get; set; } = new List(); + } +} diff --git a/exercise.webapi/DTO/BookGetDTO.cs b/exercise.webapi/DTO/BookGetDTO.cs new file mode 100644 index 0000000..29511e2 --- /dev/null +++ b/exercise.webapi/DTO/BookGetDTO.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; + +namespace exercise.webapi.DTO +{ + public class BookGetDTO + { + public int Id { get; set; } + public string Title { get; set; } + + [JsonIgnore] + public int AuthorId { get; set; } + public AuthorGetDTO? Author { get; set; } + + [JsonIgnore] + public int PublisherId { get; set; } + + public PublisherGetDTO? Publisher { get; set; } + } +} diff --git a/exercise.webapi/DTO/BookPostDTO.cs b/exercise.webapi/DTO/BookPostDTO.cs new file mode 100644 index 0000000..63a3465 --- /dev/null +++ b/exercise.webapi/DTO/BookPostDTO.cs @@ -0,0 +1,11 @@ +using exercise.webapi.Models; + +namespace exercise.webapi.DTO +{ + public class BookPostDTO + { + public string Title { get; set; } + public int AuthorId { get; set; } + public int PublisherId { get; set; } + } +} diff --git a/exercise.webapi/DTO/BookPutDTO.cs b/exercise.webapi/DTO/BookPutDTO.cs new file mode 100644 index 0000000..bb768cd --- /dev/null +++ b/exercise.webapi/DTO/BookPutDTO.cs @@ -0,0 +1,10 @@ +using exercise.webapi.Models; + +namespace exercise.webapi.DTO +{ + public class BookPutDTO + { + public int AuthorId { get; set; } + public int PublisherId { get; set; } + } +} diff --git a/exercise.webapi/DTO/BookResponseDTO.cs b/exercise.webapi/DTO/BookResponseDTO.cs new file mode 100644 index 0000000..c307026 --- /dev/null +++ b/exercise.webapi/DTO/BookResponseDTO.cs @@ -0,0 +1,7 @@ +namespace exercise.webapi.DTO +{ + public class BookResponseDTO + { + public string Title { get; set; } + } +} diff --git a/exercise.webapi/DTO/PublisherGetDTO.cs b/exercise.webapi/DTO/PublisherGetDTO.cs new file mode 100644 index 0000000..b268b1b --- /dev/null +++ b/exercise.webapi/DTO/PublisherGetDTO.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace exercise.webapi.DTO +{ + public class PublisherGetDTO + { + public int Id { get; set; } + public string Name { get; set; } + + public List? Books { get; set; } + } +} diff --git a/exercise.webapi/Data/DataContext.cs b/exercise.webapi/Data/DataContext.cs index b6be7a9..3b3828f 100644 --- a/exercise.webapi/Data/DataContext.cs +++ b/exercise.webapi/Data/DataContext.cs @@ -24,9 +24,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasData(seeder.Authors); modelBuilder.Entity().HasData(seeder.Books); + modelBuilder.Entity().HasData(seeder.Publishers); } public DbSet Authors { get; set; } public DbSet Books { get; set; } + public DbSet Publishers { get; set; } } } diff --git a/exercise.webapi/Data/Seeder.cs b/exercise.webapi/Data/Seeder.cs index 955e3c8..7405ba4 100644 --- a/exercise.webapi/Data/Seeder.cs +++ b/exercise.webapi/Data/Seeder.cs @@ -1,4 +1,5 @@ using exercise.webapi.Models; +using Microsoft.EntityFrameworkCore; namespace exercise.webapi.Data { @@ -6,112 +7,97 @@ public class Seeder { private List _firstnames = new List() { - "Audrey", - "Donald", - "Elvis", - "Barack", - "Oprah", - "Jimi", - "Mick", - "Kate", - "Charles", - "Kate" + "Audrey", "Donald", "Elvis", "Barack", "Oprah", + "Jimi", "Mick", "Kate", "Charles", "Kate" }; + private List _lastnames = new List() { - "Hepburn", - "Trump", - "Presley", - "Obama", - "Winfrey", - "Hendrix", - "Jagger", - "Winslet", - "Windsor", - "Middleton" - + "Hepburn", "Trump", "Presley", "Obama", "Winfrey", + "Hendrix", "Jagger", "Winslet", "Windsor", "Middleton" }; + private List _domain = new List() { - "bbc.co.uk", - "google.com", - "theworld.ca", - "something.com", - "tesla.com", - "nasa.org.us", - "gov.us", - "gov.gr", - "gov.nl", - "gov.ru" + "bbc.co.uk", "google.com", "theworld.ca", "something.com", + "tesla.com", "nasa.org.us", "gov.us", "gov.gr", "gov.nl", "gov.ru" }; + private List _firstword = new List() { - "The", - "Two", - "Several", - "Fifteen", - "A bunch of", - "An army of", - "A herd of" - - + "The", "Two", "Several", "Fifteen", "A bunch of", "An army of", "A herd of" }; + private List _secondword = new List() { - "Orange", - "Purple", - "Large", - "Microscopic", - "Green", - "Transparent", - "Rose Smelling", - "Bitter" + "Orange", "Purple", "Large", "Microscopic", "Green", "Transparent", "Rose Smelling", "Bitter" }; + private List _thirdword = new List() { - "Buildings", - "Cars", - "Planets", - "Houses", - "Flowers", - "Leopards" + "Buildings", "Cars", "Planets", "Houses", "Flowers", "Leopards" + }; + + private List _publisherNames = new List() + { + "Penguin Random House", "Simon & Schuster", "HarperCollins", + "Hachette Livre", "Scholastic", "Macmillan Publishers", + "Bloomsbury Publishing", "DK Publishing", "Wiley", "McGraw-Hill Education" }; private List _authors = new List(); private List _books = new List(); + private List _publishers = new List(); public Seeder() { + Random random = new Random(); - Random authorRandom = new Random(); - Random bookRandom = new Random(); - - - - for (int x = 1; x < 250; x++) + // Create Authors + for (int x = 1; x <= 50; x++) { - Author author = new Author(); - author.Id = x; - author.FirstName = _firstnames[authorRandom.Next(_firstnames.Count)]; - author.LastName = _lastnames[authorRandom.Next(_lastnames.Count)]; - author.Email = $"{author.FirstName}.{author.LastName}@{_domain[authorRandom.Next(_domain.Count)]}".ToLower(); + Author author = new Author + { + Id = x, + FirstName = _firstnames[random.Next(_firstnames.Count)], + LastName = _lastnames[random.Next(_lastnames.Count)], + Email = $"{_firstnames[random.Next(_firstnames.Count)]}.{_lastnames[random.Next(_lastnames.Count)]}@{_domain[random.Next(_domain.Count)]}".ToLower() + }; _authors.Add(author); } + // Create Publishers + for (int x = 1; x <= _publisherNames.Count; x++) + { + Publisher publisher = new Publisher + { + Id = x, + Name = _publisherNames[x - 1] + }; + _publishers.Add(publisher); + } - for (int y = 1; y < 250; y++) + // Create Books + for (int x = 1; x <= 50; x++) { - Book book = new Book(); - book.Id = y; - book.Title = $"{_firstword[bookRandom.Next(_firstword.Count)]} {_secondword[bookRandom.Next(_secondword.Count)]} {_thirdword[bookRandom.Next(_thirdword.Count)]}"; - book.AuthorId = _authors[authorRandom.Next(_authors.Count)].Id; - //book.Author = authors[book.AuthorId-1]; + Author randomAuthor = _authors[random.Next(_authors.Count)]; + Publisher randomPublisher = _publishers[random.Next(_publishers.Count)]; + + Book book = new Book + { + Id = x, + Title = $"{_firstword[random.Next(_firstword.Count)]} {_secondword[random.Next(_secondword.Count)]} {_thirdword[random.Next(_thirdword.Count)]}", + AuthorId = randomAuthor.Id, + PublisherId = randomPublisher.Id + }; + _books.Add(book); } - } - public List Authors { get { return _authors; } } - public List Books { get { return _books; } } + public List Authors => _authors; + public List Books => _books; + public List Publishers => _publishers; } + } diff --git a/exercise.webapi/Endpoints/AuthorApi.cs b/exercise.webapi/Endpoints/AuthorApi.cs new file mode 100644 index 0000000..9e33060 --- /dev/null +++ b/exercise.webapi/Endpoints/AuthorApi.cs @@ -0,0 +1,68 @@ +using exercise.webapi.DTO; +using exercise.webapi.Repository; +using Microsoft.AspNetCore.Mvc; + +namespace exercise.webapi.Endpoints +{ + public static class AuthorApi + { + public static void ConfigureAuthorsApi(this WebApplication app) + { + var authors = app.MapGroup("/authors"); + + authors.MapGet("/", GetAuthors); + authors.MapGet("/{id}", GetSingleAuthor); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetAuthors(IAuthorRepository authorRepository) + { + var authors = await authorRepository.GetAllAuthors(); + + // Handle null or empty list + if (authors == null || !authors.Any()) + { + return Results.Ok(new List()); + } + + var authorResponses = authors.Select(author => new AuthorReponseDTO + { + Id = author.Id, + FirstName = author.FirstName, + LastName = author.LastName, + Email = author.Email, + Status = "Success", + Books = author.Books?.Select(book => new BookResponseDTO + { + Title = book.Title + }).ToList() ?? new List() + }).ToList(); + + return Results.Ok(authorResponses); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public static async Task GetSingleAuthor(IAuthorRepository authorRepository, int id) + { + var author = await authorRepository.GetAuthorById(id); + if (author == null) + { + return Results.NotFound(); + } + var authorResponse = new AuthorReponseDTO + { + Id = author.Id, + FirstName = author.FirstName, + LastName = author.LastName, + Email = author.Email, + Status = "Success", + Books = author.Books.Select(book => new BookResponseDTO + { + Title = book.Title + }).ToList() + }; + return Results.Ok(authorResponse); + } + } +} diff --git a/exercise.webapi/Endpoints/BookApi.cs b/exercise.webapi/Endpoints/BookApi.cs index 6758215..3c0306a 100644 --- a/exercise.webapi/Endpoints/BookApi.cs +++ b/exercise.webapi/Endpoints/BookApi.cs @@ -1,5 +1,7 @@ -using exercise.webapi.Models; +using exercise.webapi.DTO; +using exercise.webapi.Models; using exercise.webapi.Repository; +using Microsoft.AspNetCore.Mvc; using static System.Reflection.Metadata.BlobBuilder; namespace exercise.webapi.Endpoints @@ -8,13 +10,128 @@ public static class BookApi { public static void ConfigureBooksApi(this WebApplication app) { - app.MapGet("/books", GetBooks); + var books = app.MapGroup("/books"); + + books.MapGet("/", GetBooks); + books.MapGet("/{id}", GetSingleBook); + books.MapPost("/", CreateBook); + books.MapPut("/{id}", UpdateBook); + books.MapDelete("/{id}", DeleteBook); } + [ProducesResponseType(StatusCodes.Status200OK)] private static async Task GetBooks(IBookRepository bookRepository) { var books = await bookRepository.GetAllBooks(); return TypedResults.Ok(books); } + + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public static async Task GetSingleBook(IBookRepository bookRepository, int id) + { + var book = await bookRepository.GetBookById(id); + if (book == null) + { + return TypedResults.NotFound(); + } + + return TypedResults.Ok(book); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public static async Task CreateBook( + IBookRepository bookRepository, + IAuthorRepository authorRepository, + IPublisherRepository publisherRepository, + BookPostDTO bookDto) + { + if (bookDto == null) + { + return Results.BadRequest("Invalid book object"); + } + + // Check author + var author = await authorRepository.GetAuthorById(bookDto.AuthorId); + if (author == null) + { + return Results.NotFound($"Author with ID {bookDto.AuthorId} not found"); + } + + // Check publisher + var publisher = await publisherRepository.GetPublisherById(bookDto.PublisherId); + if (publisher == null) + { + return Results.NotFound($"Publisher with ID {bookDto.PublisherId} not found"); + } + + // Create book + var newBook = new Book + { + Title = bookDto.Title, + AuthorId = bookDto.AuthorId, + PublisherId = bookDto.PublisherId + + }; + + var createdBook = await bookRepository.AddBook(newBook); + return Results.Created($"/books/{createdBook.Id}", createdBook); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public static async Task UpdateBook( + IBookRepository bookRepository, + IAuthorRepository authorRepository, + IPublisherRepository publisherRepository, + int id, + BookPutDTO bookDto) + { + // Find existing book + var existingBook = await bookRepository.GetBookByIdAsModel(id); + if (existingBook == null) + { + return Results.NotFound($"Book with ID {id} not found"); + } + + // Retrieve author of book + var author = await authorRepository.GetAuthorById(bookDto.AuthorId); + if (author == null) + { + return Results.NotFound($"Author with ID {bookDto.AuthorId} not found"); + } + + // Retrieve publisher of book + var publisher = await publisherRepository.GetPublisherById(bookDto.PublisherId); + if (publisher == null) + { + return Results.NotFound($"Publisher with ID {bookDto.PublisherId} not found"); + } + + // Update book + existingBook.AuthorId = bookDto.AuthorId; + existingBook.PublisherId = bookDto.PublisherId; + + var updatedBook = await bookRepository.UpdateBook(id, existingBook); + + return Results.Created($"/books/{id}", updatedBook); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public static async Task DeleteBook(IBookRepository bookRepository, int id) + { + var book = await bookRepository.GetBookById(id); + if (book == null) + { + return TypedResults.NotFound(); + } + + await bookRepository.DeleteBook(id); + + return TypedResults.Ok(book); + } } } diff --git a/exercise.webapi/Endpoints/PublisherApi.cs b/exercise.webapi/Endpoints/PublisherApi.cs new file mode 100644 index 0000000..3742b46 --- /dev/null +++ b/exercise.webapi/Endpoints/PublisherApi.cs @@ -0,0 +1,34 @@ +using exercise.webapi.Repository; +using Microsoft.AspNetCore.Mvc; + +namespace exercise.webapi.Endpoints +{ + public static class PublisherApi + { + public static void ConfigurePublishersApi(this WebApplication app) + { + var publishers = app.MapGroup("/publishers"); + + publishers.MapGet("/", GetPublishers); + publishers.MapGet("/{id}", GetSinglePublisher); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + private static async Task GetPublishers(IPublisherRepository publisherRepository) + { + var publishers = await publisherRepository.GetAllPublishers(); + return Results.Ok(publishers); + } + + [ProducesResponseType(StatusCodes.Status200OK)] + public static async Task GetSinglePublisher(IPublisherRepository publisherRepository, int id) + { + var publisher = await publisherRepository.GetPublisherById(id); + if (publisher == null) + { + return Results.NotFound(); + } + return Results.Ok(publisher); + } + } +} diff --git a/exercise.webapi/Models/Book.cs b/exercise.webapi/Models/Book.cs index 9534929..0c73520 100644 --- a/exercise.webapi/Models/Book.cs +++ b/exercise.webapi/Models/Book.cs @@ -9,5 +9,8 @@ public class Book public int AuthorId { get; set; } public Author Author { get; set; } + + public int PublisherId { get; set; } + public Publisher Publisher { get; set; } } } diff --git a/exercise.webapi/Models/Publisher.cs b/exercise.webapi/Models/Publisher.cs new file mode 100644 index 0000000..52739b8 --- /dev/null +++ b/exercise.webapi/Models/Publisher.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace exercise.webapi.Models +{ + public class Publisher + { + public int Id { get; set; } + public string Name { get; set; } + + public ICollection Books { get; set; } = new List(); + } +} diff --git a/exercise.webapi/Program.cs b/exercise.webapi/Program.cs index 43dec56..5896cb4 100644 --- a/exercise.webapi/Program.cs +++ b/exercise.webapi/Program.cs @@ -11,6 +11,8 @@ builder.Services.AddSwaggerGen(); builder.Services.AddDbContext(opt => opt.UseInMemoryDatabase("Library")); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); var app = builder.Build(); @@ -29,4 +31,6 @@ app.UseHttpsRedirection(); app.ConfigureBooksApi(); +app.ConfigureAuthorsApi(); +app.ConfigurePublishersApi(); app.Run(); diff --git a/exercise.webapi/Repository/AuthorRepository.cs b/exercise.webapi/Repository/AuthorRepository.cs new file mode 100644 index 0000000..2a15b02 --- /dev/null +++ b/exercise.webapi/Repository/AuthorRepository.cs @@ -0,0 +1,73 @@ +using exercise.webapi.Data; +using exercise.webapi.Models; +using exercise.webapi.DTO; +using Microsoft.EntityFrameworkCore; + +namespace exercise.webapi.Repository +{ + public class AuthorRepository : IAuthorRepository + { + private readonly DataContext _db; + + public AuthorRepository(DataContext db) + { + _db = db; + } + + public async Task> GetAllAuthors() + { + return await _db.Authors + .Include(a => a.Books) + .ThenInclude(b => b.Publisher) + .Select(a => new AuthorGetDTO + { + Id = a.Id, + FirstName = a.FirstName, + LastName = a.LastName, + Email = a.Email, + Books = a.Books.Select(b => new BookGetDTO + { + Id = b.Id, + Title = b.Title, + Author = null, // Prevents circular reference + Publisher = new PublisherGetDTO + { + Id = b.Publisher.Id, + Name = b.Publisher.Name + } + }).ToList() + }) + .ToListAsync(); + } + + + public async Task GetAuthorById(int id) + { + return await _db.Authors + .Include(a => a.Books) + .ThenInclude(b => b.Publisher) + .Where(a => a.Id == id) + .Select(a => new AuthorGetDTO + { + Id = a.Id, + FirstName = a.FirstName, + LastName = a.LastName, + Email = a.Email, + Books = a.Books.Select(b => new BookGetDTO + { + Id = b.Id, + Title = b.Title, + Author = null, // ✅ Prevents circular reference + Publisher = b.Publisher != null ? new PublisherGetDTO + { + Id = b.Publisher.Id, + Name = b.Publisher.Name, + Books = null // ✅ Prevents recursion in Publisher's books + } : null + }).ToList() + }) + .FirstOrDefaultAsync(); + } + + } +} \ No newline at end of file diff --git a/exercise.webapi/Repository/BookRepository.cs b/exercise.webapi/Repository/BookRepository.cs index 1f5e64a..fd06a6b 100644 --- a/exercise.webapi/Repository/BookRepository.cs +++ b/exercise.webapi/Repository/BookRepository.cs @@ -1,4 +1,5 @@ using exercise.webapi.Data; +using exercise.webapi.DTO; using exercise.webapi.Models; using Microsoft.EntityFrameworkCore; @@ -13,10 +14,93 @@ public BookRepository(DataContext db) _db = db; } - public async Task> GetAllBooks() + public async Task> GetAllBooks() { - return await _db.Books.Include(b => b.Author).ToListAsync(); + return await _db.Books + .Include(b => b.Author) + .Include(b => b.Publisher) + .Select(b => new BookGetDTO + { + Id = b.Id, + Title = b.Title, + Author = new AuthorGetDTO + { + Id = b.Author.Id, + FirstName = b.Author.FirstName, + LastName = b.Author.LastName, + Email = b.Author.Email + }, + Publisher = new PublisherGetDTO + { + Id = b.Publisher.Id, + Name = b.Publisher.Name + } + }) + .ToListAsync(); } + + public async Task GetBookById(int id) + { + return await _db.Books + .Include(b => b.Author) + .Include(b => b.Publisher) + .Where(b => b.Id == id) + .Select(b => new BookGetDTO + { + Id = b.Id, + Title = b.Title, + Author = new AuthorGetDTO + { + Id = b.Author.Id, + FirstName = b.Author.FirstName, + LastName = b.Author.LastName, + Email = b.Author.Email + }, + Publisher = new PublisherGetDTO + { + Id = b.Publisher.Id, + Name = b.Publisher.Name + } + }) + .FirstOrDefaultAsync(); + } + + public async Task GetBookByIdAsModel(int id) + { + return await _db.Books + .Include(b => b.Author) + .Include(b => b.Publisher) + .FirstOrDefaultAsync(b => b.Id == id); + } + + public async Task AddBook(Book book) + { + await _db.Books.AddAsync(book); + await _db.SaveChangesAsync(); + return book; + } + + public async Task UpdateBook(int id, Book book) + { + var existingBook = await _db.Books.FindAsync(id); + + existingBook.AuthorId = book.AuthorId; + existingBook.AuthorId = book.PublisherId; + + await _db.SaveChangesAsync(); + return existingBook; + } + + + public async Task DeleteBook(int id) + { + var book = await _db.Books.FindAsync(id); + _db.Books.Remove(book); + await _db.SaveChangesAsync(); + return true; + } + + } } diff --git a/exercise.webapi/Repository/IAuthorRepository.cs b/exercise.webapi/Repository/IAuthorRepository.cs new file mode 100644 index 0000000..044a08b --- /dev/null +++ b/exercise.webapi/Repository/IAuthorRepository.cs @@ -0,0 +1,11 @@ +using exercise.webapi.DTO; +using exercise.webapi.Models; + +namespace exercise.webapi.Repository +{ + public interface IAuthorRepository + { + Task> GetAllAuthors(); + Task GetAuthorById(int id); + } +} diff --git a/exercise.webapi/Repository/IBookRepository.cs b/exercise.webapi/Repository/IBookRepository.cs index f860016..7f37140 100644 --- a/exercise.webapi/Repository/IBookRepository.cs +++ b/exercise.webapi/Repository/IBookRepository.cs @@ -1,9 +1,15 @@ -using exercise.webapi.Models; +using exercise.webapi.DTO; +using exercise.webapi.Models; namespace exercise.webapi.Repository { public interface IBookRepository { - public Task> GetAllBooks(); + Task> GetAllBooks(); + Task GetBookById(int id); + Task GetBookByIdAsModel(int id); + Task AddBook(Book book); + Task UpdateBook(int id, Book book); + Task DeleteBook(int id); } } diff --git a/exercise.webapi/Repository/IPublisherRepository.cs b/exercise.webapi/Repository/IPublisherRepository.cs new file mode 100644 index 0000000..d6e1047 --- /dev/null +++ b/exercise.webapi/Repository/IPublisherRepository.cs @@ -0,0 +1,11 @@ +using exercise.webapi.DTO; + +namespace exercise.webapi.Repository +{ + public interface IPublisherRepository + { + Task> GetAllPublishers(); + Task GetPublisherById(int id); + } + +} diff --git a/exercise.webapi/Repository/PublisherRepository.cs b/exercise.webapi/Repository/PublisherRepository.cs new file mode 100644 index 0000000..0a5c0fc --- /dev/null +++ b/exercise.webapi/Repository/PublisherRepository.cs @@ -0,0 +1,69 @@ +using exercise.webapi.Data; +using exercise.webapi.DTO; +using Microsoft.EntityFrameworkCore; + +namespace exercise.webapi.Repository +{ + public class PublisherRepository : IPublisherRepository + { + private readonly DataContext _db; + + public PublisherRepository(DataContext db) + { + _db = db; + } + + public async Task> GetAllPublishers() + { + return await _db.Publishers + .Include(p => p.Books) + .ThenInclude(b => b.Author) + .Select(p => new PublisherGetDTO + { + Id = p.Id, + Name = p.Name, + Books = p.Books.Select(b => new BookGetDTO + { + Id = b.Id, + Title = b.Title, + Author = new AuthorGetDTO + { + Id = b.Author.Id, + FirstName = b.Author.FirstName, + LastName = b.Author.LastName, + Email = b.Author.Email + }, + Publisher = null + }).ToList() + }) + .ToListAsync(); + } + + public async Task GetPublisherById(int id) + { + return await _db.Publishers + .Include(p => p.Books) + .ThenInclude(b => b.Author) + .Where(p => p.Id == id) + .Select(p => new PublisherGetDTO + { + Id = p.Id, + Name = p.Name, + Books = p.Books.Select(b => new BookGetDTO + { + Id = b.Id, + Title = b.Title, + Author = new AuthorGetDTO + { + Id = b.Author.Id, + FirstName = b.Author.FirstName, + LastName = b.Author.LastName, + Email = b.Author.Email + }, + Publisher = null // Prevents circular reference + }).ToList() + }) + .FirstOrDefaultAsync(); + } + } +} diff --git a/exercise.webapi/exercise.webapi.csproj b/exercise.webapi/exercise.webapi.csproj index 0ff4269..ad12bcf 100644 --- a/exercise.webapi/exercise.webapi.csproj +++ b/exercise.webapi/exercise.webapi.csproj @@ -1,4 +1,4 @@ - + net9.0 @@ -9,9 +9,14 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + +