<file_sep>// using System;
// using System.Collections.Generic;

// namespace ECommerce.Demo.API.Domain.Entities {
//     public class Product {
//         public int Id { get; set; }
//         public string Name { get; set; }
//         public string Description { get; set; }
//         public string Type { get; set; }
//         public ICollection<ProductPrice> Prices { get; set; }
//         public DateTime CreatedDate { get; set; }
//         public DateTime ModifiedDate { get; set; }

//     }
// }<file_sep>version: "3.8"
services:
  db:
    image: "mcr.microsoft.com/mssql/server"
    container_name: db
    ports:
      - "1500:1433"
    environment:
      SA_PASSWORD: "<PASSWORD>"
      ACCEPT_EULA: "Y"
  api:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: api
    ports:
      - "5001:5001"
    depends_on:
      - db
      # - client
    volumes:
      - ".:/app/"
      - D:/Users/.aspnet/https/:/https:ro
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS="https://+;http://+"
      - ASPNETCORE_HTTPS_PORT=5001
      - ASPNETCORE_Kestrel__Certificates__Default__Password=<PASSWORD>
      - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
  # client:
  #   container_name: client
  #   build:
  #     context: .
  #     dockerfile: ./client/Dockerfile
  #   volumes:
  #     - "./client:/app"
  #     - "/app/node_modules"
  #   ports:
  #     - "4200:4200"
  #   environment:
  #     - CHOKIDAR_USEPOLLING=true
<file_sep>using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using ECommerce.Demo.Core.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace ECommerce.Demo.Infrastructure.Data
{
    public class StoreContextSeed
    {
       public static async Task SeedAsync (StoreContext context, ILoggerFactory loggerFactory) {

            try {
                using (var trans = context.Database.BeginTransaction ()) {
                    if (!context.ProductBrands.Any ()) {
                        var brandsData =
                            File.ReadAllText ("../Infrastructure/Data/SeedData/brands.json");

                        var brands = JsonConvert.DeserializeObject<List<ProductBrand>> (brandsData);

                        foreach (var item in brands) {
                            context.ProductBrands.Add (item);
                        }

                        await context.Database.ExecuteSqlRawAsync ("SET IDENTITY_INSERT dbo.ProductBrands ON");
                        await context.SaveChangesAsync ();
                        await context.Database.ExecuteSqlRawAsync ("SET IDENTITY_INSERT dbo.ProductBrands OFF");
                    }

                    if (!context.ProductTypes.Any ()) {
                        var typesData =
                            File.ReadAllText ("../Infrastructure/Data/SeedData/types.json");

                        var types = JsonConvert.DeserializeObject<List<ProductType>> (typesData);

                        foreach (var item in types) {
                            context.ProductTypes.Add (item);
                        }

                        await context.Database.ExecuteSqlRawAsync ("SET IDENTITY_INSERT dbo.ProductTypes ON");
                        await context.SaveChangesAsync ();
                        await context.Database.ExecuteSqlRawAsync ("SET IDENTITY_INSERT dbo.ProductTypes OFF");
                    }

                    if (!context.Products.Any ()) {
                        var productsData =
                            File.ReadAllText ("../Infrastructure/Data/SeedData/products.json");

                        var products = JsonConvert.DeserializeObject<List<Product>> (productsData);

                        foreach (var item in products) {
                            context.Products.Add (item);
                        }
                        await context.SaveChangesAsync ();
                    }
                    await trans.CommitAsync ();
                }
            } catch (Exception ex) {
                var logger = loggerFactory.CreateLogger<StoreContext> ();
                logger.LogError (ex.Message);
            }
        } 
    }
}<file_sep>using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ECommerce.Demo.Core.Entities;
using ECommerce.Demo.Core.Interfaces;
using ECommerce.Demo.Infrastructure.Data;
using ECommerce.Demo.Infrastructure.Repositories.EFRepo.Specs;
using Microsoft.EntityFrameworkCore;

namespace ECommerce.Demo.Infrastructure.Repositories.EFRepo
{
    public class GenericRepository<T> : IGenericRepository<T> where T : BaseEntity
    {  private readonly StoreContext _context;

        public GenericRepository(StoreContext context)
        {
            this._context = context;
            
        }

        public async Task<int> CountAsync(ISpecification<T> spec)
        {
            return await ApplySpecification(spec).CountAsync();
        }

