using System; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; namespace Logof_Client; /// /// Zentrale Datenbankverwaltung für Logof Client. /// /// Zuständig für: /// - PostgreSQL-Verbindung /// - EF Core DbContext /// - Datenbankmodelle /// - Migrationen /// - Verbindungstest /// public static class DatabseService { private static DbContextOptions? _options; /// /// Initialisiert die Datenbankverbindung. /// Sollte einmal beim Programmstart aufgerufen werden. /// public static void Initialize(string connectionString) { if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentException( "Kein Datenbank-Connection-String angegeben.", nameof(connectionString)); var builder = new DbContextOptionsBuilder(); builder.UseNpgsql(connectionString); _options = builder.Options; } /// /// Erstellt einen neuen DbContext. /// public static LogofDbContext GetContext() { if (_options == null) throw new InvalidOperationException( "DB wurde noch nicht initialisiert. " + "Rufen Sie DB.Initialize(...) auf."); return new LogofDbContext(_options); } /// /// Testet die Verbindung zum Datenbankserver. /// public static async Task TestConnectionAsync() { try { await using var db = GetContext(); return await db.Database.CanConnectAsync(); } catch { return false; } } /// /// Erstellt bzw. aktualisiert das Datenbankschema /// anhand der vorhandenen EF-Core-Migrationen. /// public static async Task MigrateAsync() { await using var db = GetContext(); await db.Database.MigrateAsync(); } } // ============================================================================ // DATABASE CONTEXT // ============================================================================ public class LogofDbContext : DbContext { public DbSet Customers => Set(); public LogofDbContext( DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // -------------------------------------------------------------------- // Customer // -------------------------------------------------------------------- modelBuilder.Entity(entity => { entity.ToTable("customers"); entity.HasKey(x => x.Id); entity.Property(x => x.Id) .ValueGeneratedOnAdd(); entity.Property(x => x.Name) .HasMaxLength(255) .IsRequired(); entity.Property(x => x.Description) .HasMaxLength(4000); entity.Property(x => x.SenderAddress) .HasMaxLength(4000); entity.Property(x => x.Separator) .HasMaxLength(1) .IsRequired(); // Optimistic Concurrency entity.Property(x => x.Version) .IsConcurrencyToken(); entity.Property(x => x.CreatedAt) .IsRequired(); entity.Property(x => x.UpdatedAt) .IsRequired(); }); } } // ============================================================================ // DATABASE MODELS // ============================================================================ public class CustomerEx { public long Id { get; set; } public string Name { get; set; } = ""; public string Description { get; set; } = ""; public string SenderAddress { get; set; } = ""; public char Separator { get; set; } = ','; /// /// Wird bei jeder Änderung erhöht. /// Verhindert, dass zwei Benutzer sich gegenseitig /// Änderungen überschreiben. /// public long Version { get; set; } = 1; public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } }