From f5224e20f29e8e3c0d7fb2c232a3b32e3f870aef Mon Sep 17 00:00:00 2001 From: OlgunR Date: Mon, 30 Mar 2026 15:16:03 +0200 Subject: [PATCH] Add time record API endpoint and supporting infrastructure Introduced a new TimeController with a POST endpoint to insert and retrieve the latest time record. Added ITimeRepository, TimeRepository, and TimeRecord entity. Implemented MediatR command and handler for time insertion. Updated ApplicationDbContext and DI configuration to support the new feature. --- DbFirst.API/Controllers/TimeController.cs | 28 +++++++++++++++++++ DbFirst.API/Program.cs | 1 + .../Repositories/ITimeRepository.cs | 9 ++++++ .../Time/Commands/InsertTimeCommand.cs | 6 ++++ .../Time/Commands/InsertTimeHandler.cs | 21 ++++++++++++++ DbFirst.Domain/Entities/Time.cs | 6 ++++ .../ApplicationDbContext.cs | 11 ++++++++ .../Repositories/TimeRepository.cs | 28 +++++++++++++++++++ 8 files changed, 110 insertions(+) create mode 100644 DbFirst.API/Controllers/TimeController.cs create mode 100644 DbFirst.Application/Repositories/ITimeRepository.cs create mode 100644 DbFirst.Application/Time/Commands/InsertTimeCommand.cs create mode 100644 DbFirst.Application/Time/Commands/InsertTimeHandler.cs create mode 100644 DbFirst.Domain/Entities/Time.cs create mode 100644 DbFirst.Infrastructure/Repositories/TimeRepository.cs diff --git a/DbFirst.API/Controllers/TimeController.cs b/DbFirst.API/Controllers/TimeController.cs new file mode 100644 index 0000000..89bc6c7 --- /dev/null +++ b/DbFirst.API/Controllers/TimeController.cs @@ -0,0 +1,28 @@ +using DbFirst.Application.Time.Commands; +using DbFirst.Domain.Entities; +using MediatR; +using Microsoft.AspNetCore.Mvc; + +namespace DbFirst.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class TimeController : ControllerBase +{ + private readonly IMediator _mediator; + + public TimeController(IMediator mediator) + { + _mediator = mediator; + } + + [HttpPost] + public async Task> InsertAndGetLast(CancellationToken cancellationToken) + { + var result = await _mediator.Send(new InsertTimeCommand(), cancellationToken); + if (result == null) + return NotFound(); + + return Ok(result); + } +} diff --git a/DbFirst.API/Program.cs b/DbFirst.API/Program.cs index bfbc792..2d2fe4e 100644 --- a/DbFirst.API/Program.cs +++ b/DbFirst.API/Program.cs @@ -54,6 +54,7 @@ builder.Services.AddApplication(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddDevExpressControls(); builder.Services.AddSignalR(); diff --git a/DbFirst.Application/Repositories/ITimeRepository.cs b/DbFirst.Application/Repositories/ITimeRepository.cs new file mode 100644 index 0000000..cdcd26e --- /dev/null +++ b/DbFirst.Application/Repositories/ITimeRepository.cs @@ -0,0 +1,9 @@ +using DbFirst.Domain.Entities; + +namespace DbFirst.Application.Repositories; + +public interface ITimeRepository +{ + Task InsertAsync(CancellationToken cancellationToken = default); + Task GetLastAsync(CancellationToken cancellationToken = default); +} diff --git a/DbFirst.Application/Time/Commands/InsertTimeCommand.cs b/DbFirst.Application/Time/Commands/InsertTimeCommand.cs new file mode 100644 index 0000000..9248507 --- /dev/null +++ b/DbFirst.Application/Time/Commands/InsertTimeCommand.cs @@ -0,0 +1,6 @@ +using DbFirst.Domain.Entities; +using MediatR; + +namespace DbFirst.Application.Time.Commands; + +public record InsertTimeCommand : IRequest; diff --git a/DbFirst.Application/Time/Commands/InsertTimeHandler.cs b/DbFirst.Application/Time/Commands/InsertTimeHandler.cs new file mode 100644 index 0000000..9fded11 --- /dev/null +++ b/DbFirst.Application/Time/Commands/InsertTimeHandler.cs @@ -0,0 +1,21 @@ +using DbFirst.Application.Repositories; +using DbFirst.Domain.Entities; +using MediatR; + +namespace DbFirst.Application.Time.Commands; + +public class InsertTimeHandler : IRequestHandler +{ + private readonly ITimeRepository _repository; + + public InsertTimeHandler(ITimeRepository repository) + { + _repository = repository; + } + + public async Task Handle(InsertTimeCommand request, CancellationToken cancellationToken) + { + await _repository.InsertAsync(cancellationToken); + return await _repository.GetLastAsync(cancellationToken); + } +} diff --git a/DbFirst.Domain/Entities/Time.cs b/DbFirst.Domain/Entities/Time.cs new file mode 100644 index 0000000..caac73c --- /dev/null +++ b/DbFirst.Domain/Entities/Time.cs @@ -0,0 +1,6 @@ +namespace DbFirst.Domain.Entities; + +public class TimeRecord +{ + public DateTime? Now { get; set; } +} diff --git a/DbFirst.Infrastructure/ApplicationDbContext.cs b/DbFirst.Infrastructure/ApplicationDbContext.cs index 24608c5..37a3898 100644 --- a/DbFirst.Infrastructure/ApplicationDbContext.cs +++ b/DbFirst.Infrastructure/ApplicationDbContext.cs @@ -16,6 +16,7 @@ public partial class ApplicationDbContext : DbContext public virtual DbSet VwmyCatalogs { get; set; } public virtual DbSet SmfLayouts { get; set; } + public virtual DbSet Times { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -83,6 +84,16 @@ public partial class ApplicationDbContext : DbContext .HasColumnName("CHANGED_WHEN"); }); + modelBuilder.Entity(entity => + { + entity.HasNoKey(); + entity.ToTable("TIME"); + + entity.Property(e => e.Now) + .HasColumnType("datetime") + .HasColumnName("NOW"); + }); + OnModelCreatingPartial(modelBuilder); } diff --git a/DbFirst.Infrastructure/Repositories/TimeRepository.cs b/DbFirst.Infrastructure/Repositories/TimeRepository.cs new file mode 100644 index 0000000..a773674 --- /dev/null +++ b/DbFirst.Infrastructure/Repositories/TimeRepository.cs @@ -0,0 +1,28 @@ +using DbFirst.Application.Repositories; +using DbFirst.Domain.Entities; +using Microsoft.EntityFrameworkCore; + +namespace DbFirst.Infrastructure.Repositories; + +public class TimeRepository : ITimeRepository +{ + private readonly ApplicationDbContext _db; + + public TimeRepository(ApplicationDbContext db) + { + _db = db; + } + + public async Task InsertAsync(CancellationToken cancellationToken = default) + { + await _db.Database.ExecuteSqlRawAsync("INSERT INTO [TIME] (NOW) VALUES (GETDATE())", cancellationToken); + } + + public async Task GetLastAsync(CancellationToken cancellationToken = default) + { + return await _db.Times + .AsNoTracking() + .OrderByDescending(t => t.Now) + .FirstOrDefaultAsync(cancellationToken); + } +}