Database migration, repository, controller and service

This commit is contained in:
Nickk888 committed 2026-10-09 16:32:38 +02:00
1 parent 07e4e6b381
commit 4fb8768807
17 files changed
+368 -44

No files matched your search

-10
View File
@@ -1,10 +0,0 @@
using System;
using Newtonsoft.Json;
namespace PaperlessAI.Bodies;
public class NewDocumentBody
{
[JsonProperty("document_id")]
public int DocumentId { get; set; }
}
+15
View File
@@ -0,0 +1,15 @@
using System;
using Newtonsoft.Json;
namespace PaperlessAI.Bodies;
public class NewPaperlessDocumentBody
{
[JsonProperty("document_id")]
public long DocumentId { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
+8 -1
View File
@@ -1,5 +1,5 @@
using System;
using Microsoft.EntityFrameworkCore;
using PaperlessAI.Models;
namespace PaperlessAI.Context;
@@ -19,6 +19,13 @@ public class MyDbContext : DbContext
modelBuilder
.UseCollation("utf8mb4_uca1400_ai_ci")
.HasCharSet("utf8mb4");
modelBuilder
.Entity<PaperlessDocument>()
.HasIndex(x => x.DocumentId)
.IsUnique();
}
public DbSet<PaperlessDocument> PaperlessDocuments { get; set; }
}
-17
View File
@@ -1,17 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using PaperlessAI.Bodies;
namespace PaperlessAI.Controllers
{
[Route("[controller]")]
[ApiController]
public class DocumentController : ControllerBase
{
[HttpPost]
public ActionResult AddNewDocument([FromBody]NewDocumentBody newDocument)
{
return Ok();
}
}
}
@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Mvc;
using PaperlessAI.Bodies;
using PaperlessAI.Services;
namespace PaperlessAI.Controllers
{
[Route("Document")]
[ApiController]
public class PaperlessDocumentController(PaperlessDocumentService documentService, ILogger<PaperlessDocumentController> logger) : ControllerBase
{
[HttpPost]
public async Task<ActionResult> AddNewDocument([FromBody]NewPaperlessDocumentBody newPaperlessDocumentBody)
{
logger.LogDebug($"AddNewDocument called with body: {newPaperlessDocumentBody}");
try
{
if(await documentService.Exists(newPaperlessDocumentBody.DocumentId))
{
logger.LogWarning($"Document {newPaperlessDocumentBody.DocumentId} already exists.");
return Conflict();
}
await documentService.Create(newPaperlessDocumentBody.DocumentId);
logger.LogWarning($"Document {newPaperlessDocumentBody.DocumentId} created.");
}
catch (Exception e)
{
logger.LogError(e.ToString());
return StatusCode(500);
}
logger.LogDebug($"AddNewDocument Ok!");
return Ok();
}
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace PaperlessAI.Enums;
public enum EOperationState
{
Created = 0,
Queued = 1,
Started = 2,
Success = 3,
Failed = 4
}
+11
View File
@@ -0,0 +1,11 @@
namespace PaperlessAI.Interfaces;
public interface IRepository<T>
{
Task Add(T model, bool persist = true);
Task Remove(T model, bool persist = true);
Task Update(T model, bool persist = true);
Task<T?> Get(long id);
Task<List<T>> GetAll();
}
+60
View File
@@ -0,0 +1,60 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using PaperlessAI.Context;
#nullable disable
namespace PaperlessAI.Migrations
{
[DbContext(typeof(MyDbContext))]
[Migration("20261009132858_Init")]
partial class Init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.UseCollation("utf8mb4_uca1400_ai_ci")
.HasAnnotation("ProductVersion", "10.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.HasCharSet(modelBuilder, "utf8mb4");
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("PaperlessAI.Models.PaperlessDocument", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<long>("DocumentId")
.HasColumnType("bigint");
b.Property<int>("DocumentState")
.HasColumnType("int");
b.Property<DateTimeOffset>("ModifiedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("DocumentId")
.IsUnique();
b.ToTable("PaperlessDocuments");
});
#pragma warning restore 612, 618
}
}
}
+50
View File
@@ -0,0 +1,50 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PaperlessAI.Migrations
{
/// <inheritdoc />
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "PaperlessDocuments",
columns: table => new
{
Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
DocumentId = table.Column<long>(type: "bigint", nullable: false),
DocumentState = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false),
ModifiedAt = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PaperlessDocuments", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4")
.Annotation("Relational:Collation", "utf8mb4_uca1400_ai_ci");
migrationBuilder.CreateIndex(
name: "IX_PaperlessDocuments_DocumentId",
table: "PaperlessDocuments",
column: "DocumentId",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PaperlessDocuments");
}
}
}
+57
View File
@@ -0,0 +1,57 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using PaperlessAI.Context;
#nullable disable
namespace PaperlessAI.Migrations
{
[DbContext(typeof(MyDbContext))]
partial class MyDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.UseCollation("utf8mb4_uca1400_ai_ci")
.HasAnnotation("ProductVersion", "10.0.12")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.HasCharSet(modelBuilder, "utf8mb4");
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("PaperlessAI.Models.PaperlessDocument", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<long>("Id"));
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<long>("DocumentId")
.HasColumnType("bigint");
b.Property<int>("DocumentState")
.HasColumnType("int");
b.Property<DateTimeOffset>("ModifiedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("DocumentId")
.IsUnique();
b.ToTable("PaperlessDocuments");
});
#pragma warning restore 612, 618
}
}
}
+24
View File
@@ -0,0 +1,24 @@
using PaperlessAI.Enums;
namespace PaperlessAI.Models;
public class PaperlessDocument
{
public long Id { get; set; }
public long DocumentId { get; set; }
public EOperationState DocumentState { get; set; } = EOperationState.Created;
public DateTimeOffset CreatedAt { get; set; } = DateTime.UtcNow;
public DateTimeOffset ModifiedAt { get; set; } = DateTime.UtcNow;
public PaperlessDocument(long documentId)
{
DocumentId = documentId;
}
public static PaperlessDocument Create(long documentId)
{
var paperlessDocument = new PaperlessDocument(documentId);
return paperlessDocument;
}
}
+3 -1
View File
@@ -11,7 +11,9 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.12" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="9.0.0" />
<PackageReference Include="Microting.EntityFrameworkCore.MySql" Version="10.0.12" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
</ItemGroup>
</Project>
+27 -6
View File
@@ -1,28 +1,49 @@
using Microsoft.EntityFrameworkCore;
using PaperlessAI.Context;
using PaperlessAI.Repositories;
using PaperlessAI.Services;
using Serilog;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Services
builder.Services.AddScoped<PaperlessDocumentService>();
// Repositories
builder.Services.AddScoped<PaperlessDocumentRepository>();
// Other
builder.Services.AddControllers();
// Database
builder.Services.AddDbContextPool<MyDbContext>(options =>
{
options.UseMySql(
builder.Configuration.GetConnectionString("MariaDbConnectionString"),
ServerVersion.Parse("12.0.2-mariadb")
);
)
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
});
// Logging
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File(
Path.Combine(AppContext.BaseDirectory, "logs", "log-.txt"),
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30)
.CreateLogger();
builder.Host.UseSerilog();
// App
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
-9
View File
@@ -10,14 +10,5 @@
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7245;http://localhost:5276",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
+38
View File
@@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore;
using PaperlessAI.Context;
using PaperlessAI.Interfaces;
using PaperlessAI.Models;
namespace PaperlessAI.Repositories;
public class PaperlessDocumentRepository(MyDbContext context) : IRepository<PaperlessDocument>
{
public async Task Add(PaperlessDocument model, bool persist = true)
{
await context.PaperlessDocuments.AddAsync(model);
await SaveOnPersist(persist);
}
public async Task Remove(PaperlessDocument model, bool persist = true)
{
context.PaperlessDocuments.Remove(model);
await SaveOnPersist(persist);
}
public async Task Update(PaperlessDocument model, bool persist = true)
{
context.PaperlessDocuments.Update(model);
await SaveOnPersist(persist);
}
public async Task<PaperlessDocument?> Get(long id) => await context.PaperlessDocuments.Where(x => x.DocumentId == id).FirstOrDefaultAsync();
public async Task<List<PaperlessDocument>> GetAll() => await context.PaperlessDocuments.ToListAsync();
public async Task SaveOnPersist(bool persist)
{
if(persist)
{
await context.SaveChangesAsync();
}
}
}
+22
View File
@@ -0,0 +1,22 @@
using PaperlessAI.Models;
using PaperlessAI.Repositories;
namespace PaperlessAI.Services;
public class PaperlessDocumentService(PaperlessDocumentRepository docRepo)
{
public async Task<bool> Exists(long documentId)
{
if(documentId < 0 || documentId > long.MaxValue)
throw new Exception($"Value \"{documentId}\" must be in Range between 0 - {long.MaxValue}!");
return await docRepo.Get(documentId) != null;
}
public async Task<PaperlessDocument> Create(long documentId)
{
var doc = PaperlessDocument.Create(documentId);
await docRepo.Add(doc);
return doc;
}
}
+6
View File
@@ -0,0 +1,6 @@
POST http://localhost:5276/Document HTTP/1.1
Content-Type: application/json
{
"document_id": 8
}