        public async Task<T> GetByIdAsync(int id)
        {
            return await _context.Set<T>().FindAsync(id);
        }

        public async Task<T> GetEntityWithSpec(ISpecification<T> spec)
        {
            return await ApplySpecification(spec).FirstOrDefaultAsync();
        }

        public async Task<IReadOnlyList<T>> ListAllAsync()
        {
            return await _context.Set<T>().ToListAsync();
        }

        public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec)
        {
            return await ApplySpecification(spec).ToListAsync();
        }

        private IQueryable<T> ApplySpecification(ISpecification<T> spec){
            return SpecEvaluator<T>.GetQuery(_context.Set<T>().AsQueryable(),spec);
        }

    }
}<file_sep>// namespace ECommerce.Demo.API.Domain.Entities {
//     public class ProductPrice {
//         public int Id { get; set; }
//         public decimal Price { get; set; }
//         public string Currency { get; set; }
//         public string Unit { get; set; }
//     }
// }<file_sep>using System.Collections.Generic;
using ECommerce.Demo.Core.Entities;

namespace ECommerce.Demo.API.SqlServerRepo.Repositories {
    public interface IProductRepository {
        IEnumerable<Product> GetProducts (int num = 1000);

    }
}<file_sep>using System.Collections.Generic;
using System.Threading.Tasks;
using Dapper.Contrib.Extensions;
using ECommerce.Demo.Infrastructure.Extensions;

namespace ECommerce.Demo.API.Repositories {
    public class GenericRepository<T> where T : class {
        private IUnitOfWork _uow;
        public GenericRepository (IUnitOfWork uow) {
            _uow = uow;
        }

        public IEnumerable<T> GetPaginated (ref int total, int currentPage, int itemsPerPage) {
            return _uow.Connection.GetPaginated<T> (ref total, currentPage, itemsPerPage, _uow.Transaction);
        }

        public IEnumerable<T> GetAll () {
            return _uow.Connection.GetAll<T> (_uow.Transaction);
        }

        public T Get (object id) {
            return _uow.Connection.Get<T> (id, _uow.Transaction);
        }

        public async Task<T> GetTaskAsync (object id) {
            return await _uow.Connection.GetAsync<T> (id, _uow.Transaction);
        }

        public void Insert (T model) {
            _uow.Connection.Insert<T> (model, _uow.Transaction);
        }

        public async Task InsertAsync (T model) {
            await _uow.Connection.InsertAsync<T> (model, _uow.Transaction);
        }

        public void Update (T model) {
            _uow.Connection.Update<T> (model, _uow.Transaction);
        }

        public async Task UpdateAsync (T model) {
            await _uow.Connection.UpdateAsync<T> (model, _uow.Transaction);
        }

        public void Delete (T model) {
            _uow.Connection.Delete<T> (model, _uow.Transaction);
        }

        public async Task DeleteAsync (T model) {
            await _uow.Connection.DeleteAsync<T> (model, _uow.Transaction);
        }

        public async Task DeleteAll () {
            await _uow.Connection.DeleteAllAsync<T> (_uow.Transaction);
        }

    }
}<file_sep>#!/bin/bash


set -e
export PATH="$PATH:$HOME/.dotnet/tools/"

until dotnet ef database update -p API; do
>&2 echo "SQL Server is starting up"
sleep 1
done

>&2 echo "SQL Server is up - executing command"

# urls domain must be 0.0.0.0, to expose ports to outside
run_cmd="dotnet watch -p API run --urls=https://0.0.0.0:5001/"
exec $run_cmd<file_sep>namespace ECommerce.Demo.API.Repositories
{
    public interface IUserRepository
    {
    }
}<file_sep>// using ECommerce.Demo.API.Domain.Entities;
// using Microsoft.AspNetCore.Identity;
// using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
// using Microsoft.EntityFrameworkCore;

// namespace ECommerce.Demo.API.Repositories {
//     public class ECDbContext : IdentityDbContext<User, Role, int, IdentityUserClaim<int>, UserRole, IdentityUserLogin<int>, IdentityRoleClaim<int>, IdentityUserToken<int>> {
//         public ECDbContext (DbContextOptions<ECDbContext> options) : base (options) { }
//         protected override void OnModelCreating (ModelBuilder builder) {
//             base.OnModelCreating (builder);

//             builder.Entity<User> (e => {
//                 e.ToTable (name: "User");
//             });

