diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6d0c20f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +**/bin/ +**/obj/ +**/global.json +**/Dockerfile* +**/.dockerignore* +**/*.user +**/.vs/ + diff --git a/.gitignore b/.gitignore index b14f7ce..46c22b0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,8 @@ /LoggerService/bin /Repository/obj /Repository/bin +/.vs/AccountOwnerServer/v16 +/AccountOwnerServer/*.user +/Tests/obj +/Tests/bin +/.vs/AccountOwnerServer/DesignTimeBuild/*.dtbcache diff --git a/AccountOwnerServer.sln b/AccountOwnerServer.sln index 7620715..13c6893 100644 --- a/AccountOwnerServer.sln +++ b/AccountOwnerServer.sln @@ -1,17 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.3 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AccountOwnerServer", "AccountOwnerServer\AccountOwnerServer.csproj", "{73FB08B8-4033-4116-B3AC-EC8253B024D4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AccountOwnerServer", "AccountOwnerServer\AccountOwnerServer.csproj", "{D9142A6E-9687-4BA4-9CF9-A9AFF006E3DF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Contracts", "Contracts\Contracts.csproj", "{52725034-B791-4DF1-A227-02EDB5BF78E0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Contracts", "Contracts\Contracts.csproj", "{E75B1842-10BD-4BF3-A96A-830220E57332}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggerService", "LoggerService\LoggerService.csproj", "{A190AF01-84DC-40A8-BEF3-C015825C8B30}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggerService", "LoggerService\LoggerService.csproj", "{DA66E4D3-1CDD-407D-9900-FC27F5AF8F06}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Entities", "Entities\Entities.csproj", "{8CD97B3F-C616-469C-80A2-A1B366611487}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entities", "Entities\Entities.csproj", "{3466888D-D523-4180-B3E4-69953F45F520}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repository", "Repository\Repository.csproj", "{CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repository", "Repository\Repository.csproj", "{7EB45A88-65DE-4A64-852A-3B6921B32D2E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{F45A20D5-FE64-49EB-AB95-2C90A0B76164}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,31 +21,35 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|Any CPU.Build.0 = Release|Any CPU - {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|Any CPU.Build.0 = Release|Any CPU - {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|Any CPU.Build.0 = Release|Any CPU - {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|Any CPU.Build.0 = Release|Any CPU - {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|Any CPU.Build.0 = Release|Any CPU + {D9142A6E-9687-4BA4-9CF9-A9AFF006E3DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9142A6E-9687-4BA4-9CF9-A9AFF006E3DF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9142A6E-9687-4BA4-9CF9-A9AFF006E3DF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9142A6E-9687-4BA4-9CF9-A9AFF006E3DF}.Release|Any CPU.Build.0 = Release|Any CPU + {E75B1842-10BD-4BF3-A96A-830220E57332}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E75B1842-10BD-4BF3-A96A-830220E57332}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E75B1842-10BD-4BF3-A96A-830220E57332}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E75B1842-10BD-4BF3-A96A-830220E57332}.Release|Any CPU.Build.0 = Release|Any CPU + {DA66E4D3-1CDD-407D-9900-FC27F5AF8F06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA66E4D3-1CDD-407D-9900-FC27F5AF8F06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA66E4D3-1CDD-407D-9900-FC27F5AF8F06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA66E4D3-1CDD-407D-9900-FC27F5AF8F06}.Release|Any CPU.Build.0 = Release|Any CPU + {3466888D-D523-4180-B3E4-69953F45F520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3466888D-D523-4180-B3E4-69953F45F520}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3466888D-D523-4180-B3E4-69953F45F520}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3466888D-D523-4180-B3E4-69953F45F520}.Release|Any CPU.Build.0 = Release|Any CPU + {7EB45A88-65DE-4A64-852A-3B6921B32D2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EB45A88-65DE-4A64-852A-3B6921B32D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EB45A88-65DE-4A64-852A-3B6921B32D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EB45A88-65DE-4A64-852A-3B6921B32D2E}.Release|Any CPU.Build.0 = Release|Any CPU + {F45A20D5-FE64-49EB-AB95-2C90A0B76164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F45A20D5-FE64-49EB-AB95-2C90A0B76164}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F45A20D5-FE64-49EB-AB95-2C90A0B76164}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F45A20D5-FE64-49EB-AB95-2C90A0B76164}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {86DE07EE-BE1C-4AAB-ADAA-224170CF42B0} + SolutionGuid = {12A94BCC-D511-439A-9D3B-C1253CB1C879} EndGlobalSection EndGlobal diff --git a/AccountOwnerServer/AccountOwnerServer.csproj b/AccountOwnerServer/AccountOwnerServer.csproj index beffa6b..3d26b60 100644 --- a/AccountOwnerServer/AccountOwnerServer.csproj +++ b/AccountOwnerServer/AccountOwnerServer.csproj @@ -1,25 +1,24 @@ - + - netcoreapp2.0 + netcoreapp3.1 - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + - - - - - - - - - - - diff --git a/AccountOwnerServer/Controllers/AccountController.cs b/AccountOwnerServer/Controllers/AccountController.cs new file mode 100644 index 0000000..d9dbd67 --- /dev/null +++ b/AccountOwnerServer/Controllers/AccountController.cs @@ -0,0 +1,78 @@ +using AutoMapper; +using Contracts; +using Entities.DataTransferObjects; +using Entities.Models; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; + +namespace AccountOwnerServer.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class AccountController : Controller + { + private ILoggerManager _logger; + private IRepositoryWrapper _repository; + private IMapper _mapper; + + public AccountController(ILoggerManager logger, IRepositoryWrapper repository, IMapper mapper) + { + _logger = logger; + _repository = repository; + _mapper = mapper; + } + + [HttpGet] + public IActionResult GetAllAccounts() + { + try + { + var accounts = _repository.Account.GetAllAccounts(); + + _logger.LogInfo($"Returned all accounts from database."); + + var accountDtos = _mapper.Map>(accounts); + return Ok(accountDtos); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetAllAccounts action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpPost] + public IActionResult CreateAccount([FromBody]AccountForCreationDto account) + { + try + { + if (account == null) + { + _logger.LogError("Object sent from client is null."); + return BadRequest("Object is null"); + } + + if (!ModelState.IsValid) + { + _logger.LogError("Invalid object sent from client."); + return BadRequest("Invalid model object"); + } + + var accountEntity = _mapper.Map(account); + + _repository.Account.CreateAccount(accountEntity); + _repository.Save(); + + var createdAccount = _mapper.Map(accountEntity); + + return CreatedAtRoute("AccountById", new { id = createdAccount.Id }, createdAccount); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside CreateAccount action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + } +} diff --git a/AccountOwnerServer/Controllers/OwnerController.cs b/AccountOwnerServer/Controllers/OwnerController.cs index dc2850c..1578424 100644 --- a/AccountOwnerServer/Controllers/OwnerController.cs +++ b/AccountOwnerServer/Controllers/OwnerController.cs @@ -1,97 +1,105 @@ -using Contracts; -using Entities.Extensions; +using AutoMapper; +using Contracts; +using Entities.DataTransferObjects; using Entities.Models; using Microsoft.AspNetCore.Mvc; using System; +using System.Collections.Generic; +using System.Linq; namespace AccountOwnerServer.Controllers { - [Route("api/owner")] - public class OwnerController : Controller - { - private ILoggerManager _logger; + [Route("api/owner")] + [ApiController] + public class OwnerController : ControllerBase + { + private ILoggerManager _logger; private IRepositoryWrapper _repository; - - public OwnerController(ILoggerManager logger, IRepositoryWrapper repository) - { - _logger = logger; + private IMapper _mapper; + + public OwnerController(ILoggerManager logger, IRepositoryWrapper repository, IMapper mapper) + { + _logger = logger; _repository = repository; + _mapper = mapper; } - - [HttpGet] - public IActionResult GetAllOwners() - { - try - { - var owners = _repository.Owner.GetAllOwners(); - + + [HttpGet] + public IActionResult GetAllOwners() + { + try + { + var owners = _repository.Owner.GetAllOwners(); _logger.LogInfo($"Returned all owners from database."); - return Ok(owners); - } - catch (Exception ex) - { - _logger.LogError($"Something went wrong inside GetAllOwners action: {ex.Message}"); - return StatusCode(500, "Internal server error"); - } + var ownersResult = _mapper.Map>(owners); + return Ok(ownersResult); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetAllOwners action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } } - [HttpGet("{id}", Name = "OwnerById")] - public IActionResult GetOwnerById(Guid id) - { - try - { - var owner = _repository.Owner.GetOwnerById(id); - - if (owner.IsEmptyObject()) - { - _logger.LogError($"Owner with id: {id}, hasn't been found in db."); - return NotFound(); - } - else - { + [HttpGet("{id}", Name = "OwnerById")] + public IActionResult GetOwnerById(Guid id) + { + try + { + var owner = _repository.Owner.GetOwnerById(id); + if (owner == null) + { + _logger.LogError($"Owner with id: {id}, hasn't been found in db."); + return NotFound(); + } + else + { _logger.LogInfo($"Returned owner with id: {id}"); - return Ok(owner); - } - } - catch (Exception ex) - { - _logger.LogError($"Something went wrong inside GetOwnerById action: {ex.Message}"); - return StatusCode(500, "Internal server error"); - } - } - [HttpGet("{id}/account")] - public IActionResult GetOwnerWithDetails(Guid id) - { - try - { - var owner = _repository.Owner.GetOwnerWithDetails(id); + var ownerResult = _mapper.Map(owner); + return Ok(ownerResult); + } + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetOwnerById action: {ex.Message}"); + return StatusCode(500, "Internal server error"); + } + } - if (owner.IsEmptyObject()) - { - _logger.LogError($"Owner with id: {id}, hasn't been found in db."); - return NotFound(); - } - else - { + [HttpGet("{id}/account")] + public IActionResult GetOwnerWithDetails(Guid id) + { + try + { + var owner = _repository.Owner.GetOwnerWithDetails(id); + if (owner == null) + { + _logger.LogError($"Owner with id: {id}, hasn't been found in db."); + return NotFound(); + } + else + { _logger.LogInfo($"Returned owner with details for id: {id}"); - return Ok(owner); - } - } - catch (Exception ex) - { - _logger.LogError($"Something went wrong inside GetOwnerWithDetails action: {ex.Message}"); - return StatusCode(500, "Internal server error"); + + var ownerResult = _mapper.Map(owner); + return Ok(ownerResult); + } + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetOwnerWithDetails action: {ex.Message}"); + return StatusCode(500, "Internal server error"); } } [HttpPost] - public IActionResult CreateOwner([FromBody]Owner owner) + public IActionResult CreateOwner([FromBody]OwnerForCreationDto owner) { try { - if (owner.IsObjectNull()) + if (owner == null) { _logger.LogError("Owner object sent from client is null."); return BadRequest("Owner object is null"); @@ -103,9 +111,14 @@ public IActionResult CreateOwner([FromBody]Owner owner) return BadRequest("Invalid model object"); } - _repository.Owner.CreateOwner(owner); + var ownerEntity = _mapper.Map(owner); + + _repository.Owner.CreateOwner(ownerEntity); + _repository.Save(); - return CreatedAtRoute("OwnerById", new { id = owner.Id }, owner); + var createdOwner = _mapper.Map(ownerEntity); + + return CreatedAtRoute("OwnerById", new { id = createdOwner.Id }, createdOwner); } catch (Exception ex) { @@ -115,11 +128,11 @@ public IActionResult CreateOwner([FromBody]Owner owner) } [HttpPut("{id}")] - public IActionResult UpdateOwner(Guid id, [FromBody]Owner owner) + public IActionResult UpdateOwner(Guid id, [FromBody]OwnerForUpdateDto owner) { try { - if (owner.IsObjectNull()) + if (owner == null) { _logger.LogError("Owner object sent from client is null."); return BadRequest("Owner object is null"); @@ -131,14 +144,17 @@ public IActionResult UpdateOwner(Guid id, [FromBody]Owner owner) return BadRequest("Invalid model object"); } - var dbOwner = _repository.Owner.GetOwnerById(id); - if (dbOwner.IsEmptyObject()) + var ownerEntity = _repository.Owner.GetOwnerById(id); + if (ownerEntity == null) { _logger.LogError($"Owner with id: {id}, hasn't been found in db."); return NotFound(); } - _repository.Owner.UpdateOwner(dbOwner, owner); + _mapper.Map(owner, ownerEntity); + + _repository.Owner.UpdateOwner(ownerEntity); + _repository.Save(); return NoContent(); } @@ -155,13 +171,14 @@ public IActionResult DeleteOwner(Guid id) try { var owner = _repository.Owner.GetOwnerById(id); - if (owner.IsEmptyObject()) + if (owner == null) { _logger.LogError($"Owner with id: {id}, hasn't been found in db."); return NotFound(); } _repository.Owner.DeleteOwner(owner); + _repository.Save(); return NoContent(); } @@ -172,4 +189,4 @@ public IActionResult DeleteOwner(Guid id) } } } -} +} \ No newline at end of file diff --git a/AccountOwnerServer/Controllers/ValuesController.cs b/AccountOwnerServer/Controllers/ValuesController.cs deleted file mode 100644 index 71841b7..0000000 --- a/AccountOwnerServer/Controllers/ValuesController.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Contracts; -using Entities; -using Entities.Enumerations; -using Entities.Models; - -namespace AccountOwnerServer.Controllers -{ - [Route("api/[controller]")] - public class ValuesController : Controller - { - private ILoggerManager _logger; - private IRepositoryWrapper _repoWrapper; - - public ValuesController(ILoggerManager logger, IRepositoryWrapper repoWrapper) - { - _logger = logger; - _repoWrapper = repoWrapper; - } - // GET api/values - [HttpGet] - public IActionResult Get() - { - //var domesticAccounts = _repoWrapper.Account.FindByCondition(x => x.AccountType.Equals("Domestic")); - var owners = _repoWrapper.Owner.GetAllOwners(); - - _logger.LogInfo("Here is info message from our values controller."); - _logger.LogDebug("Here is debug message from our values controller."); - _logger.LogWarn("Here is warn message from our values controller."); - _logger.LogError("Here is error message from our values controller."); - - return Ok(owners); - } - } -} diff --git a/AccountOwnerServer/Extensions/ServiceExtensions.cs b/AccountOwnerServer/Extensions/ServiceExtensions.cs index 89ac3a5..7e31db1 100644 --- a/AccountOwnerServer/Extensions/ServiceExtensions.cs +++ b/AccountOwnerServer/Extensions/ServiceExtensions.cs @@ -6,10 +6,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Repository; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace AccountOwnerServer.Extensions { @@ -22,16 +18,15 @@ public static void ConfigureCors(this IServiceCollection services) options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin() .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); + .AllowAnyHeader()); }); } public static void ConfigureIISIntegration(this IServiceCollection services) { - services.Configure(options => + services.Configure(options => { - + }); } @@ -40,15 +35,15 @@ public static void ConfigureLoggerService(this IServiceCollection services) services.AddSingleton(); } - public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config) + public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config) { - var connectionString = config["mysqlconnection:connectionString"]; + var connectionString = config["mysqlconnection:connectionString"]; services.AddDbContext(o => o.UseMySql(connectionString)); } - public static void ConfigureRepositoryWrapper(this IServiceCollection services) - { - services.AddScoped(); + public static void ConfigureRepositoryWrapper(this IServiceCollection services) + { + services.AddScoped(); } } } diff --git a/AccountOwnerServer/MappingProfile.cs b/AccountOwnerServer/MappingProfile.cs new file mode 100644 index 0000000..8bf056e --- /dev/null +++ b/AccountOwnerServer/MappingProfile.cs @@ -0,0 +1,27 @@ +using AutoMapper; +using Entities.DataTransferObjects; +using Entities.Models; +using System.Linq; + +namespace AccountOwnerServer +{ + public class MappingProfile : Profile + { + public MappingProfile() + { + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + + CreateMap(); + } + } +} diff --git a/AccountOwnerServer/Program.cs b/AccountOwnerServer/Program.cs index 0be0d38..7131aeb 100644 --- a/AccountOwnerServer/Program.cs +++ b/AccountOwnerServer/Program.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace AccountOwnerServer @@ -14,12 +13,14 @@ public class Program { public static void Main(string[] args) { - BuildWebHost(args).Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } diff --git a/AccountOwnerServer/Properties/launchSettings.json b/AccountOwnerServer/Properties/launchSettings.json index 348af13..4b82d54 100644 --- a/AccountOwnerServer/Properties/launchSettings.json +++ b/AccountOwnerServer/Properties/launchSettings.json @@ -1,27 +1,28 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:5000/", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": false, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "AccountOwnerServer": { - "commandName": "Project", - "launchBrowser": false, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:5000/" - } - } -} +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://0.0.0.0:5000", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "AccountOwnerServer": { + "commandName": "Project", + "launchBrowser": false, + "applicationUrl": "http://0.0.0.0:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/AccountOwnerServer/Startup.cs b/AccountOwnerServer/Startup.cs index 3a86fc4..c132c1b 100644 --- a/AccountOwnerServer/Startup.cs +++ b/AccountOwnerServer/Startup.cs @@ -1,75 +1,83 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using AccountOwnerServer.Extensions; +using AutoMapper; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using AccountOwnerServer.Extensions; -using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; +using NLog; using System.IO; -using NLog.Extensions.Logging; -using Contracts; namespace AccountOwnerServer { - public class Startup - { - public Startup(IConfiguration configuration, ILoggerFactory loggerFactory) - { - loggerFactory.ConfigureNLog(String.Concat(Directory.GetCurrentDirectory(), "/nlog.config")); - Configuration = configuration; - } - - public IConfiguration Configuration { get; } + public class Startup + { + public Startup(IConfiguration configuration) + { + LogManager.LoadConfiguration(string.Concat(Directory.GetCurrentDirectory(), "/nlog.config")); + Configuration = configuration; + } - public void ConfigureServices(IServiceCollection services) - { - services.ConfigureCors(); + public IConfiguration Configuration { get; } - services.ConfigureIISIntegration(); + public void ConfigureServices(IServiceCollection services) + { + services.ConfigureCors(); + services.ConfigureIISIntegration(); + services.ConfigureLoggerService(); + services.ConfigureMySqlContext(Configuration); + services.ConfigureRepositoryWrapper(); + services.AddAutoMapper(typeof(Startup)); - services.ConfigureLoggerService(); + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo + { + Title = "AccountOwner API", + Version = "v1" + }); + }); - services.ConfigureMySqlContext(Configuration); + services.AddControllers(); + } - services.ConfigureRepositoryWrapper(); + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } - services.AddMvc(); - } + app.UseHttpsRedirection(); + app.UseStaticFiles(); - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } + app.UseCors("CorsPolicy"); - app.UseCors("CorsPolicy"); + app.UseForwardedHeaders(new ForwardedHeadersOptions + { + ForwardedHeaders = ForwardedHeaders.All + }); - app.UseForwardedHeaders(new ForwardedHeadersOptions - { - ForwardedHeaders = ForwardedHeaders.All - }); + app.UseRouting(); - app.Use(async (context, next) => - { - await next(); + app.UseAuthorization(); - if (context.Response.StatusCode == 404 - && !Path.HasExtension(context.Request.Path.Value)) - { - context.Request.Path = "/index.html"; - await next(); - } - }); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); - app.UseStaticFiles(); + // Enable middleware to serve generated Swagger as a JSON endpoint. + app.UseSwagger(); - app.UseMvc(); - } - } + // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), + // specifying the Swagger JSON endpoint. + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "AccountOwner API V1"); + }); + } + } } diff --git a/AccountOwnerServer/appsettings.Development.json b/AccountOwnerServer/appsettings.Development.json index fa8ce71..e203e94 100644 --- a/AccountOwnerServer/appsettings.Development.json +++ b/AccountOwnerServer/appsettings.Development.json @@ -1,6 +1,5 @@ -{ +{ "Logging": { - "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", diff --git a/AccountOwnerServer/appsettings.json b/AccountOwnerServer/appsettings.json index 934ec46..2c0f849 100644 --- a/AccountOwnerServer/appsettings.json +++ b/AccountOwnerServer/appsettings.json @@ -1,18 +1,13 @@ -{ - "Logging": { - "IncludeScopes": false, - "Debug": { - "LogLevel": { - "Default": "Warning" - } - }, - "Console": { - "LogLevel": { - "Default": "Warning" - } - } - }, - "mysqlconnection": { - "connectionString": "server=localhost;userid=dbuser;password=pass;database=accountowner;" - } +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "mysqlconnection": { + "connectionString": "server=db;port=3306;userid=dbuser;password=dbuserpassword;database=accountowner;" + }, + "AllowedHosts": "*" } diff --git a/AccountOwnerServer/nlog.config b/AccountOwnerServer/nlog.config index 91c2174..47744e0 100644 --- a/AccountOwnerServer/nlog.config +++ b/AccountOwnerServer/nlog.config @@ -5,10 +5,6 @@ internalLogLevel="Trace" internalLogFile="d:Projects\Blog-AccountOwner\Project\internal_logs\internallog.txt"> - - - - - netcoreapp2.0 + netcoreapp3.1 diff --git a/Contracts/IAccountRepository.cs b/Contracts/IAccountRepository.cs index 825a4fb..776ae31 100644 --- a/Contracts/IAccountRepository.cs +++ b/Contracts/IAccountRepository.cs @@ -1,8 +1,11 @@ using Entities.Models; +using System.Collections.Generic; namespace Contracts { - public interface IAccountRepository - { - } + public interface IAccountRepository : IRepositoryBase + { + IEnumerable GetAllAccounts(); + void CreateAccount(Account account); + } } diff --git a/Contracts/ILoggerManager.cs b/Contracts/ILoggerManager.cs index 7dcd872..ee1f081 100644 --- a/Contracts/ILoggerManager.cs +++ b/Contracts/ILoggerManager.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Contracts +namespace Contracts { public interface ILoggerManager { diff --git a/Contracts/IOwnerRepository.cs b/Contracts/IOwnerRepository.cs index da31e25..d82d2a8 100644 --- a/Contracts/IOwnerRepository.cs +++ b/Contracts/IOwnerRepository.cs @@ -1,17 +1,16 @@ -using Entities.ExtendedModels; -using Entities.Models; +using Entities.Models; using System; using System.Collections.Generic; namespace Contracts { - public interface IOwnerRepository + public interface IOwnerRepository : IRepositoryBase { IEnumerable GetAllOwners(); Owner GetOwnerById(Guid ownerId); - OwnerExtended GetOwnerWithDetails(Guid ownerId); + Owner GetOwnerWithDetails(Guid ownerId); void CreateOwner(Owner owner); - void UpdateOwner(Owner dbOwner, Owner owner); + void UpdateOwner(Owner owner); void DeleteOwner(Owner owner); } } diff --git a/Contracts/IRepositoryBase.cs b/Contracts/IRepositoryBase.cs index 336894d..7a2b84b 100644 --- a/Contracts/IRepositoryBase.cs +++ b/Contracts/IRepositoryBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Text; @@ -7,11 +8,10 @@ namespace Contracts { public interface IRepositoryBase { - IEnumerable FindAll(); - IEnumerable FindByCondition(Expression> expression); - void Create(T entity); - void Update(T entity); + IQueryable FindAll(); + IQueryable FindByCondition(Expression> expression); + void Create(T entity); + void Update(T entity); void Delete(T entity); - void Save(); } } diff --git a/Contracts/IRepositoryWrapper.cs b/Contracts/IRepositoryWrapper.cs index f4275a1..445d2f7 100644 --- a/Contracts/IRepositoryWrapper.cs +++ b/Contracts/IRepositoryWrapper.cs @@ -4,9 +4,10 @@ namespace Contracts { - public interface IRepositoryWrapper - { - IOwnerRepository Owner { get; } - IAccountRepository Account { get; } + public interface IRepositoryWrapper + { + IOwnerRepository Owner { get; } + IAccountRepository Account { get; } + void Save(); } } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..edc400e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build-image + +WORKDIR /home/app + +COPY ./*.sln ./ +COPY ./*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done + +RUN dotnet restore + +COPY . . + +RUN dotnet test ./Tests/Tests.csproj + +RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ + +FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 + +WORKDIR /publish + +COPY --from=build-image /publish . + +ENV ASPNETCORE_URLS="http://0.0.0.0:5000" + +ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] \ No newline at end of file diff --git a/Entities/DataTransferObjects/AccountDto.cs b/Entities/DataTransferObjects/AccountDto.cs new file mode 100644 index 0000000..ef800f3 --- /dev/null +++ b/Entities/DataTransferObjects/AccountDto.cs @@ -0,0 +1,11 @@ +using System; + +namespace Entities.DataTransferObjects +{ + public class AccountDto + { + public Guid Id { get; set; } + public DateTime DateCreated { get; set; } + public string AccountType { get; set; } + } +} diff --git a/Entities/DataTransferObjects/AccountForCreationDto.cs b/Entities/DataTransferObjects/AccountForCreationDto.cs new file mode 100644 index 0000000..8fde44f --- /dev/null +++ b/Entities/DataTransferObjects/AccountForCreationDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace Entities.DataTransferObjects +{ + public class AccountForCreationDto + { + public DateTime DateCreated { get; set; } + public string AccountType { get; set; } + } +} diff --git a/Entities/DataTransferObjects/AccountForUpdateDto.cs b/Entities/DataTransferObjects/AccountForUpdateDto.cs new file mode 100644 index 0000000..9d75fa3 --- /dev/null +++ b/Entities/DataTransferObjects/AccountForUpdateDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace Entities.DataTransferObjects +{ + public class AccountForUpdateDto + { + public DateTime DateCreated { get; set; } + public string AccountType { get; set; } + } +} diff --git a/Entities/DataTransferObjects/OwnerDto.cs b/Entities/DataTransferObjects/OwnerDto.cs new file mode 100644 index 0000000..cdbdddc --- /dev/null +++ b/Entities/DataTransferObjects/OwnerDto.cs @@ -0,0 +1,17 @@ +using Entities.Models; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Entities.DataTransferObjects +{ + public class OwnerDto + { + public Guid Id { get; set; } + public string Name { get; set; } + public DateTime DateOfBirth { get; set; } + public string Address { get; set; } + + public IEnumerable Accounts { get; set; } + } +} diff --git a/Entities/DataTransferObjects/OwnerForCreationDto.cs b/Entities/DataTransferObjects/OwnerForCreationDto.cs new file mode 100644 index 0000000..18595f6 --- /dev/null +++ b/Entities/DataTransferObjects/OwnerForCreationDto.cs @@ -0,0 +1,19 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Entities.DataTransferObjects +{ + public class OwnerForCreationDto + { + [Required(ErrorMessage = "Name is required")] + [StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")] + public string Name { get; set; } + + [Required(ErrorMessage = "Date of birth is required")] + public DateTime DateOfBirth { get; set; } + + [Required(ErrorMessage = "Address is required")] + [StringLength(100, ErrorMessage = "Address cannot be loner then 100 characters")] + public string Address { get; set; } + } +} diff --git a/Entities/DataTransferObjects/OwnerForUpdateDto.cs b/Entities/DataTransferObjects/OwnerForUpdateDto.cs new file mode 100644 index 0000000..5bd7702 --- /dev/null +++ b/Entities/DataTransferObjects/OwnerForUpdateDto.cs @@ -0,0 +1,19 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Entities.DataTransferObjects +{ + public class OwnerForUpdateDto + { + [Required(ErrorMessage = "Name is required")] + [StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")] + public string Name { get; set; } + + [Required(ErrorMessage = "Date of birth is required")] + public DateTime DateOfBirth { get; set; } + + [Required(ErrorMessage = "Address is required")] + [StringLength(100, ErrorMessage = "Address cannot be loner then 100 characters")] + public string Address { get; set; } + } +} diff --git a/Entities/Entities.csproj b/Entities/Entities.csproj index 4de557e..01886ec 100644 --- a/Entities/Entities.csproj +++ b/Entities/Entities.csproj @@ -1,11 +1,11 @@ - netcoreapp2.0 + netcoreapp3.1 - + diff --git a/Entities/Enumerations/AccountType.cs b/Entities/Enumerations/AccountType.cs deleted file mode 100644 index 7cad9c9..0000000 --- a/Entities/Enumerations/AccountType.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Entities.Enumerations -{ - public enum AccountType - { - Domestic, - Savings, - Foreign - } -} diff --git a/Entities/ExtendedModels/OwnerExtended.cs b/Entities/ExtendedModels/OwnerExtended.cs deleted file mode 100644 index 87b8126..0000000 --- a/Entities/ExtendedModels/OwnerExtended.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Entities.Models; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Entities.ExtendedModels -{ - public class OwnerExtended: IEntity - { - public Guid Id { get; set; } - public string Name { get; set; } - public DateTime DateOfBirth { get; set; } - public string Address { get; set; } - - public IEnumerable Accounts { get; set; } - - public OwnerExtended() - { - } - - public OwnerExtended(Owner owner) - { - Id = owner.Id; - Name = owner.Name; - DateOfBirth = owner.DateOfBirth; - Address = owner.Address; - } - } -} diff --git a/Entities/Extensions/IEntityExtensions.cs b/Entities/Extensions/IEntityExtensions.cs deleted file mode 100644 index 992fca0..0000000 --- a/Entities/Extensions/IEntityExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Entities.Extensions -{ - public static class IEntityExtensions - { - public static bool IsObjectNull(this IEntity entity) - { - return entity == null; - } - - public static bool IsEmptyObject(this IEntity entity) - { - return entity.Id.Equals(Guid.Empty); - } - } -} diff --git a/Entities/Extensions/OwnerExtensions.cs b/Entities/Extensions/OwnerExtensions.cs deleted file mode 100644 index 03e8a0a..0000000 --- a/Entities/Extensions/OwnerExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Entities.Models; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Entities.Extensions -{ - public static class OwnerExtensions - { - public static void Map(this Owner dbOwner, Owner owner) - { - dbOwner.Name = owner.Name; - dbOwner.Address = owner.Address; - dbOwner.DateOfBirth = owner.DateOfBirth; - } - } -} diff --git a/Entities/IEntity.cs b/Entities/IEntity.cs deleted file mode 100644 index 8dcadc4..0000000 --- a/Entities/IEntity.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Entities -{ - public interface IEntity - { - Guid Id { get; set; } - } -} diff --git a/Entities/Models/Account.cs b/Entities/Models/Account.cs index 105d588..073d248 100644 --- a/Entities/Models/Account.cs +++ b/Entities/Models/Account.cs @@ -1,26 +1,25 @@ -using Entities.Enumerations; -using System; -using System.Collections.Generic; +using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Text; namespace Entities.Models { - [Table("account")] - public class Account : IEntity + [Table("account")] + public class Account { - [Key] [Column("AccountId")] public Guid Id { get; set; } - [Required(ErrorMessage = "Date created is required")] + [Required(ErrorMessage = "Date created is required")] public DateTime DateCreated { get; set; } - [Required(ErrorMessage = "Account type is required")] + [Required(ErrorMessage = "Account type is required")] public string AccountType { get; set; } - [Required(ErrorMessage = "Owner Id is required")] + [Required(ErrorMessage = "Owner Id is required")] + + [ForeignKey(nameof(Owner))] public Guid OwnerId { get; set; } + public Owner Owner { get; set; } } } diff --git a/Entities/Models/Owner.cs b/Entities/Models/Owner.cs index d52a756..36c3b07 100644 --- a/Entities/Models/Owner.cs +++ b/Entities/Models/Owner.cs @@ -2,26 +2,26 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -using System.Text; namespace Entities.Models { - [Table("owner")] - public class Owner: IEntity - { - [Key] + [Table("owner")] + public class Owner + { [Column("OwnerId")] public Guid Id { get; set; } - [Required(ErrorMessage = "Name is required")] - [StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")] + [Required(ErrorMessage = "Name is required")] + [StringLength(60, ErrorMessage = "Name can't be longer than 60 characters")] public string Name { get; set; } - [Required(ErrorMessage = "Date of birth is required")] + [Required(ErrorMessage = "Date of birth is required")] public DateTime DateOfBirth { get; set; } - [Required(ErrorMessage = "Address is required")] - [StringLength(100, ErrorMessage = "Address can not be loner then 100 characters")] + [Required(ErrorMessage = "Address is required")] + [StringLength(100, ErrorMessage = "Address cannot be loner then 100 characters")] public string Address { get; set; } + + public ICollection Accounts { get; set; } } } diff --git a/Entities/RepositoryContext.cs b/Entities/RepositoryContext.cs index 5687078..14a2d7b 100644 --- a/Entities/RepositoryContext.cs +++ b/Entities/RepositoryContext.cs @@ -3,11 +3,11 @@ namespace Entities { - public class RepositoryContext: DbContext + public class RepositoryContext : DbContext { - public RepositoryContext(DbContextOptions options) - :base(options) - { + public RepositoryContext(DbContextOptions options) + : base(options) + { } public DbSet Owners { get; set; } diff --git a/LoggerService/LoggerManager.cs b/LoggerService/LoggerManager.cs index b5d93f1..bf2f7be 100644 --- a/LoggerService/LoggerManager.cs +++ b/LoggerService/LoggerManager.cs @@ -1,6 +1,5 @@ using Contracts; using NLog; -using System; namespace LoggerService { @@ -8,10 +7,6 @@ public class LoggerManager : ILoggerManager { private static ILogger logger = LogManager.GetCurrentClassLogger(); - public LoggerManager() - { - } - public void LogDebug(string message) { logger.Debug(message); diff --git a/LoggerService/LoggerService.csproj b/LoggerService/LoggerService.csproj index 885b749..f24e41a 100644 --- a/LoggerService/LoggerService.csproj +++ b/LoggerService/LoggerService.csproj @@ -1,11 +1,11 @@ - netcoreapp2.0 + netcoreapp3.1 - + diff --git a/README.md b/README.md index 226a577..a6d49a5 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ # Docker Series +https://code-maze.com/docker-series/ + +## Part 4 of the Docker Series on CodeMaze blog +https://code-maze.com/mysql-aspnetcore-docker-compose/ diff --git a/Repository/AccountRepository.cs b/Repository/AccountRepository.cs index 9dcb2d5..4fa3623 100644 --- a/Repository/AccountRepository.cs +++ b/Repository/AccountRepository.cs @@ -1,14 +1,29 @@ using Contracts; using Entities; using Entities.Models; +using System; +using System.Collections.Generic; +using System.Linq; namespace Repository { - public class AccountRepository: RepositoryBase, IAccountRepository - { - public AccountRepository(RepositoryContext repositoryContext) - :base(repositoryContext) + public class AccountRepository : RepositoryBase, IAccountRepository + { + public AccountRepository(RepositoryContext repositoryContext) + : base(repositoryContext) + { + } + + public IEnumerable GetAllAccounts() + { + return FindAll() + .OrderBy(ac => ac.DateCreated); + } + + public void CreateAccount(Account account) { + account.Id = Guid.NewGuid(); + Create(account); } } } diff --git a/Repository/OwnerRepository.cs b/Repository/OwnerRepository.cs index 60422c8..ac72bb2 100644 --- a/Repository/OwnerRepository.cs +++ b/Repository/OwnerRepository.cs @@ -1,61 +1,53 @@ using Contracts; using Entities; using Entities.Models; +using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.Linq; -using System; -using Entities.ExtendedModels; -using Entities.Extensions; namespace Repository { - public class OwnerRepository: RepositoryBase, IOwnerRepository - { - public OwnerRepository(RepositoryContext repositoryContext) - :base(repositoryContext) - { + public class OwnerRepository : RepositoryBase, IOwnerRepository + { + public OwnerRepository(RepositoryContext repositoryContext) + : base(repositoryContext) + { } - public IEnumerable GetAllOwners() - { + public IEnumerable GetAllOwners() + { return FindAll() - .OrderBy(ow => ow.Name); + .OrderBy(ow => ow.Name) + .ToList(); } public Owner GetOwnerById(Guid ownerId) { return FindByCondition(owner => owner.Id.Equals(ownerId)) - .DefaultIfEmpty(new Owner()) - .FirstOrDefault(); + .FirstOrDefault(); } - public OwnerExtended GetOwnerWithDetails(Guid ownerId) + public Owner GetOwnerWithDetails(Guid ownerId) { - return new OwnerExtended(GetOwnerById(ownerId)) - { - Accounts = RepositoryContext.Accounts - .Where(a => a.OwnerId == ownerId) - }; + return FindByCondition(owner => owner.Id.Equals(ownerId)) + .Include(ac => ac.Accounts) + .FirstOrDefault(); } public void CreateOwner(Owner owner) { - owner.Id = Guid.NewGuid(); Create(owner); - Save(); } - public void UpdateOwner(Owner dbOwner, Owner owner) + public void UpdateOwner(Owner owner) { - dbOwner.Map(owner); - Update(dbOwner); - Save(); + Update(owner); } public void DeleteOwner(Owner owner) { Delete(owner); - Save(); } } } diff --git a/Repository/Repository.csproj b/Repository/Repository.csproj index e1eecf3..a2fe898 100644 --- a/Repository/Repository.csproj +++ b/Repository/Repository.csproj @@ -1,16 +1,11 @@ - netcoreapp2.0 + netcoreapp3.1 - - - - - diff --git a/Repository/RepositoryBase.cs b/Repository/RepositoryBase.cs index 64aa6af..5fdacee 100644 --- a/Repository/RepositoryBase.cs +++ b/Repository/RepositoryBase.cs @@ -1,7 +1,7 @@ using Contracts; using Entities; +using Microsoft.EntityFrameworkCore; using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -9,41 +9,35 @@ namespace Repository { public abstract class RepositoryBase : IRepositoryBase where T : class { - protected RepositoryContext RepositoryContext { get; set; } - - public RepositoryBase(RepositoryContext repositoryContext) - { - this.RepositoryContext = repositoryContext; - } - - public IEnumerable FindAll() - { - return this.RepositoryContext.Set(); - } - - public IEnumerable FindByCondition(Expression> expression) - { - return this.RepositoryContext.Set().Where(expression); - } - - public void Create(T entity) + protected RepositoryContext RepositoryContext { get; set; } + public RepositoryBase(RepositoryContext repositoryContext) { - this.RepositoryContext.Set().Add(entity); - } - - public void Update(T entity) + RepositoryContext = repositoryContext; + } + + public IQueryable FindAll() + { + return RepositoryContext.Set().AsNoTracking(); + } + + public IQueryable FindByCondition(Expression> expression) + { + return RepositoryContext.Set().Where(expression).AsNoTracking(); + } + + public void Create(T entity) + { + RepositoryContext.Set().Add(entity); + } + + public void Update(T entity) { - this.RepositoryContext.Set().Update(entity); - } - + RepositoryContext.Set().Update(entity); + } + public void Delete(T entity) - { - this.RepositoryContext.Set().Remove(entity); - } - - public void Save() - { - this.RepositoryContext.SaveChanges(); + { + RepositoryContext.Set().Remove(entity); } } } diff --git a/Repository/RepositoryWrapper.cs b/Repository/RepositoryWrapper.cs index d8be3f9..01a8b10 100644 --- a/Repository/RepositoryWrapper.cs +++ b/Repository/RepositoryWrapper.cs @@ -3,41 +3,43 @@ namespace Repository { - public class RepositoryWrapper : IRepositoryWrapper - { - private RepositoryContext _repoContext; - private IOwnerRepository _owner; - private IAccountRepository _account; - - public IOwnerRepository Owner - { - get - { - if (_owner == null) - { - _owner = new OwnerRepository(_repoContext); - } - - return _owner; - } - } - - public IAccountRepository Account - { - get - { - if (_account == null) - { - _account = new AccountRepository(_repoContext); - } - - return _account; - } - } - - public RepositoryWrapper(RepositoryContext repositoryContext) + public class RepositoryWrapper : IRepositoryWrapper + { + private RepositoryContext _repoContext; + private IOwnerRepository _owner; + private IAccountRepository _account; + public IOwnerRepository Owner + { + get + { + if (_owner == null) + { + _owner = new OwnerRepository(_repoContext); + } + return _owner; + } + } + + public IAccountRepository Account + { + get + { + if (_account == null) + { + _account = new AccountRepository(_repoContext); + } + return _account; + } + } + + public RepositoryWrapper(RepositoryContext repositoryContext) + { + _repoContext = repositoryContext; + } + + public void Save() { - _repoContext = repositoryContext; - } + _repoContext.SaveChanges(); + } } } diff --git a/Tests/OwnerRepositoryTests.cs b/Tests/OwnerRepositoryTests.cs new file mode 100644 index 0000000..0d5e4bf --- /dev/null +++ b/Tests/OwnerRepositoryTests.cs @@ -0,0 +1,42 @@ +using Contracts; +using Entities.Models; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Tests +{ + public class OwnerRepositoryTests + { + [Fact] + public void GetAllOwners_ReturnsListOfOwners_WithSingleOwner() + { + // Arrange + var mockRepo = new Mock(); + mockRepo.Setup(repo => (repo.GetAllOwners())).Returns(GetOwners()); + + // Act + var result = mockRepo.Object.GetAllOwners().ToList(); + + // Assert + Assert.IsType>(result); + Assert.Single(result); + } + + public List GetOwners() + { + return new List + { + new Owner + { + Id = Guid.NewGuid(), + Name = "John Keen", + DateOfBirth = new DateTime(1980, 12, 05), + Address = "61 Wellfield Road" + } + }; + } + } +} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj new file mode 100644 index 0000000..61e4405 --- /dev/null +++ b/Tests/Tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6d95a75 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.0' + +services: + db: + image: mysql:5.7 + environment: + MYSQL_RANDOM_ROOT_PASSWORD: 1 + MYSQL_DATABASE: accountowner + MYSQL_USER: dbuser + MYSQL_PASSWORD: dbuserpassword + volumes: + - dbdata:/var/lib/mysql + - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + restart: always + + accountownerapp: + depends_on: + - db + image: codemazeblog/accountowner:runtime + build: + context: . + ports: + - "8080:5000" + +volumes: + dbdata: \ No newline at end of file