Updates
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
using System.Reflection;
|
||||
using DCGEngine.Database.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DCGEngine.Database.Configuration;
|
||||
|
||||
public class DCGEDatabaseConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// The default name of the appsettings section where these are configured.
|
||||
/// </summary>
|
||||
public const string DefaultSectionName = "DCGEDatabaseConfiguration";
|
||||
|
||||
#region Appsettings
|
||||
|
||||
// TODO
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manual Configuration
|
||||
|
||||
/// <summary>
|
||||
/// Assemblies to be searched for classes implementing <see cref="BaseEntity{TKey}"/> to be added as <see cref="DbSet{TEntity}"/>s. Should be set in code, not in appsettings.
|
||||
/// </summary>
|
||||
public List<Assembly> DbSetSearchAssemblies { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
72
DCGEngine.Database/DCGEDbContext.cs
Normal file
72
DCGEngine.Database/DCGEDbContext.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using DCGEngine.Database.Configuration;
|
||||
using DCGEngine.Database.Interfaces;
|
||||
using DCGEngine.Database.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace DCGEngine.Database;
|
||||
|
||||
public class DCGEDbContext : DbContext
|
||||
{
|
||||
private readonly DCGEDatabaseConfiguration _configuration;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public DCGEDbContext(IOptions<DCGEDatabaseConfiguration> configuration, ILogger<DCGEDbContext> logger, DbContextOptions options) : base(options)
|
||||
{
|
||||
_logger = logger;
|
||||
_configuration = configuration.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
foreach (var entityEntry in ChangeTracker.Entries())
|
||||
{
|
||||
if (entityEntry.Entity is ITimeTrackedEntity timeTrackedEntity)
|
||||
{
|
||||
if (entityEntry.State is EntityState.Added && timeTrackedEntity.DateCreated is null)
|
||||
{
|
||||
timeTrackedEntity.DateCreated = DateTime.UtcNow;
|
||||
}
|
||||
if (entityEntry.State is EntityState.Modified or EntityState.Added)
|
||||
{
|
||||
timeTrackedEntity.DateUpdated = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
_configuration.DbSetSearchAssemblies.ForEach(assembly =>
|
||||
{
|
||||
foreach (var typeInfo in assembly.DefinedTypes.Where(type => type.IsAssignableTo(typeof(IDbTrackedEntity))))
|
||||
{
|
||||
modelBuilder.Entity(typeInfo.AsType());
|
||||
}
|
||||
});
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
|
||||
public void UpdateDatabase()
|
||||
{
|
||||
IEnumerable<string> pendingMigrations = Database.GetPendingMigrations();
|
||||
if (!pendingMigrations.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string migration in pendingMigrations)
|
||||
{
|
||||
_logger.LogInformation("Found pending migration with name {migrationName}.", migration);
|
||||
}
|
||||
_logger.LogInformation("Attempting to apply pending migrations...");
|
||||
Database.Migrate();
|
||||
_logger.LogInformation("Migrations applied.");
|
||||
}
|
||||
}
|
||||
20
DCGEngine.Database/DCGEngine.Database.csproj
Normal file
20
DCGEngine.Database/DCGEngine.Database.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Attributes\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
11
DCGEngine.Database/Interfaces/IDbTrackedEntity.cs
Normal file
11
DCGEngine.Database/Interfaces/IDbTrackedEntity.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DCGEngine.Database.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates a class should have a <see cref="DbSet{TEntity}"/> created and be tracked by the <see cref="DbContext"/>.
|
||||
/// </summary>
|
||||
public interface IDbTrackedEntity
|
||||
{
|
||||
|
||||
}
|
||||
14
DCGEngine.Database/Interfaces/ITimeTrackedEntity.cs
Normal file
14
DCGEngine.Database/Interfaces/ITimeTrackedEntity.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace DCGEngine.Database.Interfaces;
|
||||
|
||||
public interface ITimeTrackedEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="DateTime"/> this entity was first added to the database.
|
||||
/// </summary>
|
||||
public DateTime? DateCreated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DateTime"/> this entity was last updated.
|
||||
/// </summary>
|
||||
public DateTime? DateUpdated { get; set; }
|
||||
}
|
||||
14
DCGEngine.Database/Models/BaseEntity.cs
Normal file
14
DCGEngine.Database/Models/BaseEntity.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DCGEngine.Database.Interfaces;
|
||||
|
||||
namespace DCGEngine.Database.Models;
|
||||
|
||||
public class BaseEntity<TKey> : ITimeTrackedEntity, IDbTrackedEntity
|
||||
{
|
||||
[Key]
|
||||
public virtual TKey Id { get; set; }
|
||||
|
||||
public DateTime? DateCreated { get; set; }
|
||||
|
||||
public DateTime? DateUpdated { get; set; }
|
||||
}
|
||||
27
DCGEngine.Database/Models/CardEntry.cs
Normal file
27
DCGEngine.Database/Models/CardEntry.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace DCGEngine.Database.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A card within the system.
|
||||
/// </summary>
|
||||
public abstract class CardEntry : BaseEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this card used internally, to separate it from any localization key stored.
|
||||
/// </summary>
|
||||
public virtual string InternalName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The offensive power of this card.
|
||||
/// </summary>
|
||||
public virtual int? Attack { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The defensive power of this card.
|
||||
/// </summary>
|
||||
public virtual int? Defense { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How much of the primary resource (ie mana, energy) does this card cost to play in a match.
|
||||
/// </summary>
|
||||
public virtual int? PrimaryResourceCost { get; set; }
|
||||
}
|
||||
17
DCGEngine.Database/Models/DeckEntry.cs
Normal file
17
DCGEngine.Database/Models/DeckEntry.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace DCGEngine.Database.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A deck consisting of multiple <see cref="CardEntry"/> stored in the DB.
|
||||
/// </summary>
|
||||
public abstract class DeckEntry : BaseEntity<long>
|
||||
{
|
||||
/// <summary>
|
||||
/// How this deck is referred to internally.
|
||||
/// </summary>
|
||||
public virtual string InternalName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The cards present in this deck.
|
||||
/// </summary>
|
||||
public virtual List<CardEntry> Cards { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user