//             builder.Entity<Role> (e => {
//                 e.ToTable (name: "Role");
//             });

//             builder.Entity<UserRole> (e => {
//                 e.ToTable (name: "UserRole");
//                 e.HasKey (ur => new { ur.UserId, ur.RoleId });
//                 e.HasOne (ur => ur.Role)
//                     .WithMany (r => r.UserRoles)
//                     .HasForeignKey (ur => ur.RoleId)
//                     .IsRequired ();
//                 e.HasOne (ur => ur.User)
//                     .WithMany (ur => ur.UserRoles)
//                     .HasForeignKey (ur => ur.UserId)
//                     .IsRequired ();
//             });

//             builder.Entity<IdentityUserClaim<int>> (e => {
//                 e.ToTable ("UserClaim");
//             });

//             builder.Entity<IdentityUserLogin<int>> (e => {
//                 e.ToTable ("UserLogin");
//                 e.HasKey (ul => ul.UserId);
//             });

//             builder.Entity<IdentityUserClaim<int>> (e => {
//                 e.ToTable ("UserClaim");
//                 e.HasKey (uc => uc.Id);
//             });

//             builder.Entity<IdentityRoleClaim<int>> (e => {
//                 e.ToTable ("RoleClaims");
//                 e.HasKey (rc => rc.RoleId);
//             });

//             builder.Entity<IdentityUserToken<int>> (e => {
//                 e.ToTable ("UserTokens");
//                 e.HasKey (ut => ut.UserId);
//             });

//         }
//     }
// }<file_sep>using System.Threading.Tasks;
using API.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace API.Controllers {
    [AllowAnonymous]
    [Route ("api/[controller]")]
    [ApiController]
    public class UsersController : ControllerBase {
        private readonly IUserService _userService;
        public UsersController (IUserService userService) {
            this._userService = userService;
        }

        [HttpGet ("GetUser/{id}")]
        public async Task<IActionResult> GetUser (int id) {
            var user = await _userService.GetUserAsync (1);
            return Ok (user);
        }

    }
}<file_sep>namespace ECommerce.Demo.Core.Entities
{
    public class Order
    {
        
    }
}<file_sep>using System.Collections.Generic;
using System.Threading.Tasks;
using ECommerce.Demo.Core.Entities;

namespace ECommerce.Demo.Core.Interfaces {
    public interface IProductRepository {
        IEnumerable<Product> GetProducts (int num = 1000);
        Task<Product> GetProductByIdAsync (int id);
        Task<IReadOnlyList<Product>> GetProductsAsync ();
        Task<IReadOnlyList<ProductBrand>> GetProductBrandsAsync ();
        Task<IReadOnlyList<ProductType>> GetProductTypesAsync ();

    }
}<file_sep>using ECommerce.Demo.Core.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace ECommerce.Demo.Infrastructure.Configs
{
    public class ProductConfiguration : IEntityTypeConfiguration<Product>
    {
        public void Configure(EntityTypeBuilder<Product> builder)
        {
            builder.Property (p => p.Id).IsRequired ();
            builder.Property (p => p.Name).IsRequired ().HasMaxLength (100);
            builder.Property (p => p.Description).IsRequired ();
            builder.HasMany (p => p.Prices)
                .WithOne().HasForeignKey(p => p.Id);
            builder.Property (p => p.PictureUrl).IsRequired ();
            builder.HasOne (b => b.ProductBrand).WithMany ()
                .HasForeignKey (p => p.ProductBrandId);
            builder.HasOne (b => b.ProductType).WithMany ()
                .HasForeignKey (p => p.ProductTypeId);
        }
    }
}<file_sep>using System.Collections.Generic;
using ECommerce.Demo.Core.Entities;

namespace ECommerce.Demo.API.Services {
    public interface IProductService {
        List<Product> GetProducts (int num = 1000);
    }
}<file_sep>
using ECommerce.Demo.Core.Entities;

namespace ECommerce.Demo.API.Repositories {
    public class UserRepository<DbConn> : GenericRepository<User>, IUserRepository {
        public UserRepository (IUnitOfWork uow) : base (uow) { }
    }
}<file_sep>using System.Threading.Tasks;
using API.Domain.DTO;

