├── .gitignore ├── ChinookASPNETCoreAPINTier ├── Chinook.API │ ├── Chinook.API.csproj │ ├── Configurations │ │ ├── AppSettings.cs │ │ ├── ConfigureAppSettings.cs │ │ ├── ConfigureConnections.cs │ │ └── ServicesConfiguration.cs │ ├── Controllers │ │ ├── AlbumController.cs │ │ ├── ArtistController.cs │ │ ├── CustomerController.cs │ │ ├── EmployeeController.cs │ │ ├── GenreController.cs │ │ ├── HomeController.cs │ │ ├── InvoiceController.cs │ │ ├── InvoiceLineController.cs │ │ ├── MediaTypeController.cs │ │ ├── PlaylistController.cs │ │ └── TrackController.cs │ ├── Program.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── Chinook.DataEFCore │ ├── Chinook.DataEFCore.csproj │ ├── ChinookContext.cs │ ├── Configurations │ │ ├── AlbumConfiguration.cs │ │ ├── ArtistConfiguration.cs │ │ ├── CustomerConfiguration.cs │ │ ├── EmployeeConfiguration.cs │ │ ├── GenreConfiguration.cs │ │ ├── InvoiceConfiguration.cs │ │ ├── InvoiceLineConfiguration.cs │ │ ├── MediaTypeConfiguration.cs │ │ ├── PlaylistConfiguration.cs │ │ ├── PlaylistTrackConfiguration.cs │ │ └── TrackConfiguration.cs │ └── Repositories │ │ ├── AlbumRepository.cs │ │ ├── ArtistRepository.cs │ │ ├── CustomerRepository.cs │ │ ├── EmployeeRepository.cs │ │ ├── GenreRepository.cs │ │ ├── InvoiceLineRepository.cs │ │ ├── InvoiceRepository.cs │ │ ├── MediaTypeRepository.cs │ │ ├── PlaylistRepository.cs │ │ ├── PlaylistTrackRepository.cs │ │ └── TrackRepository.cs ├── Chinook.DataEFCoreCmpldQry │ ├── Chinook.DataEFCoreCmpldQry.csproj │ ├── ChinookContext.cs │ ├── Configurations │ │ ├── AlbumConfiguration.cs │ │ ├── ArtistConfiguration.cs │ │ ├── CustomerConfiguration.cs │ │ ├── EmployeeConfiguration.cs │ │ ├── GenreConfiguration.cs │ │ ├── InvoiceConfiguration.cs │ │ ├── InvoiceLineConfiguration.cs │ │ ├── MediaTypeConfiguration.cs │ │ ├── PlaylistConfiguration.cs │ │ ├── PlaylistTrackConfiguration.cs │ │ └── TrackConfiguration.cs │ └── Repositories │ │ ├── AlbumRepository.cs │ │ ├── ArtistRepository.cs │ │ ├── CustomerRepository.cs │ │ ├── EmployeeRepository.cs │ │ ├── GenreRepository.cs │ │ ├── InvoiceLineRepository.cs │ │ ├── InvoiceRepository.cs │ │ ├── MediaTypeRepository.cs │ │ ├── PlaylistRepository.cs │ │ ├── PlaylistTrackRepository.cs │ │ └── TrackRepository.cs ├── Chinook.Domain │ ├── ApiModels │ │ ├── AlbumApiModel.cs │ │ ├── ArtistApiModel.cs │ │ ├── CustomerApiModel.cs │ │ ├── EmployeeApiModel.cs │ │ ├── GenreApiModel.cs │ │ ├── InvoiceApiModel.cs │ │ ├── InvoiceLineApiModel.cs │ │ ├── MediaTypeApiModel.cs │ │ ├── PlaylistApiModel.cs │ │ ├── PlaylistTrackApiModel.cs │ │ └── TrackApiModel.cs │ ├── Chinook.Domain.csproj │ ├── Converters │ │ └── IConvertModel.cs │ ├── Entities │ │ ├── Album.cs │ │ ├── Artist.cs │ │ ├── Customer.cs │ │ ├── Employee.cs │ │ ├── Genre.cs │ │ ├── Invoice.cs │ │ ├── InvoiceLine.cs │ │ ├── MediaType.cs │ │ ├── Playlist.cs │ │ ├── PlaylistTrack.cs │ │ └── Track.cs │ ├── Extensions │ │ └── ConvertExtensions.cs │ ├── Repositories │ │ ├── IAlbumRepository.cs │ │ ├── IArtistRepository.cs │ │ ├── ICustomerRepository.cs │ │ ├── IEmployeeRepository.cs │ │ ├── IGenreRepository.cs │ │ ├── IInvoiceLineRepository.cs │ │ ├── IInvoiceRepository.cs │ │ ├── IMediaTypeRepository.cs │ │ ├── IPlaylistRepository.cs │ │ ├── IPlaylistTrackRepository.cs │ │ └── ITrackRepository.cs │ └── Supervisor │ │ ├── ChinookSupervisor.cs │ │ ├── ChinookSupervisorAlbum.cs │ │ ├── ChinookSupervisorArtist.cs │ │ ├── ChinookSupervisorCustomer.cs │ │ ├── ChinookSupervisorEmployee.cs │ │ ├── ChinookSupervisorGenre.cs │ │ ├── ChinookSupervisorInvoice.cs │ │ ├── ChinookSupervisorInvoiceLine.cs │ │ ├── ChinookSupervisorMediaType.cs │ │ ├── ChinookSupervisorPlaylist.cs │ │ ├── ChinookSupervisorPlaylistTrack.cs │ │ ├── ChinookSupervisorTrack.cs │ │ └── IChinookSupervisor.cs ├── Chinook.IntegrationTest │ ├── API │ │ ├── AlbumAPIAlbaTest.cs │ │ ├── AlbumAPITest.cs │ │ ├── ArtistAPITest.cs │ │ ├── CustomerAPITest.cs │ │ ├── EmployeeAPITest.cs │ │ ├── GenreAPITest.cs │ │ ├── InvoiceAPITest.cs │ │ ├── InvoiceLineAPITest.cs │ │ ├── MediaTypeAPITest.cs │ │ ├── PlaylistAPITest.cs │ │ └── TrackAPITest.cs │ ├── AlbumAddOne.http │ ├── AlbumDeleteOne.http │ ├── AlbumGetAll.http │ ├── AlbumGetOne.http │ ├── AlbumUpdateOne.http │ └── Chinook.IntegrationTest.csproj ├── Chinook.MSUnitTest │ ├── AlbumRepositoryTest.cs │ └── Chinook.MSUnitTest.csproj ├── Chinook.MockData │ ├── Chinook.MockData.csproj │ ├── ObjectExtensions.cs │ └── Repositories │ │ ├── AlbumRepository.cs │ │ ├── ArtistRepository.cs │ │ ├── CustomerRepository.cs │ │ ├── EmployeeRepository.cs │ │ ├── GenreRepository.cs │ │ ├── InvoiceLineRepository.cs │ │ ├── InvoiceRepository.cs │ │ ├── MediaTypeRepository.cs │ │ ├── PlaylistRepository.cs │ │ ├── PlaylistTrackRepository.cs │ │ └── TrackRepository.cs ├── Chinook.UnitTest │ ├── Chinook.UnitTest.csproj │ ├── Repository │ │ ├── AlbumRepositoryTest.cs │ │ ├── ArtistRepositoryTest.cs │ │ ├── CustomerRepositoryTest.cs │ │ ├── EmployeeRepositoryTest.cs │ │ ├── GenreRepositoryTest.cs │ │ ├── InvoiceLineRepositoryTest.cs │ │ ├── InvoiceRepositoryTest.cs │ │ ├── MediaTypeRepositoryTest.cs │ │ ├── PlayListRepositoryTest.cs │ │ ├── PlayListTrackRepositoryTest.cs │ │ └── TrackRepositoryTest.cs │ └── Supervisor │ │ ├── AlbumSupervisorTest.cs │ │ ├── ArtistSupervisorTest.cs │ │ ├── CustomerSupervisorTest.cs │ │ ├── EmployeeSupervisorTest.cs │ │ ├── GenreSupervisorTest.cs │ │ ├── InvoiceLineSupervisorTest.cs │ │ ├── InvoiceSupervisorTest.cs │ │ ├── MediaTypeSupervisorTest.cs │ │ ├── PlayListSupervisorTest.cs │ │ ├── PlayListTrackSupervisorTest.cs │ │ └── TrackSupervisorTest.cs └── ChinookASPNETCoreAPINTier.sln ├── Developing ASP.NET Core 2.2 Web APIs for your Web and Mobile Apps-NTier.pptx ├── LICENSE ├── README.md └── script_webapi.txt /ChinookASPNETCoreAPINTier/Chinook.API/Chinook.API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | latest 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | Always 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Configurations/AppSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Chinook.API.Configurations 2 | { 3 | public abstract class AppSettings 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Configurations/ConfigureAppSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Chinook.API.Configurations 5 | { 6 | public static class ConfigureAppSettings 7 | { 8 | public static IServiceCollection AddAppSettings(this IServiceCollection services, IConfiguration configuration) 9 | { 10 | services.Configure(_ => configuration.GetSection("AppSettings").Bind(_)); 11 | 12 | return services; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Configurations/ConfigureConnections.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Chinook.DataEFCoreCmpldQry; 7 | 8 | namespace Chinook.API.Configurations 9 | { 10 | public static class ConfigureConnections 11 | { 12 | public static IServiceCollection AddConnectionProvider(this IServiceCollection services, 13 | IConfiguration configuration) 14 | { 15 | var connection = String.Empty; 16 | 17 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 18 | { 19 | connection = configuration.GetConnectionString("ChinookDbWindows") ?? 20 | "Server=.;Database=Chinook;Trusted_Connection=True;Application Name=ChinookASPNETCoreAPINTier"; 21 | } 22 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) 23 | { 24 | connection = configuration.GetConnectionString("ChinookDbDocker") ?? 25 | "Server=localhost,1433;Database=Chinook;User=sa;Password=Pa55w0rd;Trusted_Connection=False;Application Name=ChinookASPNETCoreAPINTier"; 26 | } 27 | 28 | services.AddDbContextPool(options => options.UseSqlServer(connection)); 29 | 30 | return services; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Configurations/ServicesConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.DataEFCoreCmpldQry.Repositories; 2 | using Chinook.Domain.Repositories; 3 | using Chinook.Domain.Supervisor; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.API.Configurations 9 | { 10 | public static class ServicesConfiguration 11 | { 12 | public static IServiceCollection ConfigureRepositories(this IServiceCollection services) 13 | { 14 | services.AddScoped() 15 | .AddScoped() 16 | .AddScoped() 17 | .AddScoped() 18 | .AddScoped() 19 | .AddScoped() 20 | .AddScoped() 21 | .AddScoped() 22 | .AddScoped() 23 | .AddScoped(); 24 | 25 | return services; 26 | } 27 | 28 | public static IServiceCollection ConfigureSupervisor(this IServiceCollection services) 29 | { 30 | services.AddScoped(); 31 | 32 | return services; 33 | } 34 | 35 | public static IServiceCollection AddMiddleware(this IServiceCollection services) 36 | { 37 | services.AddMvc().AddJsonOptions(options => 38 | { 39 | options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 40 | }); 41 | 42 | return services; 43 | } 44 | 45 | public static IServiceCollection AddLogging(this IServiceCollection services) 46 | { 47 | services.AddLogging(builder => builder 48 | .AddConsole() 49 | .AddFilter(level => level >= LogLevel.Information) 50 | ); 51 | 52 | return services; 53 | } 54 | 55 | public static IServiceCollection AddCaching(this IServiceCollection services) 56 | { 57 | services.AddMemoryCache(); 58 | services.AddResponseCaching(); 59 | 60 | return services; 61 | } 62 | 63 | public static IServiceCollection AddCORS(this IServiceCollection services) 64 | { 65 | services.AddCors(options => 66 | { 67 | options.AddPolicy("CorsPolicy", 68 | builder => builder.WithOrigins("http://example.com") 69 | .AllowAnyMethod() 70 | .AllowAnyHeader() 71 | .AllowCredentials()); 72 | }); 73 | 74 | return services; 75 | } 76 | 77 | 78 | } 79 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Chinook.API.Controllers 5 | { 6 | public class HomeController : Controller 7 | { 8 | [HttpGet] 9 | [ApiExplorerSettings(IgnoreApi = true)] 10 | public IActionResult Index() 11 | { 12 | try 13 | { 14 | var uri = new Uri("/swagger", UriKind.Relative); 15 | return Redirect(uri.ToString()); 16 | } 17 | catch (Exception ex) 18 | { 19 | return StatusCode(500, ex); 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace Chinook.API 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) => BuildWebHost(args).Run(); 9 | 10 | private static IWebHost BuildWebHost(string[] args) => 11 | WebHost.CreateDefaultBuilder(args) 12 | .UseStartup() 13 | .Build(); 14 | } 15 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using Chinook.API.Configurations; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Swashbuckle.AspNetCore.Swagger; 9 | 10 | namespace Chinook.API 11 | { 12 | public class Startup 13 | { 14 | private IConfiguration Configuration { get; } 15 | 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | // This method gets called by the runtime. Use this method to add services to the container. 22 | public void ConfigureServices(IServiceCollection services) 23 | { 24 | services.Configure(options => 25 | { 26 | options.MaxValidationDepth = 2; 27 | }); 28 | 29 | services.AddMvc() 30 | .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 31 | 32 | services.ConfigureRepositories() 33 | .ConfigureSupervisor() 34 | .AddMiddleware() 35 | .AddConnectionProvider(Configuration) 36 | .AddAppSettings(Configuration) 37 | .AddCaching() 38 | .AddCORS(); 39 | 40 | services.AddSwaggerGen(s => s.SwaggerDoc("v1", new Info 41 | { 42 | Title = "Chinook API", 43 | Description = "Chinook Music Store API" 44 | })); 45 | } 46 | 47 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 48 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 49 | { 50 | if (env.IsDevelopment()) 51 | { 52 | app.UseDeveloperExceptionPage(); 53 | } 54 | else 55 | { 56 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 57 | app.UseHsts(); 58 | } 59 | 60 | app.UseCors("CorsPolicy"); 61 | app.UseStaticFiles(); 62 | app.UseHttpsRedirection(); 63 | app.UseMvc( 64 | routes => routes.MapRoute( 65 | "default", 66 | "{controller=Home}/{action=Index}/{id?}")); 67 | app.UseSwagger(); 68 | app.UseSwaggerUI(s => s.SwaggerEndpoint("/swagger/v1/swagger.json", "v1 docs")); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "ChinookDbWindows": "Server=.;Database=Chinook;Trusted_Connection=True;Application Name=ChinookASPNETCoreAPINTier", 4 | "ChinookDbDocker": "Server=localhost,1433;Database=Chinook;User=sa;Password=P@ssw0rd1;Trusted_Connection=False;Application Name=ChinookASPNETCoreAPINTier" 5 | }, 6 | "Logging": { 7 | "IncludeScopes": false, 8 | "Debug": { 9 | "LogLevel": { 10 | "Default": "Warning" 11 | } 12 | }, 13 | "Console": { 14 | "LogLevel": { 15 | "Default": "Warning" 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Chinook.DataEFCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | latest 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/ChinookContext.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Microsoft.EntityFrameworkCore; 3 | using Chinook.DataEFCore.Configurations; 4 | using Chinook.Domain.Entities; 5 | 6 | namespace Chinook.DataEFCore 7 | { 8 | public class ChinookContext : DbContext 9 | { 10 | public virtual DbSet Album { get; set; } 11 | public virtual DbSet Artist { get; set; } 12 | public virtual DbSet Customer { get; set; } 13 | public virtual DbSet Employee { get; set; } 14 | public virtual DbSet Genre { get; set; } 15 | public virtual DbSet Invoice { get; set; } 16 | public virtual DbSet InvoiceLine { get; set; } 17 | public virtual DbSet MediaType { get; set; } 18 | public virtual DbSet Playlist { get; set; } 19 | public virtual DbSet PlaylistTrack { get; set; } 20 | public virtual DbSet Track { get; set; } 21 | 22 | public static long InstanceCount; 23 | 24 | public ChinookContext(DbContextOptions options) : base(options) 25 | => Interlocked.Increment(ref InstanceCount); 26 | 27 | protected override void OnModelCreating(ModelBuilder modelBuilder) 28 | { 29 | new AlbumConfiguration(modelBuilder.Entity()); 30 | new ArtistConfiguration(modelBuilder.Entity()); 31 | new CustomerConfiguration(modelBuilder.Entity()); 32 | new EmployeeConfiguration(modelBuilder.Entity()); 33 | new GenreConfiguration(modelBuilder.Entity()); 34 | new InvoiceConfiguration(modelBuilder.Entity()); 35 | new InvoiceLineConfiguration(modelBuilder.Entity()); 36 | new MediaTypeConfiguration(modelBuilder.Entity()); 37 | new PlaylistConfiguration(modelBuilder.Entity()); 38 | new PlaylistTrackConfiguration(modelBuilder.Entity()); 39 | new TrackConfiguration(modelBuilder.Entity()); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/AlbumConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class AlbumConfiguration 8 | { 9 | public AlbumConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.ArtistId) 12 | .HasName("IFK_Artist_Album"); 13 | 14 | entity.Property(e => e.Title) 15 | .IsRequired() 16 | .HasMaxLength(160); 17 | 18 | entity.HasOne(d => d.Artist) 19 | .WithMany(p => p.Albums) 20 | .HasForeignKey(d => d.ArtistId) 21 | .OnDelete(DeleteBehavior.Restrict) 22 | .HasConstraintName("FK__Album__ArtistId__276EDEB3"); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/ArtistConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCore.Configurations 5 | { 6 | public class ArtistConfiguration 7 | { 8 | public ArtistConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/CustomerConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class CustomerConfiguration 8 | { 9 | public CustomerConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.SupportRepId) 12 | .HasName("IFK_Employee_Customer"); 13 | 14 | entity.Property(e => e.Address).HasMaxLength(70); 15 | 16 | entity.Property(e => e.City).HasMaxLength(40); 17 | 18 | entity.Property(e => e.Company).HasMaxLength(80); 19 | 20 | entity.Property(e => e.Country).HasMaxLength(40); 21 | 22 | entity.Property(e => e.Email) 23 | .IsRequired() 24 | .HasMaxLength(60); 25 | 26 | entity.Property(e => e.Fax).HasMaxLength(24); 27 | 28 | entity.Property(e => e.FirstName) 29 | .IsRequired() 30 | .HasMaxLength(40); 31 | 32 | entity.Property(e => e.LastName) 33 | .IsRequired() 34 | .HasMaxLength(20); 35 | 36 | entity.Property(e => e.Phone).HasMaxLength(24); 37 | 38 | entity.Property(e => e.PostalCode).HasMaxLength(10); 39 | 40 | entity.Property(e => e.State).HasMaxLength(40); 41 | 42 | entity.HasOne(d => d.SupportRep) 43 | .WithMany(p => p.Customers) 44 | .HasForeignKey(d => d.SupportRepId) 45 | .HasConstraintName("FK__Customer__Suppor__2C3393D0"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/EmployeeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class EmployeeConfiguration 8 | { 9 | public EmployeeConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.ReportsTo) 12 | .HasName("IFK_Employee_ReportsTo"); 13 | 14 | entity.Property(e => e.Address).HasMaxLength(70); 15 | 16 | entity.Property(e => e.BirthDate).HasColumnType("datetime"); 17 | 18 | entity.Property(e => e.City).HasMaxLength(40); 19 | 20 | entity.Property(e => e.Country).HasMaxLength(40); 21 | 22 | entity.Property(e => e.Email).HasMaxLength(60); 23 | 24 | entity.Property(e => e.Fax).HasMaxLength(24); 25 | 26 | entity.Property(e => e.FirstName) 27 | .IsRequired() 28 | .HasMaxLength(20); 29 | 30 | entity.Property(e => e.HireDate).HasColumnType("datetime"); 31 | 32 | entity.Property(e => e.LastName) 33 | .IsRequired() 34 | .HasMaxLength(20); 35 | 36 | entity.Property(e => e.Phone).HasMaxLength(24); 37 | 38 | entity.Property(e => e.PostalCode).HasMaxLength(10); 39 | 40 | entity.Property(e => e.State).HasMaxLength(40); 41 | 42 | entity.Property(e => e.Title).HasMaxLength(30); 43 | 44 | entity.HasOne(d => d.Manager) 45 | .WithMany(p => p.DirectReports) 46 | .HasForeignKey(d => d.ReportsTo) 47 | .HasConstraintName("FK__Employee__Report__2B3F6F97"); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/GenreConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCore.Configurations 5 | { 6 | public class GenreConfiguration 7 | { 8 | public GenreConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/InvoiceConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class InvoiceConfiguration 8 | { 9 | public InvoiceConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.CustomerId) 12 | .HasName("IFK_Customer_Invoice"); 13 | 14 | entity.Property(e => e.BillingAddress).HasMaxLength(70); 15 | 16 | entity.Property(e => e.BillingCity).HasMaxLength(40); 17 | 18 | entity.Property(e => e.BillingCountry).HasMaxLength(40); 19 | 20 | entity.Property(e => e.BillingPostalCode).HasMaxLength(10); 21 | 22 | entity.Property(e => e.BillingState).HasMaxLength(40); 23 | 24 | entity.Property(e => e.InvoiceDate).HasColumnType("datetime"); 25 | 26 | entity.Property(e => e.Total).HasColumnType("numeric"); 27 | 28 | entity.HasOne(d => d.Customer) 29 | .WithMany(p => p.Invoices) 30 | .HasForeignKey(d => d.CustomerId) 31 | .OnDelete(DeleteBehavior.Restrict) 32 | .HasConstraintName("FK__Invoice__Custome__2D27B809"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/InvoiceLineConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class InvoiceLineConfiguration 8 | { 9 | public InvoiceLineConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.InvoiceId) 12 | .HasName("IFK_Invoice_InvoiceLine"); 13 | 14 | entity.HasIndex(e => e.TrackId) 15 | .HasName("IFK_ProductItem_InvoiceLine"); 16 | 17 | entity.Property(e => e.UnitPrice).HasColumnType("numeric"); 18 | 19 | entity.HasOne(d => d.Invoice) 20 | .WithMany(p => p.InvoiceLines) 21 | .HasForeignKey(d => d.InvoiceId) 22 | .OnDelete(DeleteBehavior.Restrict) 23 | .HasConstraintName("FK__InvoiceLi__Invoi__2F10007B"); 24 | 25 | entity.HasOne(d => d.Track) 26 | .WithMany(p => p.InvoiceLines) 27 | .HasForeignKey(d => d.TrackId) 28 | .OnDelete(DeleteBehavior.Restrict) 29 | .HasConstraintName("FK__InvoiceLi__Track__2E1BDC42"); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/MediaTypeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCore.Configurations 5 | { 6 | public class MediaTypeConfiguration 7 | { 8 | public MediaTypeConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/PlaylistConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCore.Configurations 5 | { 6 | public class PlaylistConfiguration 7 | { 8 | public PlaylistConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/PlaylistTrackConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class PlaylistTrackConfiguration 8 | { 9 | public PlaylistTrackConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasKey(e => new {e.PlaylistId, e.TrackId}) 12 | .HasName("PK__Playlist__A4A6282E25869641"); 13 | 14 | entity.HasIndex(e => e.PlaylistId) 15 | .HasName("IPK_PlaylistTrack"); 16 | 17 | entity.HasIndex(e => e.TrackId) 18 | .HasName("IFK_Track_PlaylistTrack"); 19 | 20 | entity.HasOne(d => d.Playlist) 21 | .WithMany(p => p.PlaylistTracks) 22 | .HasForeignKey(d => d.PlaylistId) 23 | .OnDelete(DeleteBehavior.Restrict) 24 | .HasConstraintName("FK__PlaylistT__Playl__30F848ED"); 25 | 26 | entity.HasOne(d => d.Track) 27 | .WithMany(p => p.PlaylistTracks) 28 | .HasForeignKey(d => d.TrackId) 29 | .OnDelete(DeleteBehavior.Restrict) 30 | .HasConstraintName("FK__PlaylistT__Track__300424B4"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Configurations/TrackConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCore.Configurations 6 | { 7 | public class TrackConfiguration 8 | { 9 | public TrackConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.AlbumId) 12 | .HasName("IFK_Album_Track"); 13 | 14 | entity.HasIndex(e => e.GenreId) 15 | .HasName("IFK_Genre_Track"); 16 | 17 | entity.HasIndex(e => e.MediaTypeId) 18 | .HasName("IFK_MediaType_Track"); 19 | 20 | entity.Property(e => e.Composer).HasMaxLength(220); 21 | 22 | entity.Property(e => e.Name) 23 | .IsRequired() 24 | .HasMaxLength(200); 25 | 26 | entity.Property(e => e.UnitPrice).HasColumnType("numeric"); 27 | 28 | entity.HasOne(d => d.Album) 29 | .WithMany(p => p.Tracks) 30 | .HasForeignKey(d => d.AlbumId) 31 | .HasConstraintName("FK__Track__AlbumId__286302EC"); 32 | 33 | entity.HasOne(d => d.Genre) 34 | .WithMany(p => p.Tracks) 35 | .HasForeignKey(d => d.GenreId) 36 | .HasConstraintName("FK__Track__GenreId__2A4B4B5E"); 37 | 38 | entity.HasOne(d => d.MediaType) 39 | .WithMany(p => p.Tracks) 40 | .HasForeignKey(d => d.MediaTypeId) 41 | .OnDelete(DeleteBehavior.Restrict) 42 | .HasConstraintName("FK__Track__MediaType__29572725"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/AlbumRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Repositories; 7 | using Chinook.Domain.Entities; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | public class AlbumRepository : IAlbumRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public AlbumRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task AlbumExists(int id, CancellationToken ct = default) => 21 | await _context.Album.AnyAsync(a => a.AlbumId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) => 26 | await _context.Album.AsNoTracking().ToListAsync(ct); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var dbAlbum = await _context.Album.FindAsync(id); 31 | return dbAlbum; 32 | } 33 | 34 | public async Task AddAsync(Album newAlbum, CancellationToken ct = default) 35 | { 36 | _context.Album.Add(newAlbum); 37 | await _context.SaveChangesAsync(ct); 38 | return newAlbum; 39 | } 40 | 41 | public async Task UpdateAsync(Album album, CancellationToken ct = default) 42 | { 43 | if (!await AlbumExists(album.AlbumId, ct)) 44 | return false; 45 | _context.Album.Update(album); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await AlbumExists(id, ct)) 53 | return false; 54 | var toRemove = _context.Album.Find(id); 55 | _context.Album.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | 60 | public async Task> GetByArtistIdAsync(int id, CancellationToken ct = default) => 61 | await _context.Album.Where(a => a.ArtistId == id).ToListAsync(ct); 62 | } 63 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/ArtistRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Microsoft.EntityFrameworkCore; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | 8 | namespace Chinook.DataEFCore.Repositories 9 | { 10 | public class ArtistRepository : IArtistRepository 11 | { 12 | private readonly ChinookContext _context; 13 | 14 | public ArtistRepository(ChinookContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | private async Task ArtistExists(int id, CancellationToken ct = default) => 20 | await _context.Artist.AnyAsync(a => a.ArtistId == id, ct); 21 | 22 | public void Dispose() => _context.Dispose(); 23 | 24 | public async Task> GetAllAsync(CancellationToken ct = default) => 25 | await _context.Artist.AsNoTracking().ToListAsync(ct); 26 | 27 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 28 | await _context.Artist.FindAsync(id); 29 | 30 | public async Task AddAsync(Artist newArtist, CancellationToken ct = default) 31 | { 32 | _context.Artist.Add(newArtist); 33 | await _context.SaveChangesAsync(ct); 34 | return newArtist; 35 | } 36 | 37 | public async Task UpdateAsync(Artist artist, CancellationToken ct = default) 38 | { 39 | if (!await ArtistExists(artist.ArtistId, ct)) 40 | return false; 41 | _context.Artist.Update(artist); 42 | await _context.SaveChangesAsync(ct); 43 | return true; 44 | } 45 | 46 | public async Task DeleteAsync(int id, CancellationToken ct = default) 47 | { 48 | if (!await ArtistExists(id, ct)) 49 | return false; 50 | var toRemove = _context.Artist.Find(id); 51 | _context.Artist.Remove(toRemove); 52 | await _context.SaveChangesAsync(ct); 53 | return true; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/CustomerRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Repositories; 7 | using Chinook.Domain.Entities; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | public class CustomerRepository : ICustomerRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public CustomerRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task CustomerExists(int id, CancellationToken ct = default) => 21 | await _context.Customer.AnyAsync(c => c.CustomerId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) => 26 | await _context.Customer.AsNoTracking().ToListAsync(ct); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 29 | await _context.Customer.FindAsync(id); 30 | 31 | public async Task AddAsync(Customer newCustomer, CancellationToken ct = default) 32 | { 33 | _context.Customer.Add(newCustomer); 34 | await _context.SaveChangesAsync(ct); 35 | return newCustomer; 36 | } 37 | 38 | public async Task UpdateAsync(Customer customer, CancellationToken ct = default) 39 | { 40 | if (!await CustomerExists(customer.CustomerId, ct)) 41 | return false; 42 | _context.Customer.Update(customer); 43 | await _context.SaveChangesAsync(ct); 44 | return true; 45 | } 46 | 47 | public async Task DeleteAsync(int id, CancellationToken ct = default) 48 | { 49 | if (!await CustomerExists(id, ct)) 50 | return false; 51 | var toRemove = _context.Customer.Find(id); 52 | _context.Customer.Remove(toRemove); 53 | await _context.SaveChangesAsync(ct); 54 | return true; 55 | } 56 | 57 | public async Task> GetBySupportRepIdAsync(int id, 58 | CancellationToken ct = default) => await _context.Customer.Where(a => a.SupportRepId == id).ToListAsync(ct); 59 | } 60 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/EmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Repositories; 7 | using Chinook.Domain.Entities; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | public class EmployeeRepository : IEmployeeRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public EmployeeRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task EmployeeExists(int id, CancellationToken ct = default) => 21 | await _context.Employee.AnyAsync(e => e.EmployeeId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) => 26 | await _context.Employee.AsNoTracking().ToListAsync(ct); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 29 | await _context.Employee.FindAsync(id); 30 | 31 | public async Task AddAsync(Employee newEmployee, CancellationToken ct = default) 32 | { 33 | _context.Employee.Add(newEmployee); 34 | await _context.SaveChangesAsync(ct); 35 | return newEmployee; 36 | } 37 | 38 | public async Task UpdateAsync(Employee employee, CancellationToken ct = default) 39 | { 40 | if (!await EmployeeExists(employee.EmployeeId, ct)) 41 | return false; 42 | _context.Employee.Update(employee); 43 | await _context.SaveChangesAsync(ct); 44 | return true; 45 | } 46 | 47 | public async Task DeleteAsync(int id, CancellationToken ct = default) 48 | { 49 | if (!await EmployeeExists(id, ct)) 50 | return false; 51 | var toRemove = _context.Employee.Find(id); 52 | _context.Employee.Remove(toRemove); 53 | await _context.SaveChangesAsync(ct); 54 | return true; 55 | } 56 | 57 | public async Task GetReportsToAsync(int id, CancellationToken ct = default) => 58 | await _context.Employee.FindAsync(id); 59 | 60 | public async Task> GetDirectReportsAsync(int id, 61 | CancellationToken ct = default) => await _context.Employee.Where(e => e.ReportsTo == id).ToListAsync(ct); 62 | } 63 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/GenreRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Microsoft.EntityFrameworkCore; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | 8 | namespace Chinook.DataEFCore.Repositories 9 | { 10 | public class GenreRepository : IGenreRepository 11 | { 12 | private readonly ChinookContext _context; 13 | 14 | public GenreRepository(ChinookContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | private async Task GenreExists(int id, CancellationToken ct = default) => 20 | await _context.Genre.AnyAsync(g => g.GenreId == id, ct); 21 | 22 | public void Dispose() => _context.Dispose(); 23 | 24 | public async Task> GetAllAsync(CancellationToken ct = default) => 25 | await _context.Genre.AsNoTracking().ToListAsync(ct); 26 | 27 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 28 | { 29 | var dbGenre = await _context.Genre.FindAsync(id); 30 | return dbGenre; 31 | } 32 | 33 | public async Task AddAsync(Genre newGenre, CancellationToken ct = default) 34 | { 35 | _context.Genre.Add(newGenre); 36 | await _context.SaveChangesAsync(ct); 37 | return newGenre; 38 | } 39 | 40 | public async Task UpdateAsync(Genre genre, CancellationToken ct = default) 41 | { 42 | if (!await GenreExists(genre.GenreId, ct)) 43 | return false; 44 | _context.Genre.Update(genre); 45 | await _context.SaveChangesAsync(ct); 46 | return true; 47 | } 48 | 49 | public async Task DeleteAsync(int id, CancellationToken ct = default) 50 | { 51 | if (!await GenreExists(id, ct)) 52 | return false; 53 | var toRemove = _context.Genre.Find(id); 54 | _context.Genre.Remove(toRemove); 55 | await _context.SaveChangesAsync(ct); 56 | return true; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/InvoiceLineRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Repositories; 7 | using Chinook.Domain.Entities; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | public class InvoiceLineRepository : IInvoiceLineRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public InvoiceLineRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task InvoiceLineExists(int id, CancellationToken ct = default) => 21 | await _context.InvoiceLine.AnyAsync(i => i.InvoiceLineId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) => 26 | await _context.InvoiceLine.AsNoTracking().ToListAsync(ct); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 29 | await _context.InvoiceLine.FindAsync(id); 30 | 31 | public async Task AddAsync(InvoiceLine newInvoiceLine, 32 | CancellationToken ct = default) 33 | { 34 | _context.InvoiceLine.Add(newInvoiceLine); 35 | await _context.SaveChangesAsync(ct); 36 | return newInvoiceLine; 37 | } 38 | 39 | public async Task UpdateAsync(InvoiceLine invoiceLine, CancellationToken ct = default) 40 | { 41 | if (!await InvoiceLineExists(invoiceLine.InvoiceLineId, ct)) 42 | return false; 43 | _context.InvoiceLine.Update(invoiceLine); 44 | await _context.SaveChangesAsync(ct); 45 | return true; 46 | } 47 | 48 | public async Task DeleteAsync(int id, CancellationToken ct = default) 49 | { 50 | if (!await InvoiceLineExists(id, ct)) 51 | return false; 52 | var toRemove = _context.InvoiceLine.Find(id); 53 | _context.InvoiceLine.Remove(toRemove); 54 | await _context.SaveChangesAsync(ct); 55 | return true; 56 | } 57 | 58 | public async Task> GetByInvoiceIdAsync(int id, 59 | CancellationToken ct = default) => await _context.InvoiceLine.Where(a => a.InvoiceId == id).ToListAsync(ct); 60 | 61 | public async Task> GetByTrackIdAsync(int id, 62 | CancellationToken ct = default) => await _context.InvoiceLine.Where(a => a.TrackId == id).ToListAsync(ct); 63 | } 64 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/InvoiceRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Entities; 7 | using Chinook.Domain.Repositories; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | /// 12 | /// The invoice repository. 13 | /// 14 | public class InvoiceRepository : IInvoiceRepository 15 | { 16 | /// 17 | /// The _context. 18 | /// 19 | private readonly ChinookContext _context; 20 | 21 | public InvoiceRepository(ChinookContext context) 22 | { 23 | _context = context; 24 | } 25 | 26 | private async Task InvoiceExists(int id, CancellationToken ct = default) => 27 | await _context.Invoice.AnyAsync(i => i.InvoiceId == id, ct); 28 | 29 | public void Dispose() => _context.Dispose(); 30 | 31 | public async Task> GetAllAsync(CancellationToken ct = default) => 32 | await _context.Invoice.AsNoTracking().ToListAsync(ct); 33 | 34 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 35 | await _context.Invoice.FindAsync(id); 36 | 37 | public async Task AddAsync(Invoice newInvoice, CancellationToken ct = default) 38 | { 39 | _context.Invoice.Add(newInvoice); 40 | await _context.SaveChangesAsync(ct); 41 | return newInvoice; 42 | } 43 | 44 | public async Task UpdateAsync(Invoice invoice, CancellationToken ct = default) 45 | { 46 | if (!await InvoiceExists(invoice.InvoiceId, ct)) 47 | return false; 48 | _context.Invoice.Update(invoice); 49 | await _context.SaveChangesAsync(ct); 50 | return true; 51 | } 52 | 53 | public async Task DeleteAsync(int id, CancellationToken ct = default) 54 | { 55 | if (!await InvoiceExists(id, ct)) 56 | return false; 57 | var toRemove = _context.Invoice.Find(id); 58 | _context.Invoice.Remove(toRemove); 59 | await _context.SaveChangesAsync(ct); 60 | return true; 61 | } 62 | 63 | public async Task> GetByCustomerIdAsync(int id, CancellationToken ct = default) => 64 | await _context.Invoice.Where(a => a.InvoiceId == id).ToListAsync(ct); 65 | } 66 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/MediaTypeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Microsoft.EntityFrameworkCore; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | 8 | namespace Chinook.DataEFCore.Repositories 9 | { 10 | public class MediaTypeRepository : IMediaTypeRepository 11 | { 12 | private readonly ChinookContext _context; 13 | 14 | public MediaTypeRepository(ChinookContext context) 15 | { 16 | _context = context; 17 | } 18 | 19 | private async Task MediaTypeExists(int id, CancellationToken ct = default) => 20 | await _context.MediaType.AnyAsync(i => i.MediaTypeId == id, ct); 21 | 22 | public void Dispose() => _context.Dispose(); 23 | 24 | public async Task> GetAllAsync(CancellationToken ct = default) => 25 | await _context.MediaType.AsNoTracking().ToListAsync(ct); 26 | 27 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 28 | await _context.MediaType.FindAsync(id); 29 | 30 | public async Task AddAsync(MediaType newMediaType, CancellationToken ct = default) 31 | { 32 | _context.MediaType.Add(newMediaType); 33 | await _context.SaveChangesAsync(ct); 34 | return newMediaType; 35 | } 36 | 37 | public async Task UpdateAsync(MediaType mediaType, CancellationToken ct = default) 38 | { 39 | if (!await MediaTypeExists(mediaType.MediaTypeId, ct)) 40 | return false; 41 | _context.MediaType.Update(mediaType); 42 | await _context.SaveChangesAsync(ct); 43 | return true; 44 | } 45 | 46 | public async Task DeleteAsync(int id, CancellationToken ct = default) 47 | { 48 | if (!await MediaTypeExists(id, ct)) 49 | return false; 50 | var toRemove = _context.MediaType.Find(id); 51 | _context.MediaType.Remove(toRemove); 52 | await _context.SaveChangesAsync(ct); 53 | return true; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/PlaylistRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Repositories; 7 | using Chinook.Domain.Entities; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | public class PlaylistRepository : IPlaylistRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public PlaylistRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task PlaylistExists(int id, CancellationToken ct = default) => 21 | await _context.Playlist.AnyAsync(i => i.PlaylistId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) => 26 | await _context.Playlist.AsNoTracking().ToListAsync(ct); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 29 | await _context.Playlist.FindAsync(id); 30 | 31 | public async Task> GetTrackByPlaylistIdAsync(int id, 32 | CancellationToken ct = default) 33 | { 34 | IList list = new List(); 35 | var playlistTracks = _context.PlaylistTrack.Where(p => p.PlaylistId == id); 36 | foreach (var playlistTrack in playlistTracks) 37 | { 38 | var track = await _context.Track.FindAsync(playlistTrack.TrackId); 39 | list.Add(track); 40 | } 41 | 42 | return list.ToList(); 43 | } 44 | 45 | public async Task AddAsync(Playlist newPlaylist, CancellationToken ct = default) 46 | { 47 | _context.Playlist.Add(newPlaylist); 48 | await _context.SaveChangesAsync(ct); 49 | return newPlaylist; 50 | } 51 | 52 | public async Task UpdateAsync(Playlist playlist, CancellationToken ct = default) 53 | { 54 | if (!await PlaylistExists(playlist.PlaylistId, ct)) 55 | return false; 56 | _context.Playlist.Update(playlist); 57 | await _context.SaveChangesAsync(ct); 58 | return true; 59 | } 60 | 61 | public async Task DeleteAsync(int id, CancellationToken ct = default) 62 | { 63 | if (!await PlaylistExists(id, ct)) 64 | return false; 65 | var toRemove = _context.Playlist.Find(id); 66 | _context.Playlist.Remove(toRemove); 67 | await _context.SaveChangesAsync(ct); 68 | return true; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/PlaylistTrackRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using System.Threading; 5 | using System.Collections.Generic; 6 | using Microsoft.EntityFrameworkCore; 7 | using Chinook.Domain.Repositories; 8 | using Chinook.Domain.Entities; 9 | 10 | namespace Chinook.DataEFCore.Repositories 11 | { 12 | public class PlaylistTrackRepository : IPlaylistTrackRepository 13 | { 14 | private readonly ChinookContext _context; 15 | 16 | public PlaylistTrackRepository(ChinookContext context) 17 | { 18 | _context = context ?? throw new ArgumentNullException(nameof(context)); 19 | } 20 | 21 | private async Task PlaylistTrackExists(int id, CancellationToken ct = default) => 22 | await _context.PlaylistTrack.AnyAsync(pt => pt.PlaylistId == id, ct); 23 | 24 | public void Dispose() => _context.Dispose(); 25 | 26 | public async Task> GetAllAsync(CancellationToken ct = default) => 27 | await _context.PlaylistTrack.AsNoTracking().ToListAsync(ct); 28 | 29 | public async Task> GetByPlaylistIdAsync(int id, 30 | CancellationToken ct = default) => 31 | await _context.PlaylistTrack.Where(a => a.PlaylistId == id).ToListAsync(ct); 32 | 33 | public async Task> GetByTrackIdAsync(int id, 34 | CancellationToken ct = default) => await _context.PlaylistTrack.Where(a => a.TrackId == id).ToListAsync(ct); 35 | 36 | public async Task AddAsync(PlaylistTrack newPlaylistTrack, 37 | CancellationToken ct = default) 38 | { 39 | _context.PlaylistTrack.Add(newPlaylistTrack); 40 | await _context.SaveChangesAsync(ct); 41 | return newPlaylistTrack; 42 | } 43 | 44 | public async Task UpdateAsync(PlaylistTrack playlistTrack, 45 | CancellationToken ct = default) 46 | { 47 | if (!await PlaylistTrackExists(playlistTrack.PlaylistId, ct)) 48 | return false; 49 | _context.PlaylistTrack.Update(playlistTrack); 50 | await _context.SaveChangesAsync(ct); 51 | return true; 52 | } 53 | 54 | public async Task DeleteAsync(int id, CancellationToken ct = default) 55 | { 56 | if (!await PlaylistTrackExists(id, ct)) 57 | return false; 58 | var toRemove = _context.PlaylistTrack.Find(id); 59 | _context.PlaylistTrack.Remove(toRemove); 60 | await _context.SaveChangesAsync(ct); 61 | return true; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCore/Repositories/TrackRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Microsoft.EntityFrameworkCore; 6 | using Chinook.Domain.Repositories; 7 | using Chinook.Domain.Entities; 8 | 9 | namespace Chinook.DataEFCore.Repositories 10 | { 11 | public class TrackRepository : ITrackRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public TrackRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task TrackExists(int id, CancellationToken ct = default) => 21 | await _context.Track.AnyAsync(i => i.TrackId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) => 26 | await _context.Track.AsNoTracking().ToListAsync(ct); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) => 29 | await _context.Track.FindAsync(id); 30 | 31 | public async Task AddAsync(Track newTrack, CancellationToken ct = default) 32 | { 33 | _context.Track.Add(newTrack); 34 | await _context.SaveChangesAsync(ct); 35 | return newTrack; 36 | } 37 | 38 | public async Task UpdateAsync(Track track, CancellationToken ct = default) 39 | { 40 | if (!await TrackExists(track.TrackId, ct)) 41 | return false; 42 | _context.Track.Update(track); 43 | await _context.SaveChangesAsync(ct); 44 | return true; 45 | } 46 | 47 | public async Task DeleteAsync(int id, CancellationToken ct = default) 48 | { 49 | if (!await TrackExists(id, ct)) 50 | return false; 51 | var toRemove = _context.Track.Find(id); 52 | _context.Track.Remove(toRemove); 53 | await _context.SaveChangesAsync(ct); 54 | return true; 55 | } 56 | 57 | public async Task> GetByAlbumIdAsync(int id, CancellationToken ct = default) => 58 | await _context.Track.Where(a => a.AlbumId == id).ToListAsync(ct); 59 | 60 | public async Task> GetByGenreIdAsync(int id, CancellationToken ct = default) => 61 | await _context.Track.Where(a => a.GenreId == id).ToListAsync(ct); 62 | 63 | public async Task> GetByMediaTypeIdAsync(int id, CancellationToken ct = default) => 64 | await _context.Track.Where(a => a.MediaTypeId == id).ToListAsync(ct); 65 | } 66 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Chinook.DataEFCoreCmpldQry.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | latest 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/AlbumConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class AlbumConfiguration 8 | { 9 | public AlbumConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.ArtistId) 12 | .HasName("IFK_Artist_Album"); 13 | 14 | entity.Property(e => e.Title) 15 | .IsRequired() 16 | .HasMaxLength(160); 17 | 18 | entity.HasOne(d => d.Artist) 19 | .WithMany(p => p.Albums) 20 | .HasForeignKey(d => d.ArtistId) 21 | .OnDelete(DeleteBehavior.Restrict) 22 | .HasConstraintName("FK__Album__ArtistId__276EDEB3"); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/ArtistConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCoreCmpldQry.Configurations 5 | { 6 | public class ArtistConfiguration 7 | { 8 | public ArtistConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/CustomerConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class CustomerConfiguration 8 | { 9 | public CustomerConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.SupportRepId) 12 | .HasName("IFK_Employee_Customer"); 13 | 14 | entity.Property(e => e.Address).HasMaxLength(70); 15 | 16 | entity.Property(e => e.City).HasMaxLength(40); 17 | 18 | entity.Property(e => e.Company).HasMaxLength(80); 19 | 20 | entity.Property(e => e.Country).HasMaxLength(40); 21 | 22 | entity.Property(e => e.Email) 23 | .IsRequired() 24 | .HasMaxLength(60); 25 | 26 | entity.Property(e => e.Fax).HasMaxLength(24); 27 | 28 | entity.Property(e => e.FirstName) 29 | .IsRequired() 30 | .HasMaxLength(40); 31 | 32 | entity.Property(e => e.LastName) 33 | .IsRequired() 34 | .HasMaxLength(20); 35 | 36 | entity.Property(e => e.Phone).HasMaxLength(24); 37 | 38 | entity.Property(e => e.PostalCode).HasMaxLength(10); 39 | 40 | entity.Property(e => e.State).HasMaxLength(40); 41 | 42 | entity.HasOne(d => d.SupportRep) 43 | .WithMany(p => p.Customers) 44 | .HasForeignKey(d => d.SupportRepId) 45 | .HasConstraintName("FK__Customer__Suppor__2C3393D0"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/EmployeeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class EmployeeConfiguration 8 | { 9 | public EmployeeConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.ReportsTo) 12 | .HasName("IFK_Employee_ReportsTo"); 13 | 14 | entity.Property(e => e.Address).HasMaxLength(70); 15 | 16 | entity.Property(e => e.BirthDate).HasColumnType("datetime"); 17 | 18 | entity.Property(e => e.City).HasMaxLength(40); 19 | 20 | entity.Property(e => e.Country).HasMaxLength(40); 21 | 22 | entity.Property(e => e.Email).HasMaxLength(60); 23 | 24 | entity.Property(e => e.Fax).HasMaxLength(24); 25 | 26 | entity.Property(e => e.FirstName) 27 | .IsRequired() 28 | .HasMaxLength(20); 29 | 30 | entity.Property(e => e.HireDate).HasColumnType("datetime"); 31 | 32 | entity.Property(e => e.LastName) 33 | .IsRequired() 34 | .HasMaxLength(20); 35 | 36 | entity.Property(e => e.Phone).HasMaxLength(24); 37 | 38 | entity.Property(e => e.PostalCode).HasMaxLength(10); 39 | 40 | entity.Property(e => e.State).HasMaxLength(40); 41 | 42 | entity.Property(e => e.Title).HasMaxLength(30); 43 | 44 | entity.HasOne(d => d.Manager) 45 | .WithMany(p => p.DirectReports) 46 | .HasForeignKey(d => d.ReportsTo) 47 | .HasConstraintName("FK__Employee__Report__2B3F6F97"); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/GenreConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCoreCmpldQry.Configurations 5 | { 6 | public class GenreConfiguration 7 | { 8 | public GenreConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/InvoiceConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class InvoiceConfiguration 8 | { 9 | public InvoiceConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.CustomerId) 12 | .HasName("IFK_Customer_Invoice"); 13 | 14 | entity.Property(e => e.BillingAddress).HasMaxLength(70); 15 | 16 | entity.Property(e => e.BillingCity).HasMaxLength(40); 17 | 18 | entity.Property(e => e.BillingCountry).HasMaxLength(40); 19 | 20 | entity.Property(e => e.BillingPostalCode).HasMaxLength(10); 21 | 22 | entity.Property(e => e.BillingState).HasMaxLength(40); 23 | 24 | entity.Property(e => e.InvoiceDate).HasColumnType("datetime"); 25 | 26 | entity.Property(e => e.Total).HasColumnType("numeric"); 27 | 28 | entity.HasOne(d => d.Customer) 29 | .WithMany(p => p.Invoices) 30 | .HasForeignKey(d => d.CustomerId) 31 | .OnDelete(DeleteBehavior.Restrict) 32 | .HasConstraintName("FK__Invoice__Custome__2D27B809"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/InvoiceLineConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class InvoiceLineConfiguration 8 | { 9 | public InvoiceLineConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.InvoiceId) 12 | .HasName("IFK_Invoice_InvoiceLine"); 13 | 14 | entity.HasIndex(e => e.TrackId) 15 | .HasName("IFK_ProductItem_InvoiceLine"); 16 | 17 | entity.Property(e => e.UnitPrice).HasColumnType("numeric"); 18 | 19 | entity.HasOne(d => d.Invoice) 20 | .WithMany(p => p.InvoiceLines) 21 | .HasForeignKey(d => d.InvoiceId) 22 | .OnDelete(DeleteBehavior.Restrict) 23 | .HasConstraintName("FK__InvoiceLi__Invoi__2F10007B"); 24 | 25 | entity.HasOne(d => d.Track) 26 | .WithMany(p => p.InvoiceLines) 27 | .HasForeignKey(d => d.TrackId) 28 | .OnDelete(DeleteBehavior.Restrict) 29 | .HasConstraintName("FK__InvoiceLi__Track__2E1BDC42"); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/MediaTypeConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCoreCmpldQry.Configurations 5 | { 6 | public class MediaTypeConfiguration 7 | { 8 | public MediaTypeConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/PlaylistConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Chinook.DataEFCoreCmpldQry.Configurations 5 | { 6 | public class PlaylistConfiguration 7 | { 8 | public PlaylistConfiguration(EntityTypeBuilder entity) 9 | { 10 | entity.Property(e => e.Name).HasMaxLength(120); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/PlaylistTrackConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class PlaylistTrackConfiguration 8 | { 9 | public PlaylistTrackConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasKey(e => new {e.PlaylistId, e.TrackId}) 12 | .HasName("PK__Playlist__A4A6282E25869641"); 13 | 14 | entity.HasIndex(e => e.PlaylistId) 15 | .HasName("IPK_PlaylistTrack"); 16 | 17 | entity.HasIndex(e => e.TrackId) 18 | .HasName("IFK_Track_PlaylistTrack"); 19 | 20 | entity.HasOne(d => d.Playlist) 21 | .WithMany(p => p.PlaylistTracks) 22 | .HasForeignKey(d => d.PlaylistId) 23 | .OnDelete(DeleteBehavior.Restrict) 24 | .HasConstraintName("FK__PlaylistT__Playl__30F848ED"); 25 | 26 | entity.HasOne(d => d.Track) 27 | .WithMany(p => p.PlaylistTracks) 28 | .HasForeignKey(d => d.TrackId) 29 | .OnDelete(DeleteBehavior.Restrict) 30 | .HasConstraintName("FK__PlaylistT__Track__300424B4"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Configurations/TrackConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Chinook.DataEFCoreCmpldQry.Configurations 6 | { 7 | public class TrackConfiguration 8 | { 9 | public TrackConfiguration(EntityTypeBuilder entity) 10 | { 11 | entity.HasIndex(e => e.AlbumId) 12 | .HasName("IFK_Album_Track"); 13 | 14 | entity.HasIndex(e => e.GenreId) 15 | .HasName("IFK_Genre_Track"); 16 | 17 | entity.HasIndex(e => e.MediaTypeId) 18 | .HasName("IFK_MediaType_Track"); 19 | 20 | entity.Property(e => e.Composer).HasMaxLength(220); 21 | 22 | entity.Property(e => e.Name) 23 | .IsRequired() 24 | .HasMaxLength(200); 25 | 26 | entity.Property(e => e.UnitPrice).HasColumnType("numeric"); 27 | 28 | entity.HasOne(d => d.Album) 29 | .WithMany(p => p.Tracks) 30 | .HasForeignKey(d => d.AlbumId) 31 | .HasConstraintName("FK__Track__AlbumId__286302EC"); 32 | 33 | entity.HasOne(d => d.Genre) 34 | .WithMany(p => p.Tracks) 35 | .HasForeignKey(d => d.GenreId) 36 | .HasConstraintName("FK__Track__GenreId__2A4B4B5E"); 37 | 38 | entity.HasOne(d => d.MediaType) 39 | .WithMany(p => p.Tracks) 40 | .HasForeignKey(d => d.MediaTypeId) 41 | .OnDelete(DeleteBehavior.Restrict) 42 | .HasConstraintName("FK__Track__MediaType__29572725"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/AlbumRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class AlbumRepository : IAlbumRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public AlbumRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task AlbumExists(int id, CancellationToken ct = default) => 21 | await _context.Album.AnyAsync(a => a.AlbumId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllAlbumsAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var album = await _context.GetAlbumAsync(id); 31 | return album.First(); 32 | } 33 | 34 | public async Task AddAsync(Album newAlbum, CancellationToken ct = default) 35 | { 36 | _context.Album.Add(newAlbum); 37 | await _context.SaveChangesAsync(ct); 38 | return newAlbum; 39 | } 40 | 41 | public async Task UpdateAsync(Album album, CancellationToken ct = default) 42 | { 43 | if (!await AlbumExists(album.AlbumId, ct)) 44 | return false; 45 | _context.Album.Update(album); 46 | 47 | _context.Update(album); 48 | await _context.SaveChangesAsync(ct); 49 | return true; 50 | } 51 | 52 | public async Task DeleteAsync(int id, CancellationToken ct = default) 53 | { 54 | if (!await AlbumExists(id, ct)) 55 | return false; 56 | var toRemove = _context.Album.Find(id); 57 | _context.Album.Remove(toRemove); 58 | await _context.SaveChangesAsync(ct); 59 | return true; 60 | } 61 | 62 | public async Task> GetByArtistIdAsync(int id, CancellationToken ct = default) 63 | => await _context.GetAlbumsByArtistIdAsync(id); 64 | } 65 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/ArtistRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class ArtistRepository : IArtistRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public ArtistRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task ArtistExists(int id, CancellationToken ct = default) => 21 | await _context.Artist.AnyAsync(a => a.ArtistId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllArtistsAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var artist = await _context.GetArtistAsync(id); 31 | return artist.First(); 32 | } 33 | 34 | public async Task AddAsync(Artist newArtist, CancellationToken ct = default) 35 | { 36 | _context.Artist.Add(newArtist); 37 | await _context.SaveChangesAsync(ct); 38 | return newArtist; 39 | } 40 | 41 | public async Task UpdateAsync(Artist artist, CancellationToken ct = default) 42 | { 43 | if (!await ArtistExists(artist.ArtistId, ct)) 44 | return false; 45 | _context.Artist.Update(artist); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await ArtistExists(id, ct)) 53 | return false; 54 | var toRemove = _context.Artist.Find(id); 55 | _context.Artist.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/CustomerRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class CustomerRepository : ICustomerRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public CustomerRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task CustomerExists(int id, CancellationToken ct = default) => 21 | await _context.Customer.AnyAsync(c => c.CustomerId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllCustomersAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var customer = await _context.GetCustomerAsync(id); 31 | return customer.First(); 32 | } 33 | 34 | public async Task AddAsync(Customer newCustomer, CancellationToken ct = default) 35 | { 36 | _context.Customer.Add(newCustomer); 37 | await _context.SaveChangesAsync(ct); 38 | return newCustomer; 39 | } 40 | 41 | public async Task UpdateAsync(Customer customer, CancellationToken ct = default) 42 | { 43 | if (!await CustomerExists(customer.CustomerId, ct)) 44 | return false; 45 | _context.Customer.Update(customer); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await CustomerExists(id, ct)) 53 | return false; 54 | var toRemove = _context.Customer.Find(id); 55 | _context.Customer.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | 60 | public async Task> GetBySupportRepIdAsync(int id, 61 | CancellationToken ct = default) => await _context.GetCustomerBySupportRepIdAsync(id); 62 | } 63 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/EmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class EmployeeRepository : IEmployeeRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public EmployeeRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task EmployeeExists(int id, CancellationToken ct = default) => 21 | await _context.Employee.AnyAsync(e => e.EmployeeId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllEmployeesAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var employee = await _context.GetEmployeeAsync(id); 31 | return employee.First(); 32 | } 33 | 34 | public async Task AddAsync(Employee newEmployee, CancellationToken ct = default) 35 | { 36 | _context.Employee.Add(newEmployee); 37 | await _context.SaveChangesAsync(ct); 38 | return newEmployee; 39 | } 40 | 41 | public async Task UpdateAsync(Employee employee, CancellationToken ct = default) 42 | { 43 | if (!await EmployeeExists(employee.EmployeeId, ct)) 44 | return false; 45 | _context.Employee.Update(employee); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await EmployeeExists(id, ct)) 53 | return false; 54 | var toRemove = _context.Employee.Find(id); 55 | _context.Employee.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | 60 | public async Task GetReportsToAsync(int id, CancellationToken ct = default) 61 | { 62 | var employee = await _context.GetEmployeeGetReportsToAsync(id); 63 | return employee.First(); 64 | } 65 | 66 | public async Task> GetDirectReportsAsync(int id, 67 | CancellationToken ct = default) => await _context.GetEmployeeDirectReportsAsync(id); 68 | } 69 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/GenreRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class GenreRepository : IGenreRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public GenreRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task GenreExists(int id, CancellationToken ct = default) => 21 | await _context.Genre.AnyAsync(g => g.GenreId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllGenresAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var genres = await _context.GetGenreAsync(id); 31 | return genres.FirstOrDefault(); 32 | } 33 | 34 | public async Task AddAsync(Genre newGenre, CancellationToken ct = default) 35 | { 36 | _context.Genre.Add(newGenre); 37 | await _context.SaveChangesAsync(ct); 38 | return newGenre; 39 | } 40 | 41 | public async Task UpdateAsync(Genre genre, CancellationToken ct = default) 42 | { 43 | if (!await GenreExists(genre.GenreId, ct)) 44 | return false; 45 | _context.Genre.Update(genre); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await GenreExists(id, ct)) 53 | return false; 54 | var toRemove = _context.Genre.Find(id); 55 | _context.Genre.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/InvoiceLineRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class InvoiceLineRepository : IInvoiceLineRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public InvoiceLineRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task InvoiceLineExists(int id, CancellationToken ct = default) => 21 | await _context.InvoiceLine.AnyAsync(i => i.InvoiceLineId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllInvoiceLinesAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var invoiceLine = await _context.GetInvoiceLineAsync(id); 31 | return invoiceLine.First(); 32 | } 33 | 34 | public async Task AddAsync(InvoiceLine newInvoiceLine, 35 | CancellationToken ct = default) 36 | { 37 | _context.InvoiceLine.Add(newInvoiceLine); 38 | await _context.SaveChangesAsync(ct); 39 | return newInvoiceLine; 40 | } 41 | 42 | public async Task UpdateAsync(InvoiceLine invoiceLine, CancellationToken ct = default) 43 | { 44 | if (!await InvoiceLineExists(invoiceLine.InvoiceLineId, ct)) 45 | return false; 46 | _context.InvoiceLine.Update(invoiceLine); 47 | await _context.SaveChangesAsync(ct); 48 | return true; 49 | } 50 | 51 | public async Task DeleteAsync(int id, CancellationToken ct = default) 52 | { 53 | if (!await InvoiceLineExists(id, ct)) 54 | return false; 55 | var toRemove = _context.InvoiceLine.Find(id); 56 | _context.InvoiceLine.Remove(toRemove); 57 | await _context.SaveChangesAsync(ct); 58 | return true; 59 | } 60 | 61 | public async Task> GetByInvoiceIdAsync(int id, 62 | CancellationToken ct = default) => await _context.GetInvoiceLinesByInvoiceIdAsync(id); 63 | 64 | public async Task> GetByTrackIdAsync(int id, 65 | CancellationToken ct = default) => await _context.GetInvoiceLinesByTrackIdAsync(id); 66 | } 67 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/InvoiceRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Chinook.Domain.Entities; 6 | using Chinook.Domain.Repositories; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | /// 12 | /// The invoice repository. 13 | /// 14 | public class InvoiceRepository : IInvoiceRepository 15 | { 16 | private readonly ChinookContext _context; 17 | 18 | public InvoiceRepository(ChinookContext context) 19 | { 20 | _context = context; 21 | } 22 | 23 | private async Task InvoiceExists(int id, CancellationToken ct = default) => 24 | await _context.Invoice.AnyAsync(i => i.InvoiceId == id, ct); 25 | 26 | public void Dispose() => _context.Dispose(); 27 | 28 | public async Task> GetAllAsync(CancellationToken ct = default) 29 | => await _context.GetAllInvoicesAsync(); 30 | 31 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 32 | { 33 | var invoice = await _context.GetInvoiceAsync(id); 34 | return invoice.First(); 35 | } 36 | 37 | public async Task AddAsync(Invoice newInvoice, CancellationToken ct = default) 38 | { 39 | _context.Invoice.Add(newInvoice); 40 | await _context.SaveChangesAsync(ct); 41 | return newInvoice; 42 | } 43 | 44 | public async Task UpdateAsync(Invoice invoice, CancellationToken ct = default) 45 | { 46 | if (!await InvoiceExists(invoice.InvoiceId, ct)) 47 | return false; 48 | _context.Invoice.Update(invoice); 49 | await _context.SaveChangesAsync(ct); 50 | return true; 51 | } 52 | 53 | public async Task DeleteAsync(int id, CancellationToken ct = default) 54 | { 55 | if (!await InvoiceExists(id, ct)) 56 | return false; 57 | var toRemove = _context.Invoice.Find(id); 58 | _context.Invoice.Remove(toRemove); 59 | await _context.SaveChangesAsync(ct); 60 | return true; 61 | } 62 | 63 | public async Task> GetByCustomerIdAsync(int id, CancellationToken ct = default) 64 | => await _context.GetInvoicesByCustomerIdAsync(id); 65 | } 66 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/MediaTypeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class MediaTypeRepository : IMediaTypeRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public MediaTypeRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task MediaTypeExists(int id, CancellationToken ct = default) => 21 | await _context.MediaType.AnyAsync(i => i.MediaTypeId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllMediaTypesAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var mediaType = await _context.GetMediaTypeAsync(id); 31 | return mediaType.First(); 32 | } 33 | 34 | public async Task AddAsync(MediaType newMediaType, CancellationToken ct = default) 35 | { 36 | _context.MediaType.Add(newMediaType); 37 | await _context.SaveChangesAsync(ct); 38 | return newMediaType; 39 | } 40 | 41 | public async Task UpdateAsync(MediaType mediaType, CancellationToken ct = default) 42 | { 43 | if (!await MediaTypeExists(mediaType.MediaTypeId, ct)) 44 | return false; 45 | _context.MediaType.Update(mediaType); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await MediaTypeExists(id, ct)) 53 | return false; 54 | var toRemove = _context.MediaType.Find(id); 55 | _context.MediaType.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/PlaylistRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class PlaylistRepository : IPlaylistRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public PlaylistRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task PlaylistExists(int id, CancellationToken ct = default) => 21 | await _context.Playlist.AnyAsync(i => i.PlaylistId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllPlaylistsAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var playlist = await _context.GetPlaylistAsync(id); 31 | return playlist.First(); 32 | } 33 | 34 | public async Task> GetTrackByPlaylistIdAsync(int id, 35 | CancellationToken ct = default) 36 | { 37 | IList list = new List(); 38 | var playlistTracks = _context.PlaylistTrack.Where(p => p.PlaylistId == id); 39 | foreach (var playlistTrack in playlistTracks) 40 | { 41 | var track = await _context.Track.FindAsync(playlistTrack.TrackId); 42 | list.Add(track); 43 | } 44 | 45 | return list.ToList(); 46 | } 47 | 48 | public async Task AddAsync(Playlist newPlaylist, CancellationToken ct = default) 49 | { 50 | _context.Playlist.Add(newPlaylist); 51 | await _context.SaveChangesAsync(ct); 52 | return newPlaylist; 53 | } 54 | 55 | public async Task UpdateAsync(Playlist playlist, CancellationToken ct = default) 56 | { 57 | if (!await PlaylistExists(playlist.PlaylistId, ct)) 58 | return false; 59 | _context.Playlist.Update(playlist); 60 | await _context.SaveChangesAsync(ct); 61 | return true; 62 | } 63 | 64 | public async Task DeleteAsync(int id, CancellationToken ct = default) 65 | { 66 | if (!await PlaylistExists(id, ct)) 67 | return false; 68 | var toRemove = _context.Playlist.Find(id); 69 | _context.Playlist.Remove(toRemove); 70 | await _context.SaveChangesAsync(ct); 71 | return true; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/PlaylistTrackRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class PlaylistTrackRepository : IPlaylistTrackRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public PlaylistTrackRepository(ChinookContext context) 16 | { 17 | _context = context ?? throw new ArgumentNullException(nameof(context)); 18 | } 19 | 20 | private async Task PlaylistTrackExists(int id, CancellationToken ct = default) => 21 | await _context.PlaylistTrack.AnyAsync(pt => pt.PlaylistId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllPlaylistTracksAsync(); 27 | 28 | public async Task> GetByPlaylistIdAsync(int id, 29 | CancellationToken ct = default) => await _context.GetPlaylistTrackByPlaylistId(id); 30 | 31 | public async Task> GetByTrackIdAsync(int id, 32 | CancellationToken ct = default) => await _context.GetPlaylistTracksByTrackIdAsync(id); 33 | 34 | public async Task AddAsync(PlaylistTrack newPlaylistTrack, 35 | CancellationToken ct = default) 36 | { 37 | _context.PlaylistTrack.Add(newPlaylistTrack); 38 | await _context.SaveChangesAsync(ct); 39 | return newPlaylistTrack; 40 | } 41 | 42 | public async Task UpdateAsync(PlaylistTrack playlistTrack, 43 | CancellationToken ct = default) 44 | { 45 | if (!await PlaylistTrackExists(playlistTrack.PlaylistId, ct)) 46 | return false; 47 | _context.PlaylistTrack.Update(playlistTrack); 48 | await _context.SaveChangesAsync(ct); 49 | return true; 50 | } 51 | 52 | public async Task DeleteAsync(int id, CancellationToken ct = default) 53 | { 54 | if (!await PlaylistTrackExists(id, ct)) 55 | return false; 56 | var toRemove = _context.PlaylistTrack.Find(id); 57 | _context.PlaylistTrack.Remove(toRemove); 58 | await _context.SaveChangesAsync(ct); 59 | return true; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.DataEFCoreCmpldQry/Repositories/TrackRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Threading; 4 | using System.Collections.Generic; 5 | using Chinook.Domain.Repositories; 6 | using Chinook.Domain.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace Chinook.DataEFCoreCmpldQry.Repositories 10 | { 11 | public class TrackRepository : ITrackRepository 12 | { 13 | private readonly ChinookContext _context; 14 | 15 | public TrackRepository(ChinookContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | private async Task TrackExists(int id, CancellationToken ct = default) => 21 | await _context.Track.AnyAsync(i => i.TrackId == id, ct); 22 | 23 | public void Dispose() => _context.Dispose(); 24 | 25 | public async Task> GetAllAsync(CancellationToken ct = default) 26 | => await _context.GetAllTracksAsync(); 27 | 28 | public async Task GetByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var track = await _context.GetTrackAsync(id); 31 | return track.First(); 32 | } 33 | 34 | public async Task AddAsync(Track newTrack, CancellationToken ct = default) 35 | { 36 | _context.Track.Add(newTrack); 37 | await _context.SaveChangesAsync(ct); 38 | return newTrack; 39 | } 40 | 41 | public async Task UpdateAsync(Track track, CancellationToken ct = default) 42 | { 43 | if (!await TrackExists(track.TrackId, ct)) 44 | return false; 45 | _context.Track.Update(track); 46 | await _context.SaveChangesAsync(ct); 47 | return true; 48 | } 49 | 50 | public async Task DeleteAsync(int id, CancellationToken ct = default) 51 | { 52 | if (!await TrackExists(id, ct)) 53 | return false; 54 | var toRemove = _context.Track.Find(id); 55 | _context.Track.Remove(toRemove); 56 | await _context.SaveChangesAsync(ct); 57 | return true; 58 | } 59 | 60 | public async Task> GetByAlbumIdAsync(int id, CancellationToken ct = default) 61 | => await _context.GetTracksByAlbumIdAsync(id); 62 | 63 | public async Task> GetByGenreIdAsync(int id, CancellationToken ct = default) 64 | => await _context.GetTracksByGenreIdAsync(id); 65 | 66 | public async Task> GetByMediaTypeIdAsync(int id, CancellationToken ct = default) 67 | => await _context.GetTracksByMediaTypeIdAsync(id); 68 | } 69 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/AlbumApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public class AlbumApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int AlbumId { get; set; } 16 | 17 | public string Title { get; set; } 18 | 19 | public int ArtistId { get; set; } 20 | 21 | [NotMapped] 22 | [JsonIgnore] 23 | public string ArtistName { get; set; } 24 | 25 | [NotMapped] 26 | [JsonIgnore] 27 | public ArtistApiModel Artist { get; set; } 28 | 29 | [NotMapped] 30 | [JsonIgnore] 31 | public IList Tracks { get; set; } 32 | 33 | public Album Convert() => new Album 34 | { 35 | AlbumId = AlbumId, 36 | ArtistId = ArtistId, 37 | Title = Title 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/ArtistApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public class ArtistApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int ArtistId { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | [NotMapped] 20 | [JsonIgnore] 21 | public IList Albums { get; set; } 22 | 23 | public Artist Convert() => new Artist 24 | { 25 | ArtistId = ArtistId, 26 | Name = Name 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/CustomerApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public class CustomerApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int CustomerId { get; set; } 16 | 17 | public string FirstName { get; set; } 18 | 19 | public string LastName { get; set; } 20 | public string Company { get; set; } 21 | public string Address { get; set; } 22 | public string City { get; set; } 23 | public string State { get; set; } 24 | public string Country { get; set; } 25 | public string PostalCode { get; set; } 26 | public string Phone { get; set; } 27 | public string Fax { get; set; } 28 | public string Email { get; set; } 29 | public int? SupportRepId { get; set; } 30 | public string SupportRepName { get; set; } 31 | 32 | [NotMapped] 33 | [JsonIgnore] 34 | public IList Invoices { get; set; } 35 | [NotMapped] 36 | [JsonIgnore] 37 | public EmployeeApiModel SupportRep { get; set; } 38 | 39 | public Customer Convert() => new Customer 40 | { 41 | CustomerId = CustomerId, 42 | FirstName = FirstName, 43 | LastName = LastName, 44 | Company = Company, 45 | Address = Address, 46 | City = City, 47 | State = State, 48 | Country = Country, 49 | PostalCode = PostalCode, 50 | Phone = Phone, 51 | Fax = Fax, 52 | Email = Email, 53 | SupportRepId = SupportRepId 54 | }; 55 | } 56 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/EmployeeApiModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using Chinook.Domain.Converters; 6 | using Chinook.Domain.Entities; 7 | using Newtonsoft.Json; 8 | 9 | namespace Chinook.Domain.ApiModels 10 | { 11 | public class EmployeeApiModel : IConvertModel 12 | { 13 | 14 | [Key] 15 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 16 | public int EmployeeId { get; set; } 17 | 18 | public string LastName { get; set; } 19 | 20 | public string FirstName { get; set; } 21 | public string Title { get; set; } 22 | public int? ReportsTo { get; set; } 23 | public string ReportsToName { get; set; } 24 | public DateTime? BirthDate { get; set; } 25 | public DateTime? HireDate { get; set; } 26 | public string Address { get; set; } 27 | public string City { get; set; } 28 | public string State { get; set; } 29 | public string Country { get; set; } 30 | public string PostalCode { get; set; } 31 | public string Phone { get; set; } 32 | public string Fax { get; set; } 33 | public string Email { get; set; } 34 | 35 | [NotMapped] 36 | [JsonIgnore] 37 | public List Customers { get; set; } 38 | [NotMapped] 39 | [JsonIgnore] 40 | public EmployeeApiModel Manager { get; set; } 41 | [NotMapped] 42 | [JsonIgnore] 43 | public ICollection DirectReports { get; set; } 44 | 45 | public Employee Convert() => new Employee 46 | { 47 | EmployeeId = EmployeeId, 48 | LastName = LastName, 49 | FirstName = FirstName, 50 | Title = Title, 51 | ReportsTo = ReportsTo, 52 | BirthDate = BirthDate, 53 | HireDate = HireDate, 54 | Address = Address, 55 | City = City, 56 | State = State, 57 | Country = Country, 58 | PostalCode = PostalCode, 59 | Phone = Phone, 60 | Fax = Fax, 61 | Email = Email 62 | }; 63 | } 64 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/GenreApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public class GenreApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int GenreId { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | [NotMapped] 20 | [JsonIgnore] 21 | public IList Tracks { get; set; } 22 | 23 | public Genre Convert() => new Genre 24 | { 25 | GenreId = GenreId, 26 | Name = Name 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/InvoiceApiModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using Chinook.Domain.Converters; 6 | using Chinook.Domain.Entities; 7 | using Newtonsoft.Json; 8 | 9 | namespace Chinook.Domain.ApiModels 10 | { 11 | public sealed class InvoiceApiModel : IConvertModel 12 | { 13 | 14 | [Key] 15 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 16 | public int InvoiceId { get; set; } 17 | 18 | public int CustomerId { get; set; } 19 | public string CustomerName { get; set; } 20 | 21 | public DateTime InvoiceDate { get; set; } 22 | public string BillingAddress { get; set; } 23 | public string BillingCity { get; set; } 24 | public string BillingState { get; set; } 25 | public string BillingCountry { get; set; } 26 | public string BillingPostalCode { get; set; } 27 | 28 | public decimal Total { get; set; } 29 | 30 | [NotMapped] 31 | [JsonIgnore] 32 | public IList InvoiceLines { get; set; } 33 | [NotMapped] 34 | [JsonIgnore] 35 | public CustomerApiModel Customer { get; set; } 36 | 37 | public Invoice Convert() => new Invoice 38 | { 39 | InvoiceId = InvoiceId, 40 | CustomerId = CustomerId, 41 | InvoiceDate = InvoiceDate, 42 | BillingAddress = BillingAddress, 43 | BillingCity = BillingCity, 44 | BillingState = BillingState, 45 | BillingCountry = BillingCountry, 46 | BillingPostalCode = BillingPostalCode, 47 | Total = Total 48 | }; 49 | } 50 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/InvoiceLineApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Chinook.Domain.Converters; 4 | using Chinook.Domain.Entities; 5 | using Newtonsoft.Json; 6 | 7 | namespace Chinook.Domain.ApiModels 8 | { 9 | public class InvoiceLineApiModel : IConvertModel 10 | { 11 | 12 | [Key] 13 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 14 | public int InvoiceLineId { get; set; } 15 | 16 | public int InvoiceId { get; set; } 17 | 18 | public int TrackId { get; set; } 19 | public string TrackName { get; set; } 20 | 21 | public decimal UnitPrice { get; set; } 22 | 23 | public int Quantity { get; set; } 24 | 25 | [NotMapped] 26 | [JsonIgnore] 27 | public InvoiceApiModel Invoice { get; set; } 28 | [NotMapped] 29 | [JsonIgnore] 30 | public TrackApiModel Track { get; set; } 31 | 32 | public InvoiceLine Convert() => new InvoiceLine 33 | { 34 | InvoiceLineId = InvoiceLineId, 35 | InvoiceId = InvoiceId, 36 | TrackId = TrackId, 37 | UnitPrice = UnitPrice, 38 | Quantity = Quantity 39 | }; 40 | } 41 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/MediaTypeApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public class MediaTypeApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int MediaTypeId { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | [NotMapped] 20 | [JsonIgnore] 21 | public IList Tracks { get; set; } 22 | 23 | public MediaType Convert() => new MediaType 24 | { 25 | MediaTypeId = MediaTypeId, 26 | Name = Name 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/PlaylistApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public class PlaylistApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int PlaylistId { get; set; } 16 | 17 | public string Name { get; set; } 18 | [NotMapped] 19 | [JsonIgnore] 20 | public IList Tracks { get; set; } 21 | [NotMapped] 22 | [JsonIgnore] 23 | public IList PlaylistTracks { get; set; } 24 | 25 | public Playlist Convert() => new Playlist 26 | { 27 | PlaylistId = PlaylistId, 28 | Name = Name 29 | }; 30 | } 31 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/PlaylistTrackApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Chinook.Domain.Converters; 4 | using Chinook.Domain.Entities; 5 | using Newtonsoft.Json; 6 | 7 | namespace Chinook.Domain.ApiModels 8 | { 9 | public class PlaylistTrackApiModel : IConvertModel 10 | { 11 | 12 | public int PlaylistId { get; set; } 13 | 14 | public int TrackId { get; set; } 15 | 16 | [NotMapped] 17 | [JsonIgnore] 18 | public PlaylistApiModel Playlist { get; set; } 19 | [NotMapped] 20 | [JsonIgnore] 21 | public TrackApiModel Track { get; set; } 22 | 23 | public PlaylistTrack Convert() => new PlaylistTrack 24 | { 25 | PlaylistId = PlaylistId, 26 | TrackId = TrackId 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/ApiModels/TrackApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Chinook.Domain.Converters; 5 | using Chinook.Domain.Entities; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.ApiModels 9 | { 10 | public sealed class TrackApiModel : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int TrackId { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | public int AlbumId { get; set; } 20 | public string AlbumName { get; set; } 21 | public int MediaTypeId { get; set; } 22 | public string MediaTypeName { get; set; } 23 | public int? GenreId { get; set; } 24 | public string GenreName { get; set; } 25 | public string Composer { get; set; } 26 | public int Milliseconds { get; set; } 27 | public int Bytes { get; set; } 28 | public decimal UnitPrice { get; set; } 29 | 30 | [NotMapped] 31 | [JsonIgnore] 32 | public IList InvoiceLines { get; set; } 33 | 34 | [NotMapped] 35 | [JsonIgnore] 36 | public IList PlaylistTracks { get; set; } 37 | 38 | [NotMapped] 39 | [JsonIgnore] 40 | public AlbumApiModel Album { get; set; } 41 | 42 | [NotMapped] 43 | [JsonIgnore] 44 | public GenreApiModel Genre { get; set; } 45 | 46 | [NotMapped] 47 | [JsonIgnore] 48 | public MediaTypeApiModel MediaType { get; set; } 49 | 50 | public Track Convert() => new Track 51 | { 52 | TrackId = TrackId, 53 | Name = Name, 54 | AlbumId = AlbumId, 55 | MediaTypeId = MediaTypeId, 56 | GenreId = GenreId, 57 | Composer = Composer, 58 | Milliseconds = Milliseconds, 59 | Bytes = Bytes, 60 | UnitPrice = UnitPrice 61 | }; 62 | } 63 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Chinook.Domain.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | latest 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Converters/IConvertModel.cs: -------------------------------------------------------------------------------- 1 | namespace Chinook.Domain.Converters 2 | { 3 | public interface IConvertModel 4 | { 5 | TTarget Convert(); 6 | } 7 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Album.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public sealed class Album : IConvertModel 11 | { 12 | private Artist _artist; 13 | 14 | 15 | [Key] 16 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 17 | public int AlbumId { get; set; } 18 | 19 | 20 | public string Title { get; set; } 21 | 22 | public int ArtistId { get; set; } 23 | 24 | [NotMapped] 25 | [JsonIgnore] 26 | public ICollection Tracks { get; set; } = new HashSet(); 27 | 28 | [NotMapped] 29 | [JsonIgnore] 30 | public Artist Artist 31 | { 32 | get => _artist; 33 | set => _artist = value; 34 | } 35 | 36 | public AlbumApiModel Convert() => new AlbumApiModel 37 | { 38 | AlbumId = AlbumId, 39 | ArtistId = ArtistId, 40 | Title = Title 41 | }; 42 | } 43 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Artist.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public class Artist : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int ArtistId { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | [NotMapped] 20 | [JsonIgnore] 21 | public ICollection Albums { get; set; } = new HashSet(); 22 | 23 | public ArtistApiModel Convert() => new ArtistApiModel 24 | { 25 | ArtistId = ArtistId, 26 | Name = Name 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Customer.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public class Customer : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int CustomerId { get; set; } 16 | 17 | public string FirstName { get; set; } 18 | 19 | public string LastName { get; set; } 20 | public string Company { get; set; } 21 | public string Address { get; set; } 22 | public string City { get; set; } 23 | public string State { get; set; } 24 | public string Country { get; set; } 25 | public string PostalCode { get; set; } 26 | public string Phone { get; set; } 27 | public string Fax { get; set; } 28 | public string Email { get; set; } 29 | public int? SupportRepId { get; set; } 30 | 31 | [NotMapped] 32 | [JsonIgnore] 33 | public ICollection Invoices { get; set; } = new HashSet(); 34 | [NotMapped] 35 | [JsonIgnore] 36 | public Employee SupportRep { get; set; } 37 | 38 | public CustomerApiModel Convert() => new CustomerApiModel 39 | { 40 | CustomerId = CustomerId, 41 | FirstName = FirstName, 42 | LastName = LastName, 43 | Company = Company, 44 | Address = Address, 45 | City = City, 46 | State = State, 47 | Country = Country, 48 | PostalCode = PostalCode, 49 | Phone = Phone, 50 | Fax = Fax, 51 | Email = Email, 52 | SupportRepId = SupportRepId 53 | }; 54 | } 55 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Employee.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using System.ComponentModel.DataAnnotations.Schema; 7 | using Newtonsoft.Json; 8 | 9 | namespace Chinook.Domain.Entities 10 | { 11 | public class Employee : IConvertModel 12 | { 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int EmployeeId { get; set; } 16 | 17 | public string LastName { get; set; } 18 | 19 | public string FirstName { get; set; } 20 | public string Title { get; set; } 21 | public int? ReportsTo { get; set; } 22 | public DateTime? BirthDate { get; set; } 23 | public DateTime? HireDate { get; set; } 24 | public string Address { get; set; } 25 | public string City { get; set; } 26 | public string State { get; set; } 27 | public string Country { get; set; } 28 | public string PostalCode { get; set; } 29 | public string Phone { get; set; } 30 | public string Fax { get; set; } 31 | public string Email { get; set; } 32 | 33 | [NotMapped] 34 | [JsonIgnore] 35 | public ICollection Customers { get; set; } = new HashSet(); 36 | [NotMapped] 37 | [JsonIgnore] 38 | public Employee Manager { get; set; } 39 | [NotMapped] 40 | [JsonIgnore] 41 | public ICollection DirectReports { get; set; } = new HashSet(); 42 | 43 | public EmployeeApiModel Convert() => new EmployeeApiModel 44 | { 45 | EmployeeId = EmployeeId, 46 | LastName = LastName, 47 | FirstName = FirstName, 48 | Title = Title, 49 | ReportsTo = ReportsTo, 50 | BirthDate = BirthDate, 51 | HireDate = HireDate, 52 | Address = Address, 53 | City = City, 54 | State = State, 55 | Country = Country, 56 | PostalCode = PostalCode, 57 | Phone = Phone, 58 | Fax = Fax, 59 | Email = Email 60 | }; 61 | } 62 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Genre.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public class Genre : IConvertModel 11 | { 12 | 13 | [Key] 14 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 15 | public int GenreId { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | [NotMapped] 20 | [JsonIgnore] 21 | public ICollection Tracks { get; set; } = new HashSet(); 22 | 23 | public GenreApiModel Convert() => new GenreApiModel 24 | { 25 | GenreId = GenreId, 26 | Name = Name 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Invoice.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using System.ComponentModel.DataAnnotations.Schema; 7 | using Newtonsoft.Json; 8 | 9 | namespace Chinook.Domain.Entities 10 | { 11 | public class Invoice : IConvertModel 12 | { 13 | private Customer _customer; 14 | 15 | [Key] 16 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 17 | public int InvoiceId { get; set; } 18 | 19 | public int CustomerId { get; set; } 20 | 21 | public DateTime InvoiceDate { get; set; } 22 | public string BillingAddress { get; set; } 23 | public string BillingCity { get; set; } 24 | public string BillingState { get; set; } 25 | public string BillingCountry { get; set; } 26 | public string BillingPostalCode { get; set; } 27 | 28 | public decimal Total { get; set; } 29 | 30 | [NotMapped] 31 | [JsonIgnore] 32 | public ICollection InvoiceLines { get; set; } = new HashSet(); 33 | 34 | [NotMapped] 35 | [JsonIgnore] 36 | public Customer Customer 37 | { 38 | get => _customer; 39 | set => _customer = value; 40 | } 41 | 42 | public InvoiceApiModel Convert() => new InvoiceApiModel 43 | { 44 | InvoiceId = InvoiceId, 45 | CustomerId = CustomerId, 46 | InvoiceDate = InvoiceDate, 47 | BillingAddress = BillingAddress, 48 | BillingCity = BillingCity, 49 | BillingState = BillingState, 50 | BillingCountry = BillingCountry, 51 | BillingPostalCode = BillingPostalCode, 52 | Total = Total, 53 | CustomerName = $"{Customer.FirstName} {Customer.LastName}" 54 | }; 55 | } 56 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/InvoiceLine.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Chinook.Domain.Converters; 4 | using Chinook.Domain.ApiModels; 5 | using Newtonsoft.Json; 6 | 7 | namespace Chinook.Domain.Entities 8 | { 9 | public class InvoiceLine : IConvertModel 10 | { 11 | [Key] 12 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 13 | public int InvoiceLineId { get; set; } 14 | 15 | public int InvoiceId { get; set; } 16 | 17 | public int TrackId { get; set; } 18 | 19 | public decimal UnitPrice { get; set; } 20 | 21 | public int Quantity { get; set; } 22 | 23 | [NotMapped] 24 | [JsonIgnore] 25 | public Invoice Invoice { get; set; } 26 | [NotMapped] 27 | [JsonIgnore] 28 | public Track Track { get; set; } 29 | 30 | public InvoiceLineApiModel Convert() => new InvoiceLineApiModel 31 | { 32 | InvoiceLineId = InvoiceLineId, 33 | InvoiceId = InvoiceId, 34 | TrackId = TrackId, 35 | UnitPrice = UnitPrice, 36 | Quantity = Quantity 37 | }; 38 | } 39 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/MediaType.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public class MediaType : IConvertModel 11 | { 12 | [Key] 13 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 14 | public int MediaTypeId { get; set; } 15 | 16 | public string Name { get; set; } 17 | 18 | [NotMapped] 19 | [JsonIgnore] 20 | public ICollection Tracks { get; set; } = new HashSet(); 21 | 22 | public MediaTypeApiModel Convert() => new MediaTypeApiModel 23 | { 24 | MediaTypeId = MediaTypeId, 25 | Name = Name 26 | }; 27 | } 28 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Playlist.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public class Playlist : IConvertModel 11 | { 12 | [Key] 13 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 14 | public int PlaylistId { get; set; } 15 | public string Name { get; set; } 16 | 17 | [NotMapped] 18 | [JsonIgnore] 19 | public ICollection PlaylistTracks { get; set; } = new HashSet(); 20 | 21 | public PlaylistApiModel Convert() => new PlaylistApiModel 22 | { 23 | PlaylistId = PlaylistId, 24 | Name = Name 25 | }; 26 | } 27 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/PlaylistTrack.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Chinook.Domain.Converters; 4 | using Chinook.Domain.ApiModels; 5 | using Newtonsoft.Json; 6 | 7 | namespace Chinook.Domain.Entities 8 | { 9 | public class PlaylistTrack : IConvertModel 10 | { 11 | public int PlaylistId { get; set; } 12 | public int TrackId { get; set; } 13 | 14 | [NotMapped] 15 | [JsonIgnore] 16 | public Playlist Playlist { get; set; } 17 | [NotMapped] 18 | [JsonIgnore] 19 | public Track Track { get; set; } 20 | 21 | public PlaylistTrackApiModel Convert() => new PlaylistTrackApiModel 22 | { 23 | PlaylistId = PlaylistId, 24 | TrackId = TrackId 25 | }; 26 | } 27 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Entities/Track.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using Chinook.Domain.ApiModels; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using Newtonsoft.Json; 7 | 8 | namespace Chinook.Domain.Entities 9 | { 10 | public class Track : IConvertModel 11 | { 12 | [Key] 13 | [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 14 | public int TrackId { get; set; } 15 | 16 | public string Name { get; set; } 17 | 18 | public int AlbumId { get; set; } 19 | public int MediaTypeId { get; set; } 20 | public int? GenreId { get; set; } 21 | public string Composer { get; set; } 22 | public int Milliseconds { get; set; } 23 | public int Bytes { get; set; } 24 | public decimal UnitPrice { get; set; } 25 | 26 | [NotMapped] 27 | [JsonIgnore] 28 | public ICollection InvoiceLines { get; set; } = new HashSet(); 29 | [NotMapped] 30 | [JsonIgnore] 31 | public ICollection PlaylistTracks { get; set; } = new HashSet(); 32 | [NotMapped] 33 | [JsonIgnore] 34 | public Album Album { get; set; } 35 | [NotMapped] 36 | [JsonIgnore] 37 | public Genre Genre { get; set; } 38 | [NotMapped] 39 | [JsonIgnore] 40 | public MediaType MediaType { get; set; } 41 | 42 | public TrackApiModel Convert() => new TrackApiModel 43 | { 44 | TrackId = TrackId, 45 | Name = Name, 46 | AlbumId = AlbumId, 47 | MediaTypeId = MediaTypeId, 48 | GenreId = GenreId, 49 | Composer = Composer, 50 | Milliseconds = Milliseconds, 51 | Bytes = Bytes, 52 | UnitPrice = UnitPrice 53 | }; 54 | } 55 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Extensions/ConvertExtensions.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Converters; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Chinook.Domain.Extensions 6 | { 7 | public static class ConvertExtensions 8 | { 9 | public static IEnumerable ConvertAll( 10 | this IEnumerable> values) 11 | => values.Select(value => value.Convert()); 12 | } 13 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IAlbumRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IAlbumRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task> GetByArtistIdAsync(int id, CancellationToken ct = default); 14 | Task AddAsync(Album newAlbum, CancellationToken ct = default); 15 | Task UpdateAsync(Album album, CancellationToken ct = default); 16 | Task DeleteAsync(int id, CancellationToken ct = default); 17 | } 18 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IArtistRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Chinook.Domain.Entities; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IArtistRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task AddAsync(Artist newArtist, CancellationToken ct = default); 14 | Task UpdateAsync(Artist artist, CancellationToken ct = default); 15 | Task DeleteAsync(int id, CancellationToken ct = default); 16 | } 17 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/ICustomerRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface ICustomerRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task> GetBySupportRepIdAsync(int id, CancellationToken ct = default); 14 | Task AddAsync(Customer newCustomer, CancellationToken ct = default); 15 | Task UpdateAsync(Customer customer, CancellationToken ct = default); 16 | Task DeleteAsync(int id, CancellationToken ct = default); 17 | } 18 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IEmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IEmployeeRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task GetReportsToAsync(int id, CancellationToken ct = default); 14 | Task AddAsync(Employee newEmployee, CancellationToken ct = default); 15 | Task UpdateAsync(Employee employee, CancellationToken ct = default); 16 | Task DeleteAsync(int id, CancellationToken ct = default); 17 | Task> GetDirectReportsAsync(int id, CancellationToken ct = default); 18 | } 19 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IGenreRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IGenreRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task AddAsync(Genre newGenre, CancellationToken ct = default); 14 | Task UpdateAsync(Genre genre, CancellationToken ct = default); 15 | Task DeleteAsync(int id, CancellationToken ct = default); 16 | } 17 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IInvoiceLineRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IInvoiceLineRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task> GetByInvoiceIdAsync(int id, CancellationToken ct = default); 14 | Task> GetByTrackIdAsync(int id, CancellationToken ct = default); 15 | Task AddAsync(InvoiceLine newInvoiceLine, CancellationToken ct = default); 16 | Task UpdateAsync(InvoiceLine invoiceLine, CancellationToken ct = default); 17 | Task DeleteAsync(int id, CancellationToken ct = default); 18 | } 19 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IInvoiceRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IInvoiceRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task> GetByCustomerIdAsync(int id, CancellationToken ct = default); 14 | Task AddAsync(Invoice newInvoice, CancellationToken ct = default); 15 | Task UpdateAsync(Invoice invoice, CancellationToken ct = default); 16 | Task DeleteAsync(int id, CancellationToken ct = default); 17 | } 18 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IMediaTypeRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IMediaTypeRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task AddAsync(MediaType newMediaType, CancellationToken ct = default); 14 | Task UpdateAsync(MediaType mediaType, CancellationToken ct = default); 15 | Task DeleteAsync(int id, CancellationToken ct = default); 16 | } 17 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IPlaylistRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IPlaylistRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task AddAsync(Playlist newPlaylist, CancellationToken ct = default); 14 | Task> GetTrackByPlaylistIdAsync(int id, CancellationToken ct = default); 15 | Task UpdateAsync(Playlist playlist, CancellationToken ct = default); 16 | Task DeleteAsync(int id, CancellationToken ct = default); 17 | } 18 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/IPlaylistTrackRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface IPlaylistTrackRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task> GetByPlaylistIdAsync(int id, CancellationToken ct = default); 13 | Task> GetByTrackIdAsync(int id, CancellationToken ct = default); 14 | Task AddAsync(PlaylistTrack newPlaylistTrack, CancellationToken ct = default); 15 | Task UpdateAsync(PlaylistTrack playlistTrack, CancellationToken ct = default); 16 | Task DeleteAsync(int id, CancellationToken ct = default); 17 | } 18 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Repositories/ITrackRepository.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Chinook.Domain.Repositories 8 | { 9 | public interface ITrackRepository : IDisposable 10 | { 11 | Task> GetAllAsync(CancellationToken ct = default); 12 | Task GetByIdAsync(int id, CancellationToken ct = default); 13 | Task> GetByAlbumIdAsync(int id, CancellationToken ct = default); 14 | Task> GetByGenreIdAsync(int id, CancellationToken ct = default); 15 | Task> GetByMediaTypeIdAsync(int id, CancellationToken ct = default); 16 | Task AddAsync(Track newTrack, CancellationToken ct = default); 17 | Task UpdateAsync(Track track, CancellationToken ct = default); 18 | Task DeleteAsync(int id, CancellationToken ct = default); 19 | } 20 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Supervisor/ChinookSupervisor.cs: -------------------------------------------------------------------------------- 1 | using Chinook.Domain.Repositories; 2 | using Microsoft.Extensions.Caching.Memory; 3 | 4 | namespace Chinook.Domain.Supervisor 5 | { 6 | public partial class ChinookSupervisor : IChinookSupervisor 7 | { 8 | private readonly IAlbumRepository _albumRepository; 9 | private readonly IArtistRepository _artistRepository; 10 | private readonly ICustomerRepository _customerRepository; 11 | private readonly IEmployeeRepository _employeeRepository; 12 | private readonly IGenreRepository _genreRepository; 13 | private readonly IInvoiceLineRepository _invoiceLineRepository; 14 | private readonly IInvoiceRepository _invoiceRepository; 15 | private readonly IMediaTypeRepository _mediaTypeRepository; 16 | private readonly IPlaylistRepository _playlistRepository; 17 | private readonly ITrackRepository _trackRepository; 18 | private readonly IMemoryCache _cache; 19 | 20 | public ChinookSupervisor() 21 | { 22 | } 23 | 24 | public ChinookSupervisor(IAlbumRepository albumRepository, 25 | IArtistRepository artistRepository, 26 | ICustomerRepository customerRepository, 27 | IEmployeeRepository employeeRepository, 28 | IGenreRepository genreRepository, 29 | IInvoiceLineRepository invoiceLineRepository, 30 | IInvoiceRepository invoiceRepository, 31 | IMediaTypeRepository mediaTypeRepository, 32 | IPlaylistRepository playlistRepository, 33 | ITrackRepository trackRepository, 34 | IMemoryCache memoryCache 35 | ) 36 | { 37 | _albumRepository = albumRepository; 38 | _artistRepository = artistRepository; 39 | _customerRepository = customerRepository; 40 | _employeeRepository = employeeRepository; 41 | _genreRepository = genreRepository; 42 | _invoiceLineRepository = invoiceLineRepository; 43 | _invoiceRepository = invoiceRepository; 44 | _mediaTypeRepository = mediaTypeRepository; 45 | _playlistRepository = playlistRepository; 46 | _trackRepository = trackRepository; 47 | _cache = memoryCache; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Supervisor/ChinookSupervisorArtist.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Chinook.Domain.Extensions; 7 | using Chinook.Domain.ApiModels; 8 | using Chinook.Domain.Entities; 9 | using Microsoft.Extensions.Caching.Memory; 10 | 11 | namespace Chinook.Domain.Supervisor 12 | { 13 | public partial class ChinookSupervisor 14 | { 15 | public async Task> GetAllArtistAsync(CancellationToken ct = default) 16 | { 17 | var artists = await _artistRepository.GetAllAsync(ct); 18 | foreach (var artist in artists) 19 | { 20 | var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(604800)); 21 | _cache.Set(artist.ArtistId, artist, cacheEntryOptions); 22 | } 23 | return artists.ConvertAll(); 24 | } 25 | 26 | public async Task GetArtistByIdAsync(int id, CancellationToken ct = default) 27 | { 28 | var artist = _cache.Get(id); 29 | 30 | if (artist != null) 31 | { 32 | var artistApiModel = artist.Convert(); 33 | artistApiModel.Albums = (await GetAlbumByArtistIdAsync(artistApiModel.ArtistId, ct)).ToList(); 34 | return artistApiModel; 35 | } 36 | else 37 | { 38 | var artistApiModel = (await _artistRepository.GetByIdAsync(id, ct)).Convert(); 39 | artistApiModel.Albums = (await GetAlbumByArtistIdAsync(artistApiModel.ArtistId, ct)).ToList(); 40 | 41 | var cacheEntryOptions = 42 | new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(604800)); 43 | _cache.Set(artistApiModel.ArtistId, artistApiModel, cacheEntryOptions); 44 | 45 | return artistApiModel; 46 | } 47 | } 48 | 49 | public async Task AddArtistAsync(ArtistApiModel newArtistApiModel, 50 | CancellationToken ct = default) 51 | { 52 | var artist = newArtistApiModel.Convert(); 53 | 54 | artist = await _artistRepository.AddAsync(artist, ct); 55 | newArtistApiModel.ArtistId = artist.ArtistId; 56 | return newArtistApiModel; 57 | } 58 | 59 | public async Task UpdateArtistAsync(ArtistApiModel artistApiModel, 60 | CancellationToken ct = default) 61 | { 62 | var artist = await _artistRepository.GetByIdAsync(artistApiModel.ArtistId, ct); 63 | 64 | if (artist == null) return false; 65 | artist.ArtistId = artistApiModel.ArtistId; 66 | artist.Name = artistApiModel.Name; 67 | 68 | return await _artistRepository.UpdateAsync(artist, ct); 69 | } 70 | 71 | public Task DeleteArtistAsync(int id, CancellationToken ct = default) 72 | => _artistRepository.DeleteAsync(id, ct); 73 | } 74 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Supervisor/ChinookSupervisorGenre.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Chinook.Domain.Extensions; 6 | using Chinook.Domain.ApiModels; 7 | using System.Linq; 8 | using Chinook.Domain.Entities; 9 | using Microsoft.Extensions.Caching.Memory; 10 | 11 | namespace Chinook.Domain.Supervisor 12 | { 13 | public partial class ChinookSupervisor 14 | { 15 | public async Task> GetAllGenreAsync(CancellationToken ct = default) 16 | { 17 | var genres = await _genreRepository.GetAllAsync(ct); 18 | 19 | foreach (var genre in genres) 20 | { 21 | var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(604800)); 22 | _cache.Set(genre.GenreId, genre, cacheEntryOptions); 23 | } 24 | 25 | return genres.ConvertAll(); 26 | } 27 | 28 | public async Task GetGenreByIdAsync(int id, CancellationToken ct = default) 29 | { 30 | var genre = _cache.Get(id); 31 | 32 | if (genre != null) 33 | { 34 | var genreApiModel = genre.Convert(); 35 | genreApiModel.Tracks = (await GetTrackByGenreIdAsync(genreApiModel.GenreId, ct)).ToList(); 36 | return genreApiModel; 37 | } 38 | else 39 | { 40 | var genreApiModel = (await _genreRepository.GetByIdAsync(id, ct)).Convert(); 41 | genreApiModel.Tracks = (await GetTrackByGenreIdAsync(genreApiModel.GenreId, ct)).ToList(); 42 | 43 | var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(604800)); 44 | _cache.Set(genreApiModel.GenreId, genreApiModel, cacheEntryOptions); 45 | 46 | return genreApiModel; 47 | } 48 | } 49 | 50 | public async Task AddGenreAsync(GenreApiModel newGenreApiModel, 51 | CancellationToken ct = default) 52 | { 53 | var genre = newGenreApiModel.Convert(); 54 | 55 | genre = await _genreRepository.AddAsync(genre, ct); 56 | newGenreApiModel.GenreId = genre.GenreId; 57 | return newGenreApiModel; 58 | } 59 | 60 | public async Task UpdateGenreAsync(GenreApiModel genreApiModel, 61 | CancellationToken ct = default) 62 | { 63 | var genre = await _genreRepository.GetByIdAsync(genreApiModel.GenreId, ct); 64 | 65 | if (genre == null) return false; 66 | genre.GenreId = genreApiModel.GenreId; 67 | genre.Name = genreApiModel.Name; 68 | 69 | return await _genreRepository.UpdateAsync(genre, ct); 70 | } 71 | 72 | public Task DeleteGenreAsync(int id, CancellationToken ct = default) 73 | => _genreRepository.DeleteAsync(id, ct); 74 | } 75 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.Domain/Supervisor/ChinookSupervisorPlaylistTrack.cs: -------------------------------------------------------------------------------- 1 | namespace Chinook.Domain.Supervisor 2 | { 3 | public partial class ChinookSupervisor 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/AlbumAPIAlbaTest.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Alba; 3 | using Chinook.API; 4 | using Xunit; 5 | 6 | namespace Chinook.IntegrationTest.API 7 | { 8 | public class AlbumApiAlbaTest 9 | { 10 | [Fact] 11 | public async Task should_get_list_of_albums() 12 | { 13 | using (var system = SystemUnderTest.ForStartup()) 14 | { 15 | // This runs an HTTP request and makes an assertion 16 | // about the expected content of the response 17 | await system.Scenario(_ => 18 | { 19 | _.Get.Url("/api/Album"); 20 | _.StatusCodeShouldBeOk(); 21 | }); 22 | } 23 | } 24 | 25 | [Fact] 26 | public async Task should_get_single_album() 27 | { 28 | using (var system = SystemUnderTest.ForStartup()) 29 | { 30 | // This runs an HTTP request and makes an assertion 31 | // about the expected content of the response 32 | await system.Scenario(_ => 33 | { 34 | _.Get.Url("/api/Album/4/"); 35 | _.StatusCodeShouldBeOk(); 36 | }); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/AlbumAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Chinook.API; 6 | using Microsoft.AspNetCore.TestHost; 7 | using Microsoft.AspNetCore.Hosting; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class AlbumApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public AlbumApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task AlbumGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Album/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | response.EnsureSuccessStatusCode(); 35 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 36 | } 37 | 38 | [Theory] 39 | [InlineData("GET", 1)] 40 | public async Task AlbumGetTestAsync(string method, int? id = null) 41 | { 42 | // Arrange 43 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Album/{id}"); 44 | 45 | // Act 46 | var response = await _client.SendAsync(request); 47 | 48 | // Assert 49 | response.EnsureSuccessStatusCode(); 50 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/ArtistAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class ArtistApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public ArtistApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task ArtistGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Artist/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task ArtistGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Artist/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/CustomerAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class CustomerApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public CustomerApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task CustomerGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Customer/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task CustomerGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Customer/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/EmployeeAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class EmployeeApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public EmployeeApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task EmployeeGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Employee/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 4)] 39 | public async Task EmployeeGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Employee/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/GenreAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class GenreApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public GenreApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task GenreGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Genre/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task GenreGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Genre/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/InvoiceAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class InvoiceApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public InvoiceApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task InvoiceGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Invoice/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task InvoiceGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Invoice/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/InvoiceLineAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class InvoiceLineApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public InvoiceLineApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task InvoiceLineGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/InvoiceLine/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task InvoiceLineGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/InvoiceLine/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/MediaTypeAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class MediaTypeApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public MediaTypeApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task MediaTypeGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/MediaType/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task MediaTypeGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/MediaType/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/PlaylistAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class PlaylistApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public PlaylistApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task PlaylistGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Playlist/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task PlaylistGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Playlist/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/API/TrackAPITest.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Threading.Tasks; 4 | using Xunit; 5 | using Microsoft.AspNetCore.TestHost; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Chinook.API; 8 | 9 | namespace Chinook.IntegrationTest.API 10 | { 11 | public class TrackApiTest 12 | { 13 | private readonly HttpClient _client; 14 | 15 | public TrackApiTest() 16 | { 17 | var server = new TestServer(new WebHostBuilder() 18 | .UseEnvironment("Development") 19 | .UseStartup()); 20 | _client = server.CreateClient(); 21 | } 22 | 23 | [Theory] 24 | [InlineData("GET")] 25 | public async Task TrackGetAllTestAsync(string method) 26 | { 27 | // Arrange 28 | var request = new HttpRequestMessage(new HttpMethod(method), "/api/Track/"); 29 | 30 | // Act 31 | var response = await _client.SendAsync(request); 32 | 33 | // Assert 34 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 35 | } 36 | 37 | [Theory] 38 | [InlineData("GET", 1)] 39 | public async Task TrackGetTestAsync(string method, int? id = null) 40 | { 41 | // Arrange 42 | var request = new HttpRequestMessage(new HttpMethod(method), $"/api/Track/{id}"); 43 | 44 | // Act 45 | var response = await _client.SendAsync(request); 46 | 47 | // Assert 48 | Assert.Equal(HttpStatusCode.OK, response.StatusCode); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/AlbumAddOne.http: -------------------------------------------------------------------------------- 1 | POST http://localhost:52460/api/Album 2 | Content-Type: application/json 3 | 4 | { 5 | "title": "The Greatest Album", 6 | "artistId": 1, 7 | "artist": null, 8 | "tracks": null 9 | } 10 | 11 | ### 12 | g -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/AlbumDeleteOne.http: -------------------------------------------------------------------------------- 1 | DELETE http://localhost:52460/api/Album/6 2 | Accept: application/json 3 | 4 | ### -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/AlbumGetAll.http: -------------------------------------------------------------------------------- 1 | GET http://localhost:52460/api/Album 2 | Accept: application/json 3 | 4 | ### -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/AlbumGetOne.http: -------------------------------------------------------------------------------- 1 | GET http://localhost:52460/api/Album/6 2 | Accept: application/json 3 | 4 | ### -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/AlbumUpdateOne.http: -------------------------------------------------------------------------------- 1 | PUT http://localhost:52460/api/Album/6 2 | Content-Type: application/json 3 | 4 | { 5 | "albumId": 348, 6 | "title": "The Greatest Album!!!", 7 | "artistId": 1, 8 | "artist": null, 9 | "tracks": null 10 | } 11 | 12 | ### -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.IntegrationTest/Chinook.IntegrationTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | false 5 | latest 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | all 19 | runtime; build; native; contentfiles; analyzers 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MSUnitTest/AlbumRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Chinook.Domain.Entities; 4 | using Chinook.MockData.Repositories; 5 | using JetBrains.dotMemoryUnit; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace Chinook.MSUnitTest 9 | { 10 | [TestClass] 11 | public class AlbumRepositoryTest 12 | { 13 | private readonly AlbumRepository _repo; 14 | 15 | public AlbumRepositoryTest() 16 | { 17 | _repo = new AlbumRepository(); 18 | } 19 | 20 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 21 | [TestMethod] 22 | public async Task AlbumGetAllAsync() 23 | { 24 | // Act 25 | var albums = await _repo.GetAllAsync(); 26 | 27 | // Assert 28 | Assert.AreEqual(1, albums.Count); 29 | } 30 | 31 | [DotMemoryUnitAttribute(FailIfRunWithoutSupport = false)] 32 | [TestMethod] 33 | public async Task AlbumGetOneAsync() 34 | { 35 | // Arrange 36 | var number = 1; 37 | 38 | // Act 39 | var album = await _repo.GetByIdAsync(1); 40 | 41 | // Assert 42 | Assert.AreEqual(number, album.AlbumId); 43 | } 44 | 45 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Album)})] 46 | [TestMethod] 47 | public async Task DotMemoryUnitTest() 48 | { 49 | var repo = new AlbumRepository(); 50 | 51 | await repo.GetAllAsync(); 52 | 53 | dotMemory.Check(memory => 54 | Assert.AreEqual(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 55 | 56 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MSUnitTest/Chinook.MSUnitTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | false 5 | default 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Chinook.MockData.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | latest 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Chinook.MockData.Repositories 5 | { 6 | public static class ObjectExtensions 7 | { 8 | public static Task> AsListTask(this T value) 9 | => new List { value }.AsTask(); 10 | 11 | public static Task AsTask(this T value) 12 | => Task.FromResult(value); 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/AlbumRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class AlbumRepository : IAlbumRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Album 17 | { 18 | AlbumId = 1, 19 | ArtistId = 1, 20 | Title = "Hello World" 21 | }.AsListTask(); 22 | 23 | public Task GetByIdAsync(int id, CancellationToken ct = default) 24 | => new Album 25 | { 26 | AlbumId = id, 27 | ArtistId = 1, 28 | Title = "Hello World" 29 | }.AsTask(); 30 | 31 | public Task AddAsync(Album newAlbum, CancellationToken ct = default) 32 | { 33 | newAlbum.AlbumId = 1; 34 | return newAlbum.AsTask(); 35 | } 36 | 37 | public Task UpdateAsync(Album album, CancellationToken ct = default) => Task.FromResult(true); 38 | 39 | public Task DeleteAsync(int id, CancellationToken ct = default) => Task.FromResult(true); 40 | 41 | public Task> GetByArtistIdAsync(int id, CancellationToken ct = default) 42 | => new Album 43 | { 44 | Title = "hello World", 45 | ArtistId = 1, 46 | AlbumId = 1 47 | }.AsListTask(); 48 | } 49 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/ArtistRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class ArtistRepository : IArtistRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Artist 17 | { 18 | ArtistId = 1, 19 | Name = "Foo" 20 | }.AsListTask(); 21 | 22 | public Task GetByIdAsync(int id, CancellationToken ct = default) 23 | => new Artist 24 | { 25 | ArtistId = id, 26 | Name = "Foo" 27 | }.AsTask(); 28 | 29 | public Task AddAsync(Artist newArtist, CancellationToken ct = default) => Task.FromResult(newArtist); 30 | 31 | public Task UpdateAsync(Artist artist, CancellationToken ct = default) => Task.FromResult(true); 32 | 33 | public Task DeleteAsync(int id, CancellationToken ct = default) => Task.FromResult(true); 34 | } 35 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/CustomerRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class CustomerRepository : ICustomerRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Customer 17 | { 18 | CustomerId = 1 19 | }.AsListTask(); 20 | 21 | public Task GetByIdAsync(int id, CancellationToken ct = default) 22 | => new Customer 23 | { 24 | CustomerId = id 25 | }.AsTask(); 26 | 27 | public Task AddAsync(Customer newCustomer, CancellationToken ct = default) => newCustomer.AsTask(); 28 | 29 | public Task UpdateAsync(Customer customer, CancellationToken ct = default) => true.AsTask(); 30 | 31 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 32 | 33 | public Task> GetBySupportRepIdAsync(int id, 34 | CancellationToken ct = default) 35 | => new Customer 36 | { 37 | CustomerId = id 38 | }.AsListTask(); 39 | } 40 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/EmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class EmployeeRepository : IEmployeeRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Employee 17 | { 18 | EmployeeId = 1 19 | }.AsListTask(); 20 | 21 | public Task GetByIdAsync(int id, CancellationToken ct = default) 22 | => new Employee 23 | { 24 | EmployeeId = id 25 | }.AsTask(); 26 | 27 | public Task AddAsync(Employee newEmployee, CancellationToken ct = default) => newEmployee.AsTask(); 28 | 29 | public Task UpdateAsync(Employee employee, CancellationToken ct = default) => true.AsTask(); 30 | 31 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 32 | 33 | public Task GetReportsToAsync(int id, CancellationToken ct = default) 34 | => new Employee 35 | { 36 | EmployeeId = id 37 | }.AsTask(); 38 | 39 | public Task> GetDirectReportsAsync(int id, 40 | CancellationToken ct = default) 41 | => new Employee 42 | { 43 | EmployeeId = id 44 | }.AsListTask(); 45 | } 46 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/GenreRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class GenreRepository : IGenreRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Genre 17 | { 18 | GenreId = 1, 19 | Name = "Foo" 20 | }.AsListTask(); 21 | 22 | public Task GetByIdAsync(int id, CancellationToken ct = default) 23 | => new Genre 24 | { 25 | GenreId = id, 26 | Name = "Foo" 27 | }.AsTask(); 28 | 29 | public Task AddAsync(Genre newGenre, CancellationToken ct = default) => newGenre.AsTask(); 30 | 31 | public Task UpdateAsync(Genre genre, CancellationToken ct = default) => true.AsTask(); 32 | 33 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 34 | } 35 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/InvoiceLineRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class InvoiceLineRepository : IInvoiceLineRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new InvoiceLine 17 | { 18 | InvoiceLineId = 1 19 | }.AsListTask(); 20 | 21 | public Task GetByIdAsync(int id, CancellationToken ct = default) 22 | => new InvoiceLine 23 | { 24 | InvoiceLineId = id 25 | }.AsTask(); 26 | 27 | public Task AddAsync(InvoiceLine newInvoiceLine, 28 | CancellationToken ct = default) => newInvoiceLine.AsTask(); 29 | 30 | public Task UpdateAsync(InvoiceLine invoiceLine, CancellationToken ct = default) => true.AsTask(); 31 | 32 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 33 | 34 | public Task> GetByInvoiceIdAsync(int id, 35 | CancellationToken ct = default) 36 | => new InvoiceLine 37 | { 38 | InvoiceLineId = id 39 | }.AsListTask(); 40 | 41 | public Task> GetByTrackIdAsync(int id, 42 | CancellationToken ct = default) 43 | => new InvoiceLine 44 | { 45 | InvoiceLineId = id 46 | }.AsListTask(); 47 | } 48 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/InvoiceRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class InvoiceRepository : IInvoiceRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Invoice 17 | { 18 | InvoiceId = 1 19 | }.AsListTask(); 20 | 21 | public Task GetByIdAsync(int id, CancellationToken ct = default) 22 | => new Invoice 23 | { 24 | InvoiceId = id 25 | }.AsTask(); 26 | 27 | public Task AddAsync(Invoice newInvoice, CancellationToken ct = default) => newInvoice.AsTask(); 28 | 29 | public Task UpdateAsync(Invoice invoice, CancellationToken ct = default) => true.AsTask(); 30 | 31 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 32 | 33 | public Task> GetByCustomerIdAsync(int id, CancellationToken ct = default) 34 | => new Invoice 35 | { 36 | InvoiceId = 1 37 | }.AsListTask(); 38 | } 39 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/MediaTypeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class MediaTypeRepository : IMediaTypeRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new MediaType 17 | { 18 | MediaTypeId = 1, 19 | Name = "Foo" 20 | }.AsListTask(); 21 | 22 | public Task GetByIdAsync(int id, CancellationToken ct = default) 23 | => new MediaType 24 | { 25 | MediaTypeId = id, 26 | Name = "Foo" 27 | }.AsTask(); 28 | 29 | public Task AddAsync(MediaType newMediaType, CancellationToken ct = default) => newMediaType.AsTask(); 30 | 31 | public Task UpdateAsync(MediaType mediaType, CancellationToken ct = default) => true.AsTask(); 32 | 33 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 34 | } 35 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/PlaylistRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class PlaylistRepository : IPlaylistRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Playlist 17 | { 18 | PlaylistId = 1, 19 | Name = "Foo" 20 | }.AsListTask(); 21 | 22 | public Task GetByIdAsync(int id, CancellationToken ct = default) 23 | => new Playlist 24 | { 25 | PlaylistId = id, 26 | Name = "Foo" 27 | }.AsTask(); 28 | 29 | public Task AddAsync(Playlist newPlaylist, CancellationToken ct = default) => newPlaylist.AsTask(); 30 | 31 | public Task> GetTrackByPlaylistIdAsync(int id, 32 | CancellationToken ct = default) 33 | => new Track 34 | { 35 | TrackId = 1, 36 | Name = "foo", 37 | AlbumId = 1, 38 | MediaTypeId = 1, 39 | GenreId = 1, 40 | Composer = "foo", 41 | Milliseconds = 1, 42 | Bytes = 1, 43 | UnitPrice = 1 44 | }.AsListTask(); 45 | 46 | public Task UpdateAsync(Playlist playlist, CancellationToken ct = default) => true.AsTask(); 47 | 48 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 49 | } 50 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/PlaylistTrackRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class PlaylistTrackRepository : IPlaylistTrackRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new PlaylistTrack 17 | { 18 | PlaylistId = 1, 19 | TrackId = 1 20 | }.AsListTask(); 21 | 22 | public Task> GetByPlaylistIdAsync(int id, 23 | CancellationToken ct = default) 24 | => new PlaylistTrack 25 | { 26 | PlaylistId = id, 27 | TrackId = 1 28 | }.AsListTask(); 29 | 30 | public Task> GetByTrackIdAsync(int id, 31 | CancellationToken ct = default) 32 | => new PlaylistTrack 33 | { 34 | PlaylistId = 1, 35 | TrackId = id 36 | }.AsListTask(); 37 | 38 | public Task AddAsync(PlaylistTrack newPlaylistTrack, 39 | CancellationToken ct = default) => newPlaylistTrack.AsTask(); 40 | 41 | public Task UpdateAsync(PlaylistTrack playlistTrack, 42 | CancellationToken ct = default) => true.AsTask(); 43 | 44 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 45 | } 46 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.MockData/Repositories/TrackRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using System.Threading; 3 | using System.Collections.Generic; 4 | using Chinook.Domain.Repositories; 5 | using Chinook.Domain.Entities; 6 | 7 | namespace Chinook.MockData.Repositories 8 | { 9 | public class TrackRepository : ITrackRepository 10 | { 11 | public void Dispose() 12 | { 13 | } 14 | 15 | public Task> GetAllAsync(CancellationToken ct = default) 16 | => new Track 17 | { 18 | TrackId = 1, 19 | Name = "Foo" 20 | }.AsListTask(); 21 | 22 | public Task GetByIdAsync(int id, CancellationToken ct = default) 23 | => new Track 24 | { 25 | TrackId = id 26 | }.AsTask(); 27 | 28 | public Task AddAsync(Track newTrack, CancellationToken ct = default) => newTrack.AsTask(); 29 | 30 | public Task UpdateAsync(Track track, CancellationToken ct = default) => true.AsTask(); 31 | 32 | public Task DeleteAsync(int id, CancellationToken ct = default) => true.AsTask(); 33 | 34 | public Task> GetByAlbumIdAsync(int id, CancellationToken ct = default) 35 | => new Track 36 | { 37 | TrackId = id 38 | }.AsListTask(); 39 | 40 | public Task> GetByGenreIdAsync(int id, CancellationToken ct = default) 41 | => new Track 42 | { 43 | TrackId = id 44 | }.AsListTask(); 45 | 46 | public Task> GetByMediaTypeIdAsync(int id, CancellationToken ct = default) 47 | => new Track 48 | { 49 | TrackId = id 50 | }.AsListTask(); 51 | } 52 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Chinook.UnitTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp2.2 4 | false 5 | latest 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/AlbumRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class AlbumRepositoryTest 11 | { 12 | private readonly AlbumRepository _repo; 13 | 14 | public AlbumRepositoryTest() 15 | { 16 | _repo = new AlbumRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task AlbumGetAllAsync() 22 | { 23 | // Arrange 24 | 25 | // Act 26 | var albums = await _repo.GetAllAsync(); 27 | 28 | // Assert 29 | Assert.Single(albums); 30 | } 31 | 32 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 33 | [Fact] 34 | public async Task AlbumGetOneAsync() 35 | { 36 | // Arrange 37 | var id = 1; 38 | 39 | // Act 40 | var album = await _repo.GetByIdAsync(id); 41 | 42 | // Assert 43 | Assert.Equal(id, album.AlbumId); 44 | } 45 | 46 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Album)})] 47 | [Fact] 48 | public async Task DotMemoryUnitTest() 49 | { 50 | var repo = new AlbumRepository(); 51 | 52 | await repo.GetAllAsync(); 53 | 54 | dotMemory.Check(memory => 55 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 56 | 57 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/ArtistRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | [assembly: SuppressXUnitOutputException] 9 | [assembly: EnableDotMemoryUnitSupport] 10 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 11 | 12 | namespace Chinook.UnitTest.Repository 13 | { 14 | public class ArtistRepositoryTest 15 | { 16 | private readonly ArtistRepository _repo; 17 | 18 | public ArtistRepositoryTest() 19 | { 20 | _repo = new ArtistRepository(); 21 | } 22 | 23 | [DotMemoryUnitAttribute(FailIfRunWithoutSupport = false)] 24 | [Fact] 25 | public async Task ArtistGetAllAsync() 26 | { 27 | // Act 28 | var artists = await _repo.GetAllAsync(); 29 | 30 | // Assert 31 | Assert.Single(artists); 32 | } 33 | 34 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Artist)})] 35 | [Fact] 36 | public async Task DotMemoryUnitTest() 37 | { 38 | var repo = new ArtistRepository(); 39 | 40 | await repo.GetAllAsync(); 41 | 42 | dotMemory.Check(memory => 43 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 44 | 45 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/CustomerRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class CustomerRepositoryTest 11 | { 12 | private readonly CustomerRepository _repo; 13 | 14 | public CustomerRepositoryTest() 15 | { 16 | _repo = new CustomerRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task CustomerGetAllAsync() 22 | { 23 | // Act 24 | var customers = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(customers); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Customer)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new CustomerRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/EmployeeRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class EmployeeRepositoryTest 11 | { 12 | private readonly EmployeeRepository _repo; 13 | 14 | public EmployeeRepositoryTest() 15 | { 16 | _repo = new EmployeeRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task EmployeeGetAllAsync() 22 | { 23 | // Act 24 | var employees = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(employees); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Employee)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new EmployeeRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/GenreRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class GenreRepositoryTest 11 | { 12 | private readonly GenreRepository _repo; 13 | 14 | public GenreRepositoryTest() 15 | { 16 | _repo = new GenreRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task GenreGetAllAsync() 22 | { 23 | // Act 24 | var genres = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(genres); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Genre)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new GenreRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/InvoiceLineRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class InvoiceLineRepositoryTest 11 | { 12 | private readonly InvoiceLineRepository _repo; 13 | 14 | public InvoiceLineRepositoryTest() 15 | { 16 | _repo = new InvoiceLineRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task InvoiceLineGetAllAsync() 22 | { 23 | // Act 24 | var invoiceLines = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(invoiceLines); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(InvoiceLine)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new InvoiceLineRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/InvoiceRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class InvoiceRepositoryTest 11 | { 12 | private readonly InvoiceRepository _repo; 13 | 14 | public InvoiceRepositoryTest() 15 | { 16 | _repo = new InvoiceRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task InvoiceGetAllAsync() 22 | { 23 | // Act 24 | var invoices = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(invoices); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Invoice)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new InvoiceRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/MediaTypeRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class MediaTypeRepositoryTest 11 | { 12 | private readonly MediaTypeRepository _repo; 13 | 14 | public MediaTypeRepositoryTest() 15 | { 16 | _repo = new MediaTypeRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task MediaTypeGetAllAsync() 22 | { 23 | // Act 24 | var mediaTypes = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(mediaTypes); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(MediaType)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new MediaTypeRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/PlayListRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class PlayListRepositoryTest 11 | { 12 | private readonly PlaylistRepository _repo; 13 | 14 | public PlayListRepositoryTest() 15 | { 16 | _repo = new PlaylistRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task PlayListGetAllAsync() 22 | { 23 | // Act 24 | var playLists = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(playLists); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Playlist)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new PlaylistRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/PlayListTrackRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class PlayListTrackRepositoryTest 11 | { 12 | private readonly PlaylistTrackRepository _repo; 13 | 14 | public PlayListTrackRepositoryTest() 15 | { 16 | _repo = new PlaylistTrackRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task PlayListTrackGetAllAsync() 22 | { 23 | // Act 24 | var playListTracks = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(playListTracks); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(PlaylistTrack)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new PlaylistTrackRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Repository/TrackRepositoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using JetBrains.dotMemoryUnit; 6 | using Xunit; 7 | 8 | namespace Chinook.UnitTest.Repository 9 | { 10 | public class TrackRepositoryTest 11 | { 12 | private readonly TrackRepository _repo; 13 | 14 | public TrackRepositoryTest() 15 | { 16 | _repo = new TrackRepository(); 17 | } 18 | 19 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 20 | [Fact] 21 | public async Task TrackGetAllAsync() 22 | { 23 | // Act 24 | var tracks = await _repo.GetAllAsync(); 25 | 26 | // Assert 27 | Assert.Single(tracks); 28 | } 29 | 30 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Track)})] 31 | [Fact] 32 | public async Task DotMemoryUnitTest() 33 | { 34 | var repo = new TrackRepository(); 35 | 36 | await repo.GetAllAsync(); 37 | 38 | dotMemory.Check(memory => 39 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 40 | 41 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/AlbumSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Chinook.Domain.Supervisor; 3 | using JetBrains.dotMemoryUnit; 4 | using Xunit; 5 | 6 | namespace Chinook.UnitTest.Supervisor 7 | { 8 | public class AlbumSupervisorTest 9 | { 10 | private readonly ChinookSupervisor _super; 11 | 12 | public AlbumSupervisorTest() 13 | { 14 | _super = new ChinookSupervisor(); 15 | } 16 | 17 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 18 | [Fact] 19 | public async Task AlbumGetAllAsync() 20 | { 21 | // Arrange 22 | 23 | // Act 24 | var albums = await _super.GetAllAlbumAsync(); 25 | 26 | // Assert 27 | Assert.Single(albums); 28 | } 29 | 30 | [DotMemoryUnit(FailIfRunWithoutSupport = false)] 31 | [Fact] 32 | public async Task AlbumGetOneAsync() 33 | { 34 | // Arrange 35 | var id = 1; 36 | 37 | // Act 38 | var album = await _super.GetAlbumByIdAsync(id); 39 | 40 | // Assert 41 | Assert.Equal(id, album.AlbumId); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/ArtistSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Chinook.MockData.Repositories; 3 | using System.Threading.Tasks; 4 | using Chinook.Domain.Entities; 5 | using Chinook.Domain.Supervisor; 6 | using JetBrains.dotMemoryUnit; 7 | using Xunit; 8 | 9 | namespace Chinook.UnitTest.Supervisor 10 | { 11 | public class ArtistSupervisorTest 12 | { 13 | private readonly ChinookSupervisor _super; 14 | 15 | public ArtistSupervisorTest(ChinookSupervisor super) 16 | { 17 | _super = super; 18 | } 19 | 20 | [DotMemoryUnitAttribute(FailIfRunWithoutSupport = false)] 21 | [Fact] 22 | public async Task ArtistGetAllAsync() 23 | { 24 | // Act 25 | var artists = await _super.GetAllArtistAsync(); 26 | 27 | // Assert 28 | Assert.Single(artists); 29 | } 30 | 31 | [AssertTraffic(AllocatedSizeInBytes = 1000, Types = new[] {typeof(Artist)})] 32 | [Fact] 33 | public async Task DotMemoryUnitTest() 34 | { 35 | var repo = new ArtistRepository(); 36 | 37 | await repo.GetAllAsync(); 38 | 39 | dotMemory.Check(memory => 40 | Assert.Equal(1, memory.GetObjects(where => where.Type.Is()).ObjectsCount)); 41 | 42 | GC.KeepAlive(repo); // prevent objects from GC if this is implied by test logic 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/CustomerSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class CustomerSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public CustomerSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/EmployeeSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class EmployeeSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public EmployeeSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/GenreSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class GenreSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public GenreSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/InvoiceLineSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class InvoiceLineSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public InvoiceLineSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/InvoiceSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class InvoiceSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public InvoiceSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/MediaTypeSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class MediaTypeSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public MediaTypeSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/PlayListSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class PlayListSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public PlayListSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/PlayListTrackSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class PlayListTrackSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public PlayListTrackSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ChinookASPNETCoreAPINTier/Chinook.UnitTest/Supervisor/TrackSupervisorTest.cs: -------------------------------------------------------------------------------- 1 | using Chinook.MockData.Repositories; 2 | 3 | namespace Chinook.UnitTest.Supervisor 4 | { 5 | public class TrackSupervisorTest 6 | { 7 | private ArtistRepository _repo; 8 | 9 | public TrackSupervisorTest() 10 | { 11 | _repo = new ArtistRepository(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Developing ASP.NET Core 2.2 Web APIs for your Web and Mobile Apps-NTier.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwoodruff/ChinookASPNETCoreAPINTier/9b2366138a8d81a7bdbaf687a13c7b8c1b9202db/Developing ASP.NET Core 2.2 Web APIs for your Web and Mobile Apps-NTier.pptx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chris Woodruff 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChinookASPNETCoreAPINTier 2 | API developed with ASP.NET Core 2.2 using Chinook DB. Developed with an Architecture for better unit testing. 3 | 4 | InfoQ article covering this architecture located here: https://www.infoq.com/articles/advanced-architecture-aspnet-core 5 | 6 | You can find the Chinook database here for the project https://github.com/cwoodruff/ChinookDatabase 7 | -------------------------------------------------------------------------------- /script_webapi.txt: -------------------------------------------------------------------------------- 1 | Install-Package Microsoft.EntityFrameworkCore.SqlServer 2 | Install-Package Microsoft.EntityFrameworkCore.Tools 3 | Install-Package Microsoft.EntityFrameworkCore.SqlServer.Design 4 | 5 | Scaffold-DbContext "Server=.;Database=Chinook;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models 6 | 7 | "ConnectionStrings": { 8 | "ChinookDb": "Server=.;Database=Chinook;Trusted_Connection=True;" 9 | }, 10 | 11 | var connection = Configuration.GetConnectionString("ChinookDb"); 12 | services.AddDbContext(options => options.UseSqlServer(connection)); 13 | 14 | --------------------------------------------------------------------------------