Implemetato databese locale con EntityFramework

This commit is contained in:
2026-02-17 17:40:33 +01:00
parent 544c9e8237
commit e7357bd78a
45 changed files with 989 additions and 119 deletions

View File

@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using SteUp.Shared.Core.Entities;
namespace SteUp.Data.LocalDb;
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
{
public DbSet<Ispezione> Ispezioni => Set<Ispezione>();
public DbSet<Scheda> Schede => Set<Scheda>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Ispezione>()
.HasKey(x => new { x.CodMdep, x.Data, x.Rilevatore });
modelBuilder.Entity<Scheda>()
.HasOne(x => x.Ispezione)
.WithMany(x => x.Schede)
.HasForeignKey(x => new { x.CodMdep, x.Data, x.Rilevatore })
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Scheda>()
.HasIndex(x => new { x.CodMdep, x.Data, x.Rilevatore });
}
}

View File

@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
namespace SteUp.Data.LocalDb;
public class AppDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlite("Data Source=design-time.db3")
.Options;
return new AppDbContext(options);
}
}

View File

@@ -0,0 +1,12 @@
using Microsoft.EntityFrameworkCore;
using SteUp.Shared.Core.Interface.LocalDb;
namespace SteUp.Data.LocalDb;
public class DbInitializer(AppDbContext db) : IDbInitializer
{
public async Task InitializeAsync()
{
await db.Database.MigrateAsync();
}
}

View File

@@ -0,0 +1,17 @@
using Microsoft.Maui.Storage;
namespace SteUp.Data.LocalDb;
public interface IDbPathProvider
{
string GetDbPath();
}
public class DbPathProvider : IDbPathProvider
{
private const string DbName = "steup_db.db3";
public string GetDbPath() =>
Path.Combine(FileSystem.AppDataDirectory, DbName);
}

View File

@@ -0,0 +1,127 @@
using Microsoft.EntityFrameworkCore;
using SteUp.Shared.Core.Entities;
using SteUp.Shared.Core.Interface.LocalDb;
namespace SteUp.Data.LocalDb.EntityServices;
public class IspezioniService(AppDbContext db) : IIspezioniService
{
public Task<Ispezione?> GetIspezioneAsync(string codMdep, DateOnly data, string rilevatore) =>
db.Ispezioni
.Include(x => x.Schede)
.FirstOrDefaultAsync(x =>
x.CodMdep == codMdep &&
x.Data == data &&
x.Rilevatore == rilevatore);
public Task<List<Ispezione>> GetAllIspezioniWithSchedeAsync() =>
db.Ispezioni
.Include(x => x.Schede)
.AsNoTracking()
.OrderByDescending(x => x.Data)
.ToListAsync();
public async Task AddIspezioneAsync(Ispezione ispezione)
{
db.Ispezioni.Add(ispezione);
await db.SaveChangesAsync();
}
public async Task<Ispezione> GetOrCreateIspezioneAsync(string codMdep, DateOnly data, string rilevatore)
{
var existing = await db.Ispezioni
.Include(x => x.Schede)
.FirstOrDefaultAsync(x =>
x.CodMdep == codMdep &&
x.Data == data &&
x.Rilevatore == rilevatore);
if (existing != null)
return existing;
var created = new Ispezione
{
CodMdep = codMdep,
Data = data,
Rilevatore = rilevatore
};
db.Ispezioni.Add(created);
await db.SaveChangesAsync();
return created;
}
/// <summary>
/// Cancella l'ispezione e tutte le schede collegate.
/// </summary>
public async Task<bool> DeleteIspezioneAsync(string codMdep, DateOnly data, string rilevatore)
{
var ispezione = await db.Ispezioni
.FirstOrDefaultAsync(x =>
x.CodMdep == codMdep &&
x.Data == data &&
x.Rilevatore == rilevatore);
if (ispezione is null)
return false;
db.Ispezioni.Remove(ispezione);
await db.SaveChangesAsync();
return true;
}
public async Task AddSchedaAsync(string codMdep, DateOnly data, string rilevatore, Scheda scheda)
{
// assicura che il parent esista
await GetOrCreateIspezioneAsync(codMdep, data, rilevatore);
scheda.CodMdep = codMdep;
scheda.Data = data;
scheda.Rilevatore = rilevatore;
db.Schede.Add(scheda);
await db.SaveChangesAsync();
}
public Task<Scheda?> GetSchedaAsync(int schedaId) =>
db.Schede
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == schedaId);
public Task<Scheda?> GetSchedaWithIspezioneAsync(int schedaId) =>
db.Schede
.Include(x => x.Ispezione)
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == schedaId);
public async Task<bool> DeleteSchedaAsync(int schedaId)
{
var scheda = await db.Schede.FirstOrDefaultAsync(x => x.Id == schedaId);
if (scheda is null)
return false;
db.Schede.Remove(scheda);
await db.SaveChangesAsync();
return true;
}
/// <summary>
/// Cancella tutte le schede di una ispezione senza cancellare l'ispezione.
/// </summary>
public async Task<int> DeleteAllSchedeOfIspezioneAsync(string codMdep, DateOnly data, string rilevatore)
{
var schede = await db.Schede
.Where(s =>
s.CodMdep == codMdep &&
s.Data == data &&
s.Rilevatore == rilevatore)
.ToListAsync();
if (schede.Count == 0)
return 0;
db.Schede.RemoveRange(schede);
return await db.SaveChangesAsync();
}
}

