IW4M-Admin/SharedLibraryCore/Database/DatabaseContext.cs
RaidMax ed83c4c011 started work on getting the restart functionality in the gamelogserver
fix bug with unbanned players still showing as banned via lock icon
move player based stuff into client class
finally renamed Player to EFClient via partial class
don't try to run this build because it's in between stages
2018-11-05 21:01:29 -06:00

169 lines
6.1 KiB
C#

using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
namespace SharedLibraryCore.Database
{
public class DatabaseContext : DbContext
{
public DbSet<EFClient> Clients { get; set; }
public DbSet<EFAlias> Aliases { get; set; }
public DbSet<EFAliasLink> AliasLinks { get; set; }
public DbSet<EFPenalty> Penalties { get; set; }
public DbSet<EFMeta> EFMeta { get; set; }
public DbSet<EFChangeHistory> EFChangeHistory { get; set; }
static string _ConnectionString;
static string _provider;
private static string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins\";
public DatabaseContext(DbContextOptions<DatabaseContext> opt) : base(opt) { }
public DatabaseContext() { }
public DatabaseContext(bool disableTracking)
{
if (disableTracking)
{
this.ChangeTracker.AutoDetectChangesEnabled = false;
this.ChangeTracker.LazyLoadingEnabled = false;
this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
}
public DatabaseContext(string connStr, string provider)
{
_ConnectionString = connStr;
_provider = provider;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (string.IsNullOrEmpty(_ConnectionString))
{
string currentPath = Utilities.OperatingDirectory;
// allows the application to find the database file
currentPath = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
$"{Path.DirectorySeparatorChar}{currentPath}" :
currentPath;
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = Path.Join(currentPath, "Database", "Database.db") };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
optionsBuilder.UseSqlite(connection);
}
else
{
switch (_provider)
{
default:
case "mysql":
optionsBuilder.UseMySql(_ConnectionString);
break;
case "postgresql":
optionsBuilder.UseNpgsql(_ConnectionString);
break;
}
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// make network id unique
modelBuilder.Entity<EFClient>(entity =>
{
entity.HasIndex(e => e.NetworkId).IsUnique();
});
modelBuilder.Entity<EFPenalty>(entity =>
{
entity.HasOne(p => p.Offender)
.WithMany(c => c.ReceivedPenalties)
.HasForeignKey(c => c.OffenderId)
.OnDelete(DeleteBehavior.Restrict);
entity.HasOne(p => p.Punisher)
.WithMany(p => p.AdministeredPenalties)
.HasForeignKey(c => c.PunisherId)
.OnDelete(DeleteBehavior.Restrict);
entity.Property(p => p.Expires)
.IsRequired(false);
});
modelBuilder.Entity<EFAliasLink>(entity =>
{
entity.HasMany(e => e.Children)
.WithOne(a => a.Link)
.HasForeignKey(k => k.LinkId)
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<EFAlias>(ent =>
{
ent.HasIndex(a => a.IPAddress);
ent.Property(a => a.Name).HasMaxLength(24);
ent.HasIndex(a => a.Name);
});
// force full name for database conversion
modelBuilder.Entity<EFClient>().ToTable("EFClients");
modelBuilder.Entity<EFAlias>().ToTable("EFAlias");
modelBuilder.Entity<EFAliasLink>().ToTable("EFAliasLinks");
modelBuilder.Entity<EFPenalty>().ToTable("EFPenalties");
// adapted from
// https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/
string pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins");
IEnumerable<string> directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
#if DEBUG == TRUE
foreach (string dllPath in Directory.GetFiles(_migrationPluginDirectory).Where(f => f.EndsWith(".dll")))
#else
foreach (string dllPath in directoryFiles)
#endif
{
Assembly library;
try
{
library = Assembly.LoadFrom(dllPath);
}
// not a valid assembly, ie plugin support files
catch (Exception)
{
continue;
}
var configurations = library.ExportedTypes.Where(c => c.GetInterfaces().FirstOrDefault(i => typeof(IModelConfiguration).IsAssignableFrom(i)) != null)
.Select(c => (IModelConfiguration)Activator.CreateInstance(c));
foreach (var configurable in configurations)
{
configurable.Configure(modelBuilder);
}
foreach (var type in library.ExportedTypes)
{
if (type.IsClass && type.IsSubclassOf(typeof(SharedEntity)))
{
var method = modelBuilder.GetType().GetMethod("Entity", new[] { typeof(Type) });
method.Invoke(modelBuilder, new[] { type });
}
}
}
base.OnModelCreating(modelBuilder);
}
}
}