Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Response Perfomance Improvement Completed #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Contracts/RepositoryContracts/ICompanyRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ namespace Contracts.RepositoryContracts;
public interface ICompanyRepository : IRepositoryBase<Company>
{

Task<IEnumerable<Company>> GetAllCompaniesAsync(bool trackChanges);
Task<Company> GetCompanyAsync(Guid companyId, bool trackChanges);
// Task<IEnumerable<Company>> GetAllCompaniesAsync(bool trackChanges);
IEnumerable<Company> GetAllCompanies(bool trackChanges);
// Task<Company> GetCompanyAsync(Guid companyId, bool trackChanges);
Company GetCompany(Guid companyId, bool trackChanges);
void CreateCompany(Company company);
Task<IEnumerable<Company>> GetByIdsAsync(IEnumerable<Guid> ids, bool trackChanges);
void DeleteCompany(Company company);
Expand Down
9 changes: 7 additions & 2 deletions Contracts/ServiceContracts/ICompanyService.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@

using Entities.DTO;
using Entities.Responses;

namespace Contracts.ServiceContracts;

public interface ICompanyService
{
Task<IEnumerable<CompanyDto>> GetAllCompaniesAsync(bool trackChanges);
Task<CompanyDto> GetCompanyAsync(Guid companyId, bool trackChanges);
// Task<IEnumerable<CompanyDto>> GetAllCompaniesAsync(bool trackChanges);
ApiBaseResponse GetAllCompanies(bool trackChanges);
// Task<CompanyDto> GetCompanyAsync(Guid companyId, bool trackChanges);
ApiBaseResponse GetCompany(Guid companyId, bool trackChanges);


Task<CompanyDto> CreateCompanyAsync(CompanyForCreationDto company);
Task<IEnumerable<CompanyDto>> GetByIdsAsync(IEnumerable<Guid> ids, bool trackChanges);
Task<(IEnumerable<CompanyDto> companies, string ids)> CreateCompanyCollectionAsync(IEnumerable<CompanyForCreationDto> companyCollection);
Expand Down
6 changes: 6 additions & 0 deletions Entities/Responses/ApiBadRequestResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Entities.Responses;

public abstract class ApiBadRequestResponse(string message) : ApiBaseResponse(false)
{
public string Message { get; set; } = message;
}
6 changes: 6 additions & 0 deletions Entities/Responses/ApiBaseResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Entities.Responses;

public abstract class ApiBaseResponse(bool success)
{
public bool Success { get; set; } = success;
}
6 changes: 6 additions & 0 deletions Entities/Responses/ApiNotFoundResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Entities.Responses;

public abstract class ApiNotFoundResponse(string message) : ApiBaseResponse(false)
{
public string Message { get; set; } = message;
}
6 changes: 6 additions & 0 deletions Entities/Responses/ApiOkResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Entities.Responses;

public sealed class ApiOkResponse<TResult>(TResult result) : ApiBaseResponse(true)
{
public TResult Result { get; set; } = result;
}
8 changes: 8 additions & 0 deletions Entities/Responses/CompanyNotFoundResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Entities.Responses;

public sealed class CompanyNotFoundResponse : ApiNotFoundResponse
{
public CompanyNotFoundResponse(Guid id) : base($"Company with id: {id} is not found in db.")
{
}
}
27 changes: 27 additions & 0 deletions Presentation/Controllers/ApiControllerBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Entities.ErrorModel;
using Entities.Responses;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Presentation.Controllers;

public class ApiControllerBase : ControllerBase
{
public IActionResult ProcessError(ApiBaseResponse baseResponse)
{
return baseResponse switch
{
ApiNotFoundResponse => NotFound(new ErrorDetails
{
Message = ((ApiNotFoundResponse)baseResponse).Message,
StatusCode = StatusCodes.Status404NotFound
}),
ApiBadRequestResponse => BadRequest(new ErrorDetails
{
Message = ((ApiBadRequestResponse)baseResponse).Message,
StatusCode = StatusCodes.Status400BadRequest
}),
_ => throw new NotImplementedException()
};
}
}
2 changes: 1 addition & 1 deletion Presentation/Controllers/AuthenticationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Entities.DTO;
using Microsoft.AspNetCore.Mvc;

namespace CompanyEmployees.Presentation.Controllers;
namespace Presentation.Controllers;

[Route("api/[controller]")]
[ApiController]
Expand Down
29 changes: 18 additions & 11 deletions Presentation/Controllers/CompaniesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,46 @@
using CompanyEmployees.Presentation.ModelBinders;
using Contracts.ServiceContracts;
using Entities.DTO;
using Entities.Responses;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Presentation.Extensions;

namespace CompanyEmployees.Presentation.Controllers;
namespace Presentation.Controllers;

[ApiVersion("1.0")]
[Route("api/companies")]
[ApiController]
[ApiExplorerSettings(GroupName = "v1")]
public class CompaniesController(IServiceManager service) : ControllerBase
public class CompaniesController(IServiceManager service) : ApiControllerBase
{
private readonly IServiceManager _service = service;

/// <summary>
/// Gets the list of all companies
/// </summary>
/// <returns>The companies list</returns>
// [HttpHead]
[HttpGet]
[Authorize]
[Authorize(Roles = "Manager")]
public async Task<IActionResult> GetCompanies()
// public async Task<IActionResult> GetCompanies()
public IActionResult GetCompanies()
{
var companies = await _service.CompanyService.GetAllCompaniesAsync(trackChanges: false);
// var companies = await _service.CompanyService.GetAllCompaniesAsync(trackChanges: false);

var baseResult = _service.CompanyService.GetAllCompanies(trackChanges: false);
// var companies = ((ApiOkResponse<IEnumerable<CompanyDto>>)baseResult).Result;
var companies = baseResult.GetResult<IEnumerable<CompanyDto>>();
return Ok(companies);
}


[HttpGet("{id:guid}", Name = "CompanyById")]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> GetCompany(Guid id)
// public async Task<IActionResult> GetCompany(Guid id)
public IActionResult GetCompany(Guid id)
{
var company = await _service.CompanyService.GetCompanyAsync(id, trackChanges: false);
// var company = await _service.CompanyService.GetCompanyAsync(id, trackChanges: false);
var baseResult = _service.CompanyService.GetCompany(id, trackChanges: false);
if (!baseResult.Success) return ProcessError(baseResult);
// var company = ((ApiOkResponse<CompanyDto>)baseResult).Result;
var company = baseResult.GetResult<CompanyDto>();
return Ok(company);
}

Expand Down
12 changes: 7 additions & 5 deletions Presentation/Controllers/CompaniesV2Controller.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Contracts.ServiceContracts;
using Microsoft.AspNetCore.Mvc;

namespace CompanyEmployees.Presentation.Controllers;
namespace Presentation.Controllers;

[ApiVersion("2.0", Deprecated = true)] //artık kullanılmayan sürümleri deprecated olarak işaretleyebiliriz. böylece responsun header bölümünde kullanıcı artık bu apinin kullanılmadığını anlar
// [Route("api/{v:apiversion}/companies")] //url api versioning için. ama header versioning kullandığımız için yoruma aldık
Expand All @@ -13,11 +13,13 @@ public class CompaniesV2Controller(IServiceManager service) : ControllerBase
private readonly IServiceManager _service = service;

[HttpGet]
public async Task<IActionResult> GetCompanies()
// public async Task<IActionResult> GetCompanies()
public IActionResult GetCompanies()
{
var companies = await _service.CompanyService.GetAllCompaniesAsync(trackChanges: false);
// var companies = await _service.CompanyService.GetAllCompaniesAsync(trackChanges: false);
// return Ok(companies);
var companiesV2 = companies.Select(x => $"{x.Name} V2");
return Ok(companiesV2);
// var companiesV2 = companies.Select(x => $"{x.Name} V2");
var companies = _service.CompanyService.GetAllCompanies(trackChanges: false);
return Ok(companies);
}
}
2 changes: 1 addition & 1 deletion Presentation/Controllers/EmpoyeesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace CompanyEmployees.Presentation.Controllers;
namespace Presentation.Controllers;

// Alternatif olarak, /api/employees gibi düz bir yapı da kullanılabilirdi, ancak mevcut yapı daha zengin ve ilişkisel bir API tasarımı sunar. Bu, özellikle karmaşık iş mantığı ve veri ilişkileri olan sistemlerde faydalıdır.
[Route("api/companies/{companyId}/[controller]")]
Expand Down
4 changes: 2 additions & 2 deletions Presentation/Controllers/TokenController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Entities.DTO;
using Microsoft.AspNetCore.Mvc;

namespace CompanyEmployees.Presentation.Controllers;
namespace Presentation.Controllers;

// tokenın süresi dolmak üzereyse, api/token uç noktasına istekte bulunun ve yeni bir geçerli token alın.
[Route("api/[controller]")]
Expand All @@ -20,4 +20,4 @@ public async Task<IActionResult> Refresh([FromBody] TokenDto tokenDto)
var tokenDtoToReturn = await _service.AuthenticationService.RefreshToken(tokenDto);
return Ok(tokenDtoToReturn);
}
}
}
9 changes: 9 additions & 0 deletions Presentation/Extensions/ApiBaseResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Entities.Responses;