namespace API.Services {
    public interface IUserService {
        Task<UserDetailDto> GetUserAsync (int id);
    }
}<file_sep>using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using ECommerce.Demo.API.Repositories;
using Dapper;
using Dapper.Contrib.Extensions;
using ECommerce.Demo.Core.Entities;

namespace ECommerce.Demo.API.SqlServerRepo.Repositories {

    public class ProductRepository<DbConn> : GenericRepository<Product>, IProductRepository where DbConn : IDbConnection, new () {

        private IUnitOfWork _uow;
        public ProductRepository (IUnitOfWork uow) : base (uow) {
            _uow = uow;
        }

        public IEnumerable<Product> GetProducts (int num = 1000) {
            string sqlCmd = GetSqlCommand ().GetProducts ();
            return _uow.Connection.Query<Product> (sqlCmd, new { Num = num }, _uow.Transaction);
        }

        #region SqlCmd String
        private interface ISqlCommand {
            string GetProducts ();
        }

        private class SqlServerCmd : ISqlCommand {
            public string GetProducts () {
                return @"";
            }
        }

        private class PostgreCmd : ISqlCommand {
            public string GetProducts () {
                return @"";
            }
        }
        private class MySqlCmd : ISqlCommand {
            public string GetProducts () {
                return @"";
            }
        }

        private readonly Dictionary<string, ISqlCommand> CmdDict = new Dictionary<string, ISqlCommand> {
            ["sqlconnection"] = new SqlServerCmd (),
            ["npgsqlconnection"] = new PostgreCmd (),
            ["mysqlconnection"] = new MySqlCmd (),
        };
        private readonly ISqlCommand DefaultAdapter = new SqlServerCmd ();

        private ISqlCommand GetSqlCommand () {
            var name = typeof (DbConn).FullName.ToLower ();
            return CmdDict.TryGetValue (name, out var cmd) ? cmd : DefaultAdapter;
        }
        #endregion

    }
}<file_sep>// namespace API.Domain.Entities
// {
//     public class Order
//     {
        
//     }
// }<file_sep>using System;
using System.Collections.Generic;
using System.Linq;
using ECommerce.Demo.API.Repositories;
using ECommerce.Demo.API.SqlServerRepo.Repositories;
using NLog;

namespace ECommerce.Demo.API.Services {
    public class ProductService : IProductService {
        private IProductRepository _repo;
        private IUnitOfWork _uow;
        private static Logger _logger = NLog.LogManager.GetCurrentClassLogger ();
        public ProductService (IUnitOfWork uow, IProductRepository repo) {
            _uow = uow;
            _repo = repo;
        }

        public List<Product> GetProducts (int num = 1000) {
            try {
                _uow.BeginTrans ();
                var products = _repo.GetProducts (num).ToList ();
                _uow.Commit ();
                return products;
            } catch (Exception ex) {
                _logger.Error (ex, "Get Products  Error");
            }
            return null;
        }

    }

}<file_sep>using System.Text;
using API.Services;
using AutoMapper;
using ECommerce.Demo.API.Repositories;
using ECommerce.Demo.API.Services;
using ECommerce.Demo.API.SqlServerRepo.Repositories;
using ECommerce.Demo.Core.Entities;
using ECommerce.Demo.Infrastructure.Data;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;

namespace ECommerce.Demo.API
{
    public class Startup {
        public Startup (IConfiguration configuration) {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices (IServiceCollection services) {

            IdentityBuilder builder = services.AddIdentityCore<User> (opt => {
                opt.Password.RequireLowercase = false;
                opt.Password.RequireDigit = false;
                opt.Password.RequiredLength = 4;
                opt.Password.RequireNonAlphanumeric = false;
                opt.Password.RequireUppercase = false;
            });
            builder = new IdentityBuilder (builder.UserType, typeof (Role), builder.Services);
            builder.AddEntityFrameworkStores<StoreContext> ();
            builder.AddRoleValidator<RoleValidator<Role>> ();
            builder.AddRoleManager<RoleManager<Role>> ();
            builder.AddSignInManager<SignInManager<User>> ();
            services.AddAuthentication (JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer (options => {
                    options.TokenValidationParameters = new TokenValidationParameters {
                    ValidateIssuerSigningKey = true,
                    // IssuerSigningKey = new SymmetricSecurityKey ( Encoding.ASCII.GetBytes (Configuration.GetSection ("AppSetting:Token").Value)),
                    IssuerSigningKey = new SymmetricSecurityKey (Encoding.ASCII.GetBytes ("Test")),
                    ValidateIssuer = false,
                    ValidateAudience = false
                    };
                });

            services.AddControllers (options => {
                var policy = new AuthorizationPolicyBuilder ().RequireAuthenticatedUser ().Build ();
                options.Filters.Add (new AuthorizeFilter (policy));
            }).AddNewtonsoftJson (opt => {
                opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            });
            services.AddAutoMapper (typeof (UserService).Assembly);
            services.AddDbContext<StoreContext> (x => x.UseSqlServer (Configuration.GetConnectionString ("Default")));
            services.AddCors (opt =>{
                opt.AddPolicy("CorsPolicy",policy =>{
                    policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("https://localhost:4200");
                });
            });

            services.AddSingleton<IUnitOfWork> (u => new UnitOfWork<SqlConnection> (Configuration.GetConnectionString ("Default")));
            services.AddSingleton<IProductRepository, ProductRepository<SqlConnection>> ();
            services.AddSingleton<IUserRepository, UserRepository<SqlConnection>> ();
            services.AddScoped<IProductService, ProductService> ();
            services.AddScoped<IUserService, UserService> ();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure (IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment ()) {
                app.UseDeveloperExceptionPage ();
            }

            app.UseHttpsRedirection ();

            app.UseCors("CorsPolicy");

            app.UseRouting ();

            app.UseAuthorization ();


            app.UseEndpoints (endpoints => {
                endpoints.MapControllers ();
            });
        }
    }
}<file_sep>using System.Linq;
using ECommerce.Demo.Core.Entities;
using ECommerce.Demo.Core.Interfaces;
using Microsoft.EntityFrameworkCore;

namespace ECommerce.Demo.Infrastructure.Repositories.EFRepo.Specs
{
    public class SpecEvaluator<TEntity> where TEntity :BaseEntity
    {
        public static IQueryable<TEntity> GetQuery(IQueryable<TEntity> inputQuery,ISpecification<TEntity> spec){
            var query = inputQuery;

            if(spec.Criteria != null){
                query = query.Where(spec.Criteria);
            }

            if(spec.OrderBy != null){
                query = query.OrderBy(spec.OrderBy);
            }

            if(spec.OrderByDescending != null){
                query = query.OrderByDescending(spec.OrderByDescending);
            }

            if(spec.IsPagingEnabled){
                query = query.Skip(spec.Skip).Take(spec.Take);
            }

            query = spec.Includes.Aggregate(query, (current,include) => current.Include(include));

            return query;
        }
    }
}<file_sep>using API.Domain.DTO;
using AutoMapper;
using ECommerce.Demo.API.Domain.DTO;
using ECommerce.Demo.Core.Entities;

namespace API.Extensions {
    public class AutoMapperProfiles : Profile {
        public AutoMapperProfiles () {
            CreateMap<UserRegisterDto, User> ();
            CreateMap<User, UserDetailDto> ();
            CreateMap<UserLoginDto, UserDetailDto> ();
        }
    }
}<file_sep>exec "/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P \"Your_<PASSWORD>\""
exec "CREATE DATABASE ECommerce"
exec "exit"
<file_sep>using System.Reflection;
using ECommerce.Demo.Core.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace ECommerce.Demo.Infrastructure.Data
{
    public class StoreContext:IdentityDbContext<User, Role, int, IdentityUserClaim<int>, UserRole, IdentityUserLogin<int>, IdentityRoleClaim<int>, IdentityUserToken<int>> 
    {
       public StoreContext (DbContextOptions options) : base (options) { }

        public DbSet<Product> Products { get; set; }
        public DbSet<ProductPrice> ProductPrices {get;set;}
        public DbSet<ProductType> ProductTypes { get; set; }
        public DbSet<ProductBrand> ProductBrands { get; set; }

        protected override void OnModelCreating (ModelBuilder builder) {
            base.OnModelCreating (builder);
            builder.ApplyConfigurationsFromAssembly (Assembly.GetExecutingAssembly ());
            builder.Entity<User> (e => {
                e.ToTable (name: "User");
            });

            builder.Entity<Role> (e => {
                e.ToTable (name: "Role");
            });

            builder.Entity<UserRole> (e => {
                e.ToTable (name: "UserRole");
                e.HasKey (ur => new { ur.UserId, ur.RoleId });
                e.HasOne (ur => ur.Role)
                    .WithMany (r => r.UserRoles)
                    .HasForeignKey (ur => ur.RoleId)
                    .IsRequired ();
                e.HasOne (ur => ur.User)
                    .WithMany (ur => ur.UserRoles)
                    .HasForeignKey (ur => ur.UserId)
                    .IsRequired ();
            });

            builder.Entity<IdentityUserClaim<int>> (e => {
                e.ToTable ("UserClaim");
            });

            builder.Entity<IdentityUserLogin<int>> (e => {
                e.ToTable ("UserLogin");
                e.HasKey (ul => ul.UserId);
            });

            builder.Entity<IdentityUserClaim<int>> (e => {
                e.ToTable ("UserClaim");
                e.HasKey (uc => uc.Id);
            });

            builder.Entity<IdentityRoleClaim<int>> (e => {
                e.ToTable ("RoleClaims");
                e.HasKey (rc => rc.RoleId);
            });

            builder.Entity<IdentityUserToken<int>> (e => {
                e.ToTable ("UserTokens");
                e.HasKey (ut => ut.UserId);
            });

          
        } 
    }
}<file_sep>using System;
using System.Collections.Generic;

namespace ECommerce.Demo.Core.Entities {
    public class Product:BaseEntity {
        public string Name { get; set; }
        public string Description { get; set; }
        public string Type { get; set; }
        public string PictureUrl { get; set; }
        public ProductType ProductType { get; set; }
        public int ProductTypeId { get; set; }
        public ProductBrand ProductBrand { get; set; }
        public int ProductBrandId { get; set; }
        public ICollection<ProductPrice> Prices { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime ModifiedDate { get; set; }

    }
}<file_sep>using System.Collections.Generic;
using ECommerce.Demo.API.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace ECommerce.Demo.API.Controllers {
    public class ProductController : ControllerBase {
        private IProductService _productService;
        private readonly ILogger<ProductController> _logger;
        public ProductController (IProductService productService, ILogger<ProductController> logger) {
            _productService = productService;
            _logger = logger;
            _logger.LogDebug (1, "Test logging");
        }

        [HttpGet ("Hello")]
        public IActionResult Hello () {
            _logger.LogInformation ("hello");
            return Ok ("Hello");
        }

    }
}<file_sep>namespace ECommerce.Demo.Core.Interfaces
{
    public interface IUserRepository
    {
    }
}<file_sep>using System.Threading.Tasks;
using API.Domain.DTO;
using AutoMapper;
using ECommerce.Demo.API.Repositories;
using ECommerce.Demo.Core.Entities;
using ECommerce.Demo.Infrastructure.Data;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;

namespace API.Services {
    public class UserService : IUserService {
        private readonly IUserRepository _userRepository;
        private readonly IUnitOfWork _uow;
        private readonly StoreContext _context;
        private readonly IMapper _mapper;

