diff --git a/Infraestructure/Data/WorkshopDBContext.cs b/Infraestructure/Data/WorkshopDBContext.cs new file mode 100644 index 0000000..5f2cd4e --- /dev/null +++ b/Infraestructure/Data/WorkshopDBContext.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore; +using CampusWorkshops.Api.Models; + +namespace CampusWorkshops.Api.Infrastructure.Data; + +public class WorkshopsDbContext : DbContext +{ + public WorkshopsDbContext(DbContextOptions options) : base(options) {} + + public DbSet Workshops => Set(); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(e => + { + e.ToTable("Workshops"); + e.HasKey(w => w.Id); + e.Property(w => w.Title).IsRequired().HasMaxLength(120); + e.Property(w => w.Description).HasMaxLength(2000); + e.Property(w => w.Location).HasMaxLength(200); + e.Property(w => w.Capacity).HasDefaultValue(1); + e.HasIndex(w => w.StartAt); + }); + } +} diff --git a/Migrations/20250903175616_InitialCreate.Designer.cs b/Migrations/20250903175616_InitialCreate.Designer.cs new file mode 100644 index 0000000..05ff215 --- /dev/null +++ b/Migrations/20250903175616_InitialCreate.Designer.cs @@ -0,0 +1,65 @@ +// +using System; +using CampusWorkshops.Api.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Workshop10_API.Migrations +{ + [DbContext(typeof(WorkshopsDbContext))] + [Migration("20250903175616_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.8"); + + modelBuilder.Entity("CampusWorkshops.Api.Models.Workshop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Capacity") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("EndAt") + .HasColumnType("TEXT"); + + b.Property("IsOnline") + .HasColumnType("INTEGER"); + + b.Property("Location") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("StartAt") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StartAt"); + + b.ToTable("Workshops", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20250903175616_InitialCreate.cs b/Migrations/20250903175616_InitialCreate.cs new file mode 100644 index 0000000..e867052 --- /dev/null +++ b/Migrations/20250903175616_InitialCreate.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Workshop10_API.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Workshops", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", maxLength: 120, nullable: false), + Description = table.Column(type: "TEXT", maxLength: 2000, nullable: true), + StartAt = table.Column(type: "TEXT", nullable: false), + EndAt = table.Column(type: "TEXT", nullable: false), + Location = table.Column(type: "TEXT", maxLength: 200, nullable: true), + Capacity = table.Column(type: "INTEGER", nullable: false, defaultValue: 1), + IsOnline = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Workshops", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Workshops_StartAt", + table: "Workshops", + column: "StartAt"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Workshops"); + } + } +} diff --git a/Migrations/WorkshopsDbContextModelSnapshot.cs b/Migrations/WorkshopsDbContextModelSnapshot.cs new file mode 100644 index 0000000..029c404 --- /dev/null +++ b/Migrations/WorkshopsDbContextModelSnapshot.cs @@ -0,0 +1,62 @@ +// +using System; +using CampusWorkshops.Api.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Workshop10_API.Migrations +{ + [DbContext(typeof(WorkshopsDbContext))] + partial class WorkshopsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.8"); + + modelBuilder.Entity("CampusWorkshops.Api.Models.Workshop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Capacity") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("EndAt") + .HasColumnType("TEXT"); + + b.Property("IsOnline") + .HasColumnType("INTEGER"); + + b.Property("Location") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("StartAt") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StartAt"); + + b.ToTable("Workshops", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Program.cs b/Program.cs index 7fa8063..0e0069a 100644 --- a/Program.cs +++ b/Program.cs @@ -2,11 +2,16 @@ using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; using CampusWorkshops.Api.Repositories; +using Microsoft.EntityFrameworkCore; +using CampusWorkshops.Api.Infrastructure.Data; var builder = WebApplication.CreateBuilder(args); // Add services -builder.Services.AddSingleton(); +builder.Services.AddDbContext(options => + options.UseSqlite(builder.Configuration.GetConnectionString("WorkshopsDb"))); + +builder.Services.AddScoped(); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(o => diff --git a/Repositories/EfWorkshopRepository.cs b/Repositories/EfWorkshopRepository.cs new file mode 100644 index 0000000..4079f52 --- /dev/null +++ b/Repositories/EfWorkshopRepository.cs @@ -0,0 +1,71 @@ +using CampusWorkshops.Api.Models; +using Microsoft.EntityFrameworkCore; +using CampusWorkshops.Api.Infrastructure.Data; + +namespace CampusWorkshops.Api.Repositories; + +public class EfWorkshopRepository : IWorkshopRepository +{ + private readonly WorkshopsDbContext _db; + public EfWorkshopRepository(WorkshopsDbContext db) => _db = db; + + public async Task> GetAllAsync(DateTimeOffset? from, DateTimeOffset? to, string? q, CancellationToken ct) + { + var query = _db.Workshops.AsNoTracking().AsQueryable(); + if (from.HasValue) + { + query = query.Where(w => w.StartAt >= from.Value); + } + if (to.HasValue) + { + query = query.Where(w => w.EndAt >= to.Value); + } + if (!string.IsNullOrWhiteSpace(q)) + { + var termo = q.ToLowerInvariant(); + query = query.Where(w => w.Title.Contains(termo)|| w.Description.Contains(termo)); + } + Console.WriteLine(query.ToQueryString()); + return await query.ToListAsync(ct); + + } + + public async Task GetByIdAsync(Guid id, CancellationToken ct) + => await _db.Workshops.AsNoTracking().FirstOrDefaultAsync(w => w.Id == id, ct); + + public async Task AddAsync(Workshop workshop, CancellationToken ct) + { + _db.Workshops.Add(workshop); + await _db.SaveChangesAsync(); + return workshop; + } + + public async Task UpdateAsync(Workshop workshop, CancellationToken ct) + { + _db.Workshops.Update(workshop); + await _db.SaveChangesAsync(ct); + return workshop; + } + + public async Task DeleteAsync(Guid id, CancellationToken ct) + { + var encontrado = await _db.Workshops.FindAsync([id]); + if (encontrado == null) + { + return false; + } + _db.Workshops.Remove(encontrado); + await _db.SaveChangesAsync(); + return true; + } + + public Task ExistsAsync(Guid id, CancellationToken ct) + => _db.Workshops.AnyAsync(w => w.Id == id, ct); + + public async Task UpdatePartialAsync(Guid id, Action updateAction, CancellationToken ct) + { + var w = await _db.Workshops.FirstOrDefaultAsync(x => x.Id == id, ct); + // TODO: implementar o UpdatePartial + return w; + } +} diff --git a/Workshop10-API.csproj b/Workshop10-API.csproj index eb31916..fc6fcda 100644 --- a/Workshop10-API.csproj +++ b/Workshop10-API.csproj @@ -9,6 +9,16 @@ + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/appsettings.Development.json b/appsettings.Development.json index ff66ba6..7ece802 100644 --- a/appsettings.Development.json +++ b/appsettings.Development.json @@ -1,4 +1,7 @@ { + "ConnectionStrings": { + "WorkshopsDb": "Data Source=workshops.db" + }, "Logging": { "LogLevel": { "Default": "Information", diff --git a/workshops.db b/workshops.db new file mode 100644 index 0000000..92aa373 Binary files /dev/null and b/workshops.db differ