316 lines
9.9 KiB
C#
316 lines
9.9 KiB
C#
using KoogleApp.Entities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using System;
|
|
using Koogle.Domain.Interfaces;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace KoogleApp.Data.Repository
|
|
{
|
|
|
|
|
|
public class InMemoryPlayerRepository : IPlayerRepository
|
|
{
|
|
private readonly List<Player> _data = new();
|
|
private readonly List<PlayerExpense> _playerExpenses = new();
|
|
|
|
private int _nextId = 1;
|
|
private readonly SemaphoreSlim _lock = new(1, 1);
|
|
|
|
public InMemoryPlayerRepository()
|
|
{
|
|
// Seed-Daten für Entwicklung
|
|
_data.AddRange(new[]
|
|
{
|
|
new Player
|
|
{
|
|
Id = _nextId++,
|
|
Name = "Christian Kauer",
|
|
//Description = "Beschreibung 1",
|
|
CreatedAt = DateTime.UtcNow.AddDays(-5)
|
|
},
|
|
new Player
|
|
{
|
|
Id = _nextId++,
|
|
Name = "Michael Thöne",
|
|
//Description = "Beschreibung 2",
|
|
CreatedAt = DateTime.UtcNow.AddDays(-3)
|
|
},
|
|
new Player
|
|
{
|
|
Id = _nextId++,
|
|
Name = "Christian Hermann",
|
|
//Description = "Beschreibung 3",
|
|
CreatedAt = DateTime.UtcNow.AddDays(-1)
|
|
},
|
|
new Player
|
|
{
|
|
Id = _nextId++,
|
|
Name = "Stefan Meinerzhagen",
|
|
//Description = "Beschreibung 3",
|
|
CreatedAt = DateTime.UtcNow.AddDays(-1)
|
|
}
|
|
});
|
|
|
|
|
|
_playerExpenses.AddRange([
|
|
new PlayerExpense()
|
|
{
|
|
Id = 1,
|
|
PlayerId = _data[0].Id,
|
|
Name = "Expense 1",
|
|
CreatedAt = DateTime.UtcNow.AddDays(-1)
|
|
|
|
}
|
|
]);
|
|
}
|
|
|
|
public async Task<List<Player>> GetAllAsync(bool includeExpenses = false)
|
|
{
|
|
await _lock.WaitAsync();
|
|
try
|
|
{
|
|
// Simuliere Datenbanklatenz
|
|
await Task.Delay(100);
|
|
return _data.Select(d => new Player
|
|
{
|
|
Id = d.Id,
|
|
Name = d.Name,
|
|
//Description = d.Description,
|
|
CreatedAt = d.CreatedAt,
|
|
ModifiedAt = d.ModifiedAt,
|
|
ModifiedBy = d.ModifiedBy,
|
|
Expenses = includeExpenses
|
|
? _playerExpenses.Where(p => p.PlayerId == d.Id)
|
|
.OrderBy(p => p.CreatedAt)
|
|
.ToList()
|
|
: new List<PlayerExpense>()
|
|
}).ToList();
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<Player?> GetByIdAsync(int id, bool includeExpenses = false)
|
|
{
|
|
await _lock.WaitAsync();
|
|
try
|
|
{
|
|
await Task.Delay(50);
|
|
var item = _data.FirstOrDefault(d => d.Id == id);
|
|
if (item == null) return null;
|
|
|
|
return new Player
|
|
{
|
|
Id = item.Id,
|
|
Name = item.Name,
|
|
//Description = item.Description,
|
|
CreatedAt = item.CreatedAt,
|
|
ModifiedAt = item.ModifiedAt,
|
|
ModifiedBy = item.ModifiedBy,
|
|
Expenses = includeExpenses
|
|
? _playerExpenses.Where(p => p.PlayerId == id)
|
|
.OrderBy(p => p.CreatedAt)
|
|
.ToList()
|
|
: new List<PlayerExpense>()
|
|
};
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<Player> CreateAsync(Player item)
|
|
{
|
|
await _lock.WaitAsync();
|
|
try
|
|
{
|
|
await Task.Delay(100);
|
|
item.Id = _nextId++;
|
|
item.CreatedAt = DateTime.UtcNow;
|
|
|
|
// Positionen IDs setzen
|
|
foreach (var pos in item.Expenses)
|
|
{
|
|
pos.Id = _playerExpenses.Any() ? _playerExpenses.Max(p => p.Id) + 1 : 1;
|
|
pos.PlayerId = item.Id;
|
|
_playerExpenses.Add(pos);
|
|
}
|
|
|
|
|
|
_data.Add(item);
|
|
return item;
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<Player> UpdateAsync(Player item)
|
|
{
|
|
await _lock.WaitAsync();
|
|
try
|
|
{
|
|
await Task.Delay(100);
|
|
var existing = _data.FirstOrDefault(d => d.Id == item.Id);
|
|
if (existing == null)
|
|
throw new KeyNotFoundException($"Item with ID {item.Id} not found");
|
|
|
|
existing.Name = item.Name;
|
|
existing.PlayerStatus = item.PlayerStatus;
|
|
//existing.Description = item.Description;
|
|
existing.ModifiedAt = DateTime.UtcNow;
|
|
existing.ModifiedBy = item.ModifiedBy;
|
|
|
|
// Positionen aktualisieren (einfache Strategie: alte löschen, neue hinzufügen)
|
|
_playerExpenses.RemoveAll(p => p.PlayerId == item.Id);
|
|
foreach (var pos in item.Expenses)
|
|
{
|
|
if (pos.Id == 0)
|
|
pos.Id = _playerExpenses.Any() ? _playerExpenses.Max(p => p.Id) + 1 : 1;
|
|
pos.PlayerId = item.Id;
|
|
_playerExpenses.Add(pos);
|
|
}
|
|
|
|
existing.Expenses = item.Expenses;
|
|
|
|
return existing;
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<bool> DeleteAsync(int id)
|
|
{
|
|
await _lock.WaitAsync();
|
|
try
|
|
{
|
|
await Task.Delay(50);
|
|
var item = _data.FirstOrDefault(d => d.Id == id);
|
|
if (item == null) return false;
|
|
|
|
// Cascade Delete - Positionen auch löschen
|
|
_playerExpenses.RemoveAll(p => p.PlayerId == id);
|
|
|
|
_data.Remove(item);
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class PlayerRepository : IPlayerRepository
|
|
{
|
|
private readonly IDbContextFactory<AppDbContext> _contextFactory;
|
|
private readonly ILogger<IPlayerRepository> _logger;
|
|
|
|
public PlayerRepository(
|
|
IDbContextFactory<AppDbContext> contextFactory,
|
|
ILogger<IPlayerRepository> logger)
|
|
{
|
|
_contextFactory = contextFactory;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<List<Player>> GetAllAsync(bool includeExpenses = false)
|
|
{
|
|
try
|
|
{
|
|
await using var context = await _contextFactory.CreateDbContextAsync();
|
|
return await context.Players
|
|
.OrderByDescending(d => d.CreatedAt)
|
|
.ToListAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error loading all data items");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<Player?> GetByIdAsync(int id, bool includeExpenses = false)
|
|
{
|
|
try
|
|
{
|
|
await using var context = await _contextFactory.CreateDbContextAsync();
|
|
return await context.Players
|
|
.FirstOrDefaultAsync(d => d.Id == id);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error loading data item {Id}", id);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<Player> CreateAsync(Player item)
|
|
{
|
|
try
|
|
{
|
|
await using var context = await _contextFactory.CreateDbContextAsync();
|
|
item.CreatedAt = DateTime.UtcNow;
|
|
context.Players.Add(item);
|
|
await context.SaveChangesAsync();
|
|
return item;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error creating data item");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<Player> UpdateAsync(Player item)
|
|
{
|
|
try
|
|
{
|
|
await using var context = await _contextFactory.CreateDbContextAsync();
|
|
var existing = await context.Players.FindAsync(item.Id);
|
|
if (existing == null)
|
|
throw new KeyNotFoundException($"Item with ID {item.Id} not found");
|
|
|
|
existing.Name = item.Name;
|
|
existing.PlayerStatus = item.PlayerStatus;
|
|
//existing.Description = item.Description;
|
|
existing.ModifiedAt = DateTime.UtcNow;
|
|
existing.ModifiedBy = item.ModifiedBy;
|
|
|
|
await context.SaveChangesAsync();
|
|
return existing;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error updating data item {Id}", item.Id);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> DeleteAsync(int id)
|
|
{
|
|
try
|
|
{
|
|
await using var context = await _contextFactory.CreateDbContextAsync();
|
|
var item = await context.Players.FindAsync(id);
|
|
if (item == null) return false;
|
|
|
|
context.Players.Remove(item);
|
|
await context.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error deleting data item {Id}", id);
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
}
|