        public UserService (
            IUnitOfWork uow,
            IUserRepository userRepository,
            StoreContext context,
            IMapper mapper) {
            this._mapper = mapper;
            this._context = context;
            this._uow = uow;
            this._userRepository = userRepository;
        }

        public async Task<UserDetailDto> GetUserAsync (int id) {
            var user = await _context.Users.FirstOrDefaultAsync (u => u.Id == id);
            var userDto = _mapper.Map<User, UserDetailDto> (user);

            return userDto;
        }

        

    }
}<file_sep>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using NLog.Web;

namespace ECommerce.Demo.API {
    public class Program {
        public static void Main (string[] args) {

            var logger = NLog.Web.NLogBuilder.ConfigureNLog ("nlog.config").GetCurrentClassLogger ();
            try {
                logger.Debug ("init main");
                CreateHostBuilder (args).Build ().Run ();
            } catch (Exception ex) {
                logger.Error (ex, "Stopped program because of exception");
                throw;
            } finally {
                NLog.LogManager.Shutdown ();
            }
        }

        public static IHostBuilder CreateHostBuilder (string[] args) =>
            Host.CreateDefaultBuilder (args)
            .ConfigureWebHostDefaults (webBuilder => {
                webBuilder.UseStartup<Startup> ();
            })
            // .ConfigureLogging (logging => {
            //     logging.ClearProviders ();
            //     logging.SetMinimumLevel (Microsoft.Extensions.Logging.LogLevel.Trace);
            // })
            .UseNLog ();
    }
}