Use EFCore to store preferences (#506)

* Use EFcore to store preferences

* Fixed nullabilty warnings
This commit is contained in:
DamianX
2020-01-15 15:10:18 +01:00
committed by Pieter-Jan Briers
parent 1856cb079c
commit c4ea6e53e8
12 changed files with 473 additions and 359 deletions

View File

@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\RobustToolbox\MSBuild\Robust.Properties.targets"/>
<PropertyGroup>
<!-- Work around https://github.com/dotnet/project-system/issues/4314 -->
<TargetFramework>$(TargetFramework)</TargetFramework>
<LangVersion>8</LangVersion>
<IsPackable>false</IsPackable>
<Platforms>x64</Platforms>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<OutputPath>..\bin\Content.Server.Database\</OutputPath>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="..\RobustToolbox\MSBuild\Robust.DefineConstants.targets"/>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0"/>
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,109 @@
// <auto-generated />
using System;
using Content.Server.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Content.Server.Database.Migrations
{
[DbContext(typeof(PreferencesDbContext))]
[Migration("20200111103836_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.0");
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
{
b.Property<int>("HumanoidProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Age")
.HasColumnType("INTEGER");
b.Property<string>("CharacterName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("EyeColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("FacialHairColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("FacialHairName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("HairColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("HairName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("PrefsId")
.HasColumnType("INTEGER");
b.Property<string>("Sex")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("SkinColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Slot")
.HasColumnType("INTEGER");
b.Property<string>("SlotName")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("HumanoidProfileId");
b.HasIndex("PrefsId");
b.ToTable("HumanoidProfile");
});
modelBuilder.Entity("Content.Server.Database.Prefs", b =>
{
b.Property<int>("PrefsId")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("SelectedCharacterSlot")
.HasColumnType("INTEGER");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("PrefsId");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Preferences");
});
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
{
b.HasOne("Content.Server.Database.Prefs", null)
.WithMany("HumanoidProfiles")
.HasForeignKey("PrefsId");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,71 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Content.Server.Database.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
"Preferences",
table => new
{
PrefsId = table.Column<int>()
.Annotation("Sqlite:Autoincrement", true),
Username = table.Column<string>(),
SelectedCharacterSlot = table.Column<int>()
},
constraints: table => { table.PrimaryKey("PK_Preferences", x => x.PrefsId); });
migrationBuilder.CreateTable(
"HumanoidProfile",
table => new
{
HumanoidProfileId = table.Column<int>()
.Annotation("Sqlite:Autoincrement", true),
Slot = table.Column<int>(),
SlotName = table.Column<string>(),
CharacterName = table.Column<string>(),
Age = table.Column<int>(),
Sex = table.Column<string>(),
HairName = table.Column<string>(),
HairColor = table.Column<string>(),
FacialHairName = table.Column<string>(),
FacialHairColor = table.Column<string>(),
EyeColor = table.Column<string>(),
SkinColor = table.Column<string>(),
PrefsId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_HumanoidProfile", x => x.HumanoidProfileId);
table.ForeignKey(
"FK_HumanoidProfile_Preferences_PrefsId",
x => x.PrefsId,
"Preferences",
"PrefsId",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
"IX_HumanoidProfile_PrefsId",
"HumanoidProfile",
"PrefsId");
migrationBuilder.CreateIndex(
"IX_Preferences_Username",
"Preferences",
"Username",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
"HumanoidProfile");
migrationBuilder.DropTable(
"Preferences");
}
}
}

View File

@@ -0,0 +1,105 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace Content.Server.Database.Migrations
{
[DbContext(typeof(PreferencesDbContext))]
internal class PreferencesDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.0");
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
{
b.Property<int>("HumanoidProfileId")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("Age")
.HasColumnType("INTEGER");
b.Property<string>("CharacterName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("EyeColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("FacialHairColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("FacialHairName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("HairColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("HairName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("PrefsId")
.HasColumnType("INTEGER");
b.Property<string>("Sex")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("SkinColor")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Slot")
.HasColumnType("INTEGER");
b.Property<string>("SlotName")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("HumanoidProfileId");
b.HasIndex("PrefsId");
b.ToTable("HumanoidProfile");
});
modelBuilder.Entity("Content.Server.Database.Prefs", b =>
{
b.Property<int>("PrefsId")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("SelectedCharacterSlot")
.HasColumnType("INTEGER");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("PrefsId");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Preferences");
});
modelBuilder.Entity("Content.Server.Database.HumanoidProfile", b =>
{
b.HasOne("Content.Server.Database.Prefs", null)
.WithMany("HumanoidProfiles")
.HasForeignKey("PrefsId");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace Content.Server.Database
{
public class PreferencesDbContext : DbContext
{
// This is used by the "dotnet ef" CLI tool.
public PreferencesDbContext() :
base(new DbContextOptionsBuilder().UseSqlite("Data Source=:memory:").Options)
{
}
public PreferencesDbContext(DbContextOptions<PreferencesDbContext> options) : base(options)
{
}
public DbSet<Prefs> Preferences { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Prefs>()
.HasIndex(p => p.Username)
.IsUnique();
}
}
public class Prefs
{
public int PrefsId { get; set; }
public string Username { get; set; } = null!;
public int SelectedCharacterSlot { get; set; }
public List<HumanoidProfile> HumanoidProfiles { get; } = new List<HumanoidProfile>();
}
public class HumanoidProfile
{
public int HumanoidProfileId { get; set; }
public int Slot { get; set; }
public string SlotName { get; set; } = null!;
public string CharacterName { get; set; } = null!;
public int Age { get; set; }
public string Sex { get; set; } = null!;
public string HairName { get; set; } = null!;
public string HairColor { get; set; } = null!;
public string FacialHairName { get; set; } = null!;
public string FacialHairColor { get; set; } = null!;
public string EyeColor { get; set; } = null!;
public string SkinColor { get; set; } = null!;
}
}

View File

@@ -0,0 +1,60 @@
using System.Linq;
using Microsoft.EntityFrameworkCore;
namespace Content.Server.Database
{
public class PrefsDb
{
private readonly PreferencesDbContext _prefsCtx;
public PrefsDb(string dbPath)
{
var optionsBuilder = new DbContextOptionsBuilder<PreferencesDbContext>();
optionsBuilder.UseSqlite($"Data Source={dbPath}");
_prefsCtx = new PreferencesDbContext(optionsBuilder.Options);
_prefsCtx.Database.Migrate();
}
public Prefs GetPlayerPreferences(string username)
{
return _prefsCtx.Preferences.SingleOrDefault(p => p.Username == username);
}
public void SaveSelectedCharacterIndex(string username, int slot)
{
var prefs = _prefsCtx.Preferences.SingleOrDefault(p => p.Username == username);
if (prefs is null)
_prefsCtx.Preferences.Add(new Prefs
{
Username = username,
SelectedCharacterSlot = slot
});
else
prefs.SelectedCharacterSlot = slot;
_prefsCtx.SaveChanges();
}
public void SaveCharacterSlot(string username, HumanoidProfile newProfile)
{
var prefs = _prefsCtx
.Preferences
.Single(p => p.Username == username);
var oldProfile = prefs
.HumanoidProfiles
.SingleOrDefault(h => h.Slot == newProfile.Slot);
if (!(oldProfile is null)) prefs.HumanoidProfiles.Remove(oldProfile);
prefs.HumanoidProfiles.Add(newProfile);
}
public void DeleteCharacterSlot(string username, int slot)
{
var profile = _prefsCtx
.Preferences
.Single(p => p.Username == username)
.HumanoidProfiles
.RemoveAll(h => h.Slot == slot);
_prefsCtx.SaveChanges();
}
}
}