namespace Presentation.Extensions;

public static class ApiBaseResponseExtensions
{
public static TResultType GetResult<TResultType>(this ApiBaseResponse apiBaseResponse)
=> ((ApiOkResponse<TResultType>)apiBaseResponse).Result;
}
16 changes: 12 additions & 4 deletions Repository/CompanyRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ namespace Repository;

public class CompanyRepository(RepositoryContext repositoryContext) : RepositoryBase<Company>(repositoryContext), ICompanyRepository
{
public async Task<IEnumerable<Company>> GetAllCompaniesAsync(bool trackChanges)
=> await FindAll(trackChanges).OrderBy(c => c.Name).ToListAsync();

public async Task<Company> GetCompanyAsync(Guid companyId, bool trackChanges)
=> await FindByCondition(c => c.Id.Equals(companyId), trackChanges).SingleOrDefaultAsync();
// public async Task<IEnumerable<Company>> GetAllCompaniesAsync(bool trackChanges)
// => await FindAll(trackChanges).OrderBy(c => c.Name).ToListAsync();
public IEnumerable<Company> GetAllCompanies(bool trackChanges)
=> [.. FindAll(trackChanges).OrderBy(c => c.Name)];


// public async Task<Company> GetCompanyAsync(Guid companyId, bool trackChanges)
// => await FindByCondition(c => c.Id.Equals(companyId), trackChanges).SingleOrDefaultAsync();
public Company GetCompany(Guid companyId, bool trackChanges)
=> FindByCondition(c => c.Id.Equals(companyId), trackChanges).SingleOrDefault();



public async Task<IEnumerable<Company>> GetByIdsAsync(IEnumerable<Guid> ids, bool trackChanges)
=> await FindByCondition(x => ids.Contains(x.Id), trackChanges).ToListAsync();
Expand Down
40 changes: 29 additions & 11 deletions Service/CompanyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Entities.DTO;
using Entities.Exceptions;
using Entities.Models;
using Entities.Responses;

namespace Service;

Expand All @@ -14,22 +15,39 @@ internal sealed class CompanyService(IRepositoryManager repository, ILoggerManag
private readonly ILoggerManager _logger = logger;
private readonly IMapper _mapper = mapper;

public async Task<IEnumerable<CompanyDto>> GetAllCompaniesAsync(bool trackChanges)
// public async Task<IEnumerable<CompanyDto>> GetAllCompaniesAsync(bool trackChanges)
// {
// var companies = await _repository.Company.GetAllCompaniesAsync(trackChanges);
// // var companiesDto = companies.Select(c => new CompanyDto(c.Id, c.Name ?? "", string.Join(' ', c.Address, c.Country))).ToList();
// var companiesDto = _mapper.Map<IEnumerable<CompanyDto>>(companies);
// return companiesDto;
// }
public ApiBaseResponse GetAllCompanies(bool trackChanges)
{
var companies = await _repository.Company.GetAllCompaniesAsync(trackChanges);
// var companiesDto = companies.Select(c => new CompanyDto(c.Id, c.Name ?? "", string.Join(' ', c.Address, c.Country))).ToList();
var companies = _repository.Company.GetAllCompanies(trackChanges);
var companiesDto = _mapper.Map<IEnumerable<CompanyDto>>(companies);
return companiesDto;
return new ApiOkResponse<IEnumerable<CompanyDto>>(companiesDto);
}

public async Task<CompanyDto> GetCompanyAsync(Guid id, bool trackChanges)


// public async Task<CompanyDto> GetCompanyAsync(Guid id, bool trackChanges)
// {
// var company = await GetCompanyAndCheckIfItExists(id, trackChanges);
// var companyDto = _mapper.Map<CompanyDto>(company);
// return companyDto;
// }
public ApiBaseResponse GetCompany(Guid id, bool trackChanges)
{
var company = await GetCompanyAndCheckIfItExists(id, trackChanges);
var company = _repository.Company.GetCompany(id, trackChanges);
if (company is null) return new CompanyNotFoundResponse(id);
var companyDto = _mapper.Map<CompanyDto>(company);
return companyDto;
return new ApiOkResponse<CompanyDto>(companyDto);
}




public async Task<CompanyDto> CreateCompanyAsync(CompanyForCreationDto company)
{
var companyEntity = _mapper.Map<Company>(company);
Expand Down Expand Up @@ -72,21 +90,21 @@ public async Task<IEnumerable<CompanyDto>> GetByIdsAsync(IEnumerable<Guid> ids,

public async Task DeleteCompanyAsync(Guid companyId, bool trackChanges)
{
var company = await GetCompanyAndCheckIfItExists(companyId, trackChanges);
var company = GetCompanyAndCheckIfItExists(companyId, trackChanges);
_repository.Company.DeleteCompany(company);
await _repository.SaveAsync();
}

public async Task UpdateCompanyAsync(Guid companyId, CompanyForUpdateDto companyForUpdate, bool trackChanges)
{
var company = await GetCompanyAndCheckIfItExists(companyId, trackChanges);
var company = GetCompanyAndCheckIfItExists(companyId, trackChanges);
_mapper.Map(companyForUpdate, company);
await _repository.SaveAsync();
}

private async Task<Company> GetCompanyAndCheckIfItExists(Guid id, bool trackChanges)
private Company GetCompanyAndCheckIfItExists(Guid id, bool trackChanges)
{
var company = await _repository.Company.GetCompanyAsync(id, trackChanges) ?? throw new CompanyNotFoundException(id);
var company = _repository.Company.GetCompany(id, trackChanges) ?? throw new CompanyNotFoundException(id);
return company;
}

Expand Down
Loading