View File

@@ -0,0 +1,102 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SteUp.Data.LocalDb;
#nullable disable
namespace SteUp.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20260217143326_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.13");
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Property<string>("CodMdep")
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.HasColumnType("TEXT");
b.Property<int>("Stato")
.HasColumnType("INTEGER");
b.HasKey("CodMdep", "Data", "Rilevatore");
b.ToTable("Ispezioni");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ActivityTypeId")
.HasColumnType("TEXT");
b.Property<string>("CodJfas")
.HasColumnType("TEXT");
b.Property<string>("CodMdep")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("DescrizioneReparto")
.HasColumnType("TEXT");
b.Property<string>("Note")
.HasColumnType("TEXT");
b.Property<string>("Responsabile")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Scadenza")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CodMdep", "Data", "Rilevatore");
b.ToTable("Schede");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.HasOne("SteUp.Shared.Core.Entities.Ispezione", "Ispezione")
.WithMany("Schede")
.HasForeignKey("CodMdep", "Data", "Rilevatore")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ispezione");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Navigation("Schede");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,71 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SteUp.Data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Ispezioni",
columns: table => new
{
CodMdep = table.Column<string>(type: "TEXT", nullable: false),
Data = table.Column<DateOnly>(type: "TEXT", nullable: false),
Rilevatore = table.Column<string>(type: "TEXT", nullable: false),
Stato = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Ispezioni", x => new { x.CodMdep, x.Data, x.Rilevatore });
});
migrationBuilder.CreateTable(
name: "Schede",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CodJfas = table.Column<string>(type: "TEXT", nullable: true),
CodMdep = table.Column<string>(type: "TEXT", nullable: false),
Data = table.Column<DateOnly>(type: "TEXT", nullable: false),
Rilevatore = table.Column<string>(type: "TEXT", nullable: false),
DescrizioneReparto = table.Column<string>(type: "TEXT", nullable: true),
ActivityTypeId = table.Column<string>(type: "TEXT", nullable: true),
Note = table.Column<string>(type: "TEXT", nullable: true),
Responsabile = table.Column<string>(type: "TEXT", nullable: true),
Scadenza = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Schede", x => x.Id);
table.ForeignKey(
name: "FK_Schede_Ispezioni_CodMdep_Data_Rilevatore",
columns: x => new { x.CodMdep, x.Data, x.Rilevatore },
principalTable: "Ispezioni",
principalColumns: new[] { "CodMdep", "Data", "Rilevatore" },
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Schede_CodMdep_Data_Rilevatore",
table: "Schede",
columns: new[] { "CodMdep", "Data", "Rilevatore" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Schede");
migrationBuilder.DropTable(
name: "Ispezioni");
}
}
}

View File

@@ -0,0 +1,99 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SteUp.Data.LocalDb;
#nullable disable
namespace SteUp.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.13");
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Property<string>("CodMdep")
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.HasColumnType("TEXT");
b.Property<int>("Stato")
.HasColumnType("INTEGER");
b.HasKey("CodMdep", "Data", "Rilevatore");
b.ToTable("Ispezioni");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ActivityTypeId")
.HasColumnType("TEXT");
b.Property<string>("CodJfas")
.HasColumnType("TEXT");
b.Property<string>("CodMdep")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateOnly>("Data")
.HasColumnType("TEXT");
b.Property<string>("DescrizioneReparto")
.HasColumnType("TEXT");
b.Property<string>("Note")
.HasColumnType("TEXT");
b.Property<string>("Responsabile")
.HasColumnType("TEXT");
b.Property<string>("Rilevatore")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Scadenza")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CodMdep", "Data", "Rilevatore");
b.ToTable("Schede");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Scheda", b =>
{
b.HasOne("SteUp.Shared.Core.Entities.Ispezione", "Ispezione")
.WithMany("Schede")
.HasForeignKey("CodMdep", "Data", "Rilevatore")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ispezione");
});
modelBuilder.Entity("SteUp.Shared.Core.Entities.Ispezione", b =>
{
b.Navigation("Schede");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.13" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.13">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.13" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SteUp.Shared\SteUp.Shared.csproj" />
</ItemGroup>
</Project>