diff --git a/.gitignore b/.gitignore
index c0df4b2..364e10d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,6 @@ Thumbs.db
# Environment / secrets
.env
-appsettings.Development.json
\ No newline at end of file
+appsettings.json
+appsettings.Development.json
+.fake
diff --git a/Migrations/20260416121807_Init.Designer.cs b/Migrations/20260416121807_Init.Designer.cs
new file mode 100644
index 0000000..4755071
--- /dev/null
+++ b/Migrations/20260416121807_Init.Designer.cs
@@ -0,0 +1,49 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TicketAppIncrArchi.Infrastructure.Persistence;
+
+#nullable disable
+
+namespace TicketAppIncrArchi.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ [Migration("20260416121807_Init")]
+ partial class Init
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TicketAppIncrArchi.Domain.Entities.Ticket", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Tickets");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Migrations/20260416121807_Init.cs b/Migrations/20260416121807_Init.cs
new file mode 100644
index 0000000..cc55799
--- /dev/null
+++ b/Migrations/20260416121807_Init.cs
@@ -0,0 +1,35 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace TicketAppIncrArchi.Migrations
+{
+ ///
+ public partial class Init : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Tickets",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ Title = table.Column(type: "text", nullable: false),
+ Description = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Tickets", x => x.Id);
+ });
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Tickets");
+ }
+ }
+}
diff --git a/Migrations/AppDbContextModelSnapshot.cs b/Migrations/AppDbContextModelSnapshot.cs
new file mode 100644
index 0000000..1a59f91
--- /dev/null
+++ b/Migrations/AppDbContextModelSnapshot.cs
@@ -0,0 +1,46 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TicketAppIncrArchi.Infrastructure.Persistence;
+
+#nullable disable
+
+namespace TicketAppIncrArchi.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ partial class AppDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TicketAppIncrArchi.Domain.Entities.Ticket", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Tickets");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Program.cs b/Program.cs
index 3ad00f5..0fbdbe6 100644
--- a/Program.cs
+++ b/Program.cs
@@ -1,7 +1,8 @@
using TicketAppIncrArchi.API.Controllers;
using TicketAppIncrArchi.Application.Interfaces;
using TicketAppIncrArchi.Application.Services;
-
+using TicketAppIncrArchi.Infrastructure.Persistence;
+using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
@@ -13,7 +14,10 @@ builder.Services.AddOpenApi();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
+builder.Services.AddDbContext(options =>
+ options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
+builder.Services.AddScoped();
builder.Services.AddScoped();
var app = builder.Build();
diff --git a/TicketAppIncrArchi.API/Controllers/TicketsController.cs b/TicketAppIncrArchi.API/Controllers/TicketsController.cs
index cad0b55..0f19448 100644
--- a/TicketAppIncrArchi.API/Controllers/TicketsController.cs
+++ b/TicketAppIncrArchi.API/Controllers/TicketsController.cs
@@ -17,36 +17,29 @@ public class TicketsController : ControllerBase
{
_service = service;
}
-
//-----------------------------------------------------------
-
[HttpGet]
public IEnumerable Get()
{
- return _service.GetAll();
+ return _service.GetAll().Result;
}
[HttpGet("{id}")]
public ActionResult Get(Guid id)
{
- var result = _service.GetById(id);
+ var result = _service.GetById(id).Result;
if (result is FailureResult fail)
return NotFound(fail.Error);
var success = (SuccessResult) result;
return Ok(success.Value);
-
- /*
- if (ticket == null) return NotFound();
- return Ok(ticket);
- */
}
[HttpPost]
public IActionResult Create(CreateTicketRequest request)
{
- var result = _service.Create(request);
+ var result = _service.Create(request).Result;
if (result is FailureResult fail)
return BadRequest(fail.Error);
diff --git a/TicketAppIncrArchi.Application/Interfaces/ITicketRepository.cs b/TicketAppIncrArchi.Application/Interfaces/ITicketRepository.cs
new file mode 100644
index 0000000..c127bbf
--- /dev/null
+++ b/TicketAppIncrArchi.Application/Interfaces/ITicketRepository.cs
@@ -0,0 +1,11 @@
+using TicketAppIncrArchi.Domain.Entities;
+
+public interface ITicketRepository
+{
+
+ Task GetByIdAsync(Guid id);
+ Task> GetAllAsync();
+ Task AddAsync(Ticket ticket);
+ Task DeleteAsync(Guid id);
+
+}
diff --git a/TicketAppIncrArchi.Application/Interfaces/ITicketService.cs b/TicketAppIncrArchi.Application/Interfaces/ITicketService.cs
index 31d7c2a..9cf713e 100644
--- a/TicketAppIncrArchi.Application/Interfaces/ITicketService.cs
+++ b/TicketAppIncrArchi.Application/Interfaces/ITicketService.cs
@@ -1,14 +1,13 @@
+using System.Data.Entity.Infrastructure;
using TicketAppIncrArchi.Application.DTO;
using TicketAppIncrArchi.Domain.Entities;
namespace TicketAppIncrArchi.Application.Interfaces;
public interface ITicketService
-{
-
+{
//TODO: implement Repository
- IEnumerable GetAll();
-
- Result GetById(Guid id);
- Result Create(CreateTicketRequest request);
+ Task> GetAll();
+ Task> GetById(Guid id);
+ Task> Create(CreateTicketRequest request);
}
diff --git a/TicketAppIncrArchi.Application/Services/TicketServices.cs b/TicketAppIncrArchi.Application/Services/TicketServices.cs
index 228e010..86d19a8 100644
--- a/TicketAppIncrArchi.Application/Services/TicketServices.cs
+++ b/TicketAppIncrArchi.Application/Services/TicketServices.cs
@@ -11,10 +11,19 @@ namespace TicketAppIncrArchi.Application.Services;
public class TicketService : ITicketService
{
- private readonly List _tickets = new();
- public IEnumerable GetAll()
+ private readonly ITicketRepository _repo;
+ //private readonly List _tickets = new();
+
+ public TicketService(ITicketRepository repo)
{
- var result =_tickets.Select(t => new TicketResponse
+ _repo = repo;
+ }
+
+ public async Task> GetAll()
+ {
+ var tickets = await _repo.GetAllAsync();
+
+ var result =tickets.Select(t => new TicketResponse
{
Id = t.Id,
Title = t.Title,
@@ -23,29 +32,27 @@ public class TicketService : ITicketService
return result;
}
-
- public Result GetById(Guid id)
+ public async Task> GetById(Guid id)
{
- //TODO: should use result
- var found = _tickets.FirstOrDefault(ticket => ticket.Id == id);
-
- if (found == null)
+ var ticket = await _repo.GetByIdAsync(id);
+
+ if (ticket == null)
{
return Result.Fail("No Ticket Found");
}
var ticketResponse = new TicketResponse
{
- Id = found.Id,
- Title = found.Title,
- Description = found.Description,
+ Id = ticket.Id,
+ Title = ticket.Title,
+ Description = ticket.Description,
};
- return Result.Ok(found);
+ return Result.Ok(ticketResponse);
}
- public Result Create(CreateTicketRequest request)
+ public async Task> Create(CreateTicketRequest request)
{
if (string.IsNullOrWhiteSpace(request.Title))
@@ -53,25 +60,21 @@ public class TicketService : ITicketService
var ticket = new Ticket
{
- Id = Guid.NewGuid(),
Title = request.Title,
Description = request.Description
};
- //send creation to repo
- _tickets.Add(ticket);
+ Ticket resultTicket = await _repo.AddAsync(ticket);
var ticketResponse = new CreateTicketResponse
{
- Id = ticket.Id,
- Title = ticket.Title,
- Description = ticket.Description
+ Id = resultTicket.Id,
+ Title = resultTicket.Title,
+ Description = resultTicket.Description
};
- return Result.Ok(ticketResponse);
-
+ return Result.Ok(ticketResponse);
}
-
}
diff --git a/TicketAppIncrArchi.Domain/Entities.cs/Tickets.cs b/TicketAppIncrArchi.Domain/Entities.cs/Tickets.cs
index a801c05..afa13fb 100644
--- a/TicketAppIncrArchi.Domain/Entities.cs/Tickets.cs
+++ b/TicketAppIncrArchi.Domain/Entities.cs/Tickets.cs
@@ -1,6 +1,9 @@
+using System.ComponentModel.DataAnnotations;
+
namespace TicketAppIncrArchi.Domain.Entities;
public class Ticket
{
+ [Key]
public Guid Id {get;set;}
public string Title {get;set;} = "";
public string Description {get;set;} = "";
diff --git a/TicketAppIncrArchi.Infrastructure/DbContext.cs b/TicketAppIncrArchi.Infrastructure/DbContext.cs
new file mode 100644
index 0000000..ba16279
--- /dev/null
+++ b/TicketAppIncrArchi.Infrastructure/DbContext.cs
@@ -0,0 +1,18 @@
+
+using Microsoft.EntityFrameworkCore;
+
+namespace TicketAppIncrArchi.Infrastructure.Persistence;
+
+using TicketAppIncrArchi.Domain.Entities;
+
+public class AppDbContext : DbContext
+{
+ public AppDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ public DbSet Tickets {get;set;}
+}
+
diff --git a/TicketAppIncrArchi.Infrastructure/TicketRepository.cs b/TicketAppIncrArchi.Infrastructure/TicketRepository.cs
new file mode 100644
index 0000000..9e363a7
--- /dev/null
+++ b/TicketAppIncrArchi.Infrastructure/TicketRepository.cs
@@ -0,0 +1,37 @@
+using Microsoft.EntityFrameworkCore;
+using TicketAppIncrArchi.Domain.Entities;
+using TicketAppIncrArchi.Application.Interfaces;
+using TicketAppIncrArchi.Infrastructure.Persistence;
+
+
+public class TicketRepository : ITicketRepository
+{
+ private readonly AppDbContext _context;
+
+ public TicketRepository(AppDbContext context)
+ {
+ _context = context;
+ }
+
+ public async Task GetByIdAsync(Guid id)
+ => await _context.Tickets.FindAsync(id);
+
+ public async Task> GetAllAsync()
+ => await _context.Tickets.ToListAsync();
+
+ public async Task AddAsync(Ticket ticket)
+ {
+ _context.Tickets.Add(ticket);
+ await _context.SaveChangesAsync();
+ return(ticket);
+ }
+
+ public async Task DeleteAsync(Guid id)
+ {
+ var ticket = await _context.Tickets.FindAsync(id);
+ if (ticket is null) return;
+
+ _context.Tickets.Remove(ticket);
+ await _context.SaveChangesAsync();
+ }
+}
diff --git a/TicketAppIncrArchi.csproj b/TicketAppIncrArchi.csproj
index ad460fe..f167c54 100644
--- a/TicketAppIncrArchi.csproj
+++ b/TicketAppIncrArchi.csproj
@@ -7,7 +7,13 @@
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
diff --git a/TicketAppIncrArchi.csproj.Backup.tmp b/TicketAppIncrArchi.csproj.Backup.tmp
new file mode 100644
index 0000000..16c659d
--- /dev/null
+++ b/TicketAppIncrArchi.csproj.Backup.tmp
@@ -0,0 +1,15 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/appsettings.json b/appsettings.json
index 10f68b8..6df0a13 100644
--- a/appsettings.json
+++ b/appsettings.json
@@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning"
}
},
- "AllowedHosts": "*"
+ "AllowedHosts": "*",
+ "ConnectionStrings":{
+ "DefaultConnection": "Host=localhost;Port=45738;Database=mydb;Username=postgres;Password=password"
+ }
}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..8227d3d
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,20 @@
+services:
+ db:
+ image: postgres:14.5
+ restart: always
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: password
+ POSTGRES_DB: mydb
+ ports:
+ - "45738:5432"
+ volumes:
+ - pgdata:/var/lib/postgresql/data
+
+ adminer:
+ image: adminer
+ restart: always
+ ports:
+ - 8080:8080
+volumes:
+ pgdata: