I18NCommander/I18N Commander/DataModel/Database/Common/DataContext.cs

161 lines
5.7 KiB
C#
Raw Normal View History

2022-11-14 19:32:41 +00:00
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.EntityFrameworkCore;
2022-06-12 15:15:30 +00:00
namespace DataModel.Database.Common;
public sealed class DataContext : DbContext, IDataContext
2022-06-12 15:15:30 +00:00
{
2022-07-09 13:03:50 +00:00
public DbSet<Setting> Settings { get; set; }
2022-06-12 15:15:30 +00:00
2022-07-09 13:03:50 +00:00
public DbSet<Section> Sections { get; set; }
2022-06-12 19:42:47 +00:00
2022-07-09 13:03:50 +00:00
public DbSet<TextElement> TextElements { get; set; }
2022-06-12 19:42:47 +00:00
2022-07-09 13:03:50 +00:00
public DbSet<Translation> Translations { get; set; }
2022-06-12 19:42:47 +00:00
2022-06-12 15:15:30 +00:00
public DataContext(DbContextOptions<DataContext> contextOptions) : base(contextOptions)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
2022-06-12 19:42:47 +00:00
#region Settings
2022-06-12 15:15:30 +00:00
modelBuilder.Entity<Setting>().HasIndex(n => n.Id);
2022-07-25 17:03:49 +00:00
modelBuilder.Entity<Setting>().HasIndex(n => n.Code).IsUnique();
2022-06-12 15:15:30 +00:00
modelBuilder.Entity<Setting>().HasIndex(n => n.BoolValue);
modelBuilder.Entity<Setting>().HasIndex(n => n.GuidValue);
modelBuilder.Entity<Setting>().HasIndex(n => n.IntegerValue);
modelBuilder.Entity<Setting>().HasIndex(n => n.TextValue);
#endregion
2022-06-12 19:42:47 +00:00
#region Sections
modelBuilder.Entity<Section>().HasIndex(n => n.Id);
modelBuilder.Entity<Section>().HasIndex(n => n.Name);
modelBuilder.Entity<Section>().HasIndex(n => n.Depth);
modelBuilder.Entity<Section>().HasIndex(n => n.DataKey);
2022-07-16 20:28:40 +00:00
// modelBuilder.Entity<Section>().Navigation(n => n.Parent).AutoInclude(); // Cycle-reference, does not work, though.
modelBuilder.Entity<Section>().Navigation(n => n.TextElements).AutoInclude();
2022-06-12 19:42:47 +00:00
#endregion
#region TextElements
modelBuilder.Entity<TextElement>().HasIndex(n => n.Id);
modelBuilder.Entity<TextElement>().HasIndex(n => n.Code);
2022-07-10 17:30:22 +00:00
modelBuilder.Entity<TextElement>().HasIndex(n => n.Name);
modelBuilder.Entity<TextElement>().HasIndex(n => n.IsMultiLine);
modelBuilder.Entity<TextElement>().Navigation(n => n.Section).AutoInclude();
modelBuilder.Entity<TextElement>().Navigation(n => n.Translations).AutoInclude();
2022-06-12 19:42:47 +00:00
#endregion
#region Translations
modelBuilder.Entity<Translation>().HasIndex(n => n.Id);
modelBuilder.Entity<Translation>().HasIndex(n => n.Culture);
modelBuilder.Entity<Translation>().HasIndex(n => n.Text);
modelBuilder.Entity<Translation>().HasIndex(n => n.TranslateManual);
modelBuilder.Entity<Translation>().Navigation(n => n.TextElement).AutoInclude();
2022-06-12 19:42:47 +00:00
#endregion
2022-06-12 15:15:30 +00:00
}
2022-11-14 19:32:41 +00:00
2023-01-02 19:50:11 +00:00
#region Export and import
2022-11-14 19:32:41 +00:00
private readonly record struct JsonData(
IEnumerable<JsonSetting> Settings,
IEnumerable<JsonSection> Sections,
IEnumerable<JsonTextElement> TextElements,
IEnumerable<JsonTranslation> Translations
);
internal readonly record struct JsonUniqueId(string Code, Guid UniqueId, string Prefix = "")
{
public override string ToString() => string.IsNullOrWhiteSpace(this.Prefix) ? $"{this.Code}::{this.UniqueId}" : $"{this.Prefix}::{this.Code}::{this.UniqueId}";
public static implicit operator string(JsonUniqueId id) => id.ToString();
}
private sealed class JsonUniqueIdConverter : JsonConverter<JsonUniqueId>
{
public override JsonUniqueId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var json = reader.GetString();
var parts = json?.Split("::");
return parts?.Length switch
{
2 => new JsonUniqueId(parts[0], Guid.Parse(parts[1])),
3 => new JsonUniqueId(parts[1], Guid.Parse(parts[2]), parts[0]),
_ => throw new JsonException($"Invalid format of JsonUniqueId: {json}")
};
}
public override void Write(Utf8JsonWriter writer, JsonUniqueId value, JsonSerializerOptions options)
{
writer.WriteStringValue(value);
}
}
internal readonly record struct JsonSetting(
JsonUniqueId UniqueId,
string Code,
string TextValue,
int IntegerValue,
bool BoolValue,
Guid GuidValue
);
internal readonly record struct JsonSection(
JsonUniqueId UniqueId,
string Name,
string DataKey,
int Depth,
JsonUniqueId ParentUniqueId,
List<JsonUniqueId> TextElements
);
internal readonly record struct JsonTextElement(
JsonUniqueId UniqueId,
string Code,
string Name,
bool IsMultiLine,
JsonUniqueId SectionUniqueId,
List<JsonUniqueId> Translations
);
internal readonly record struct JsonTranslation(
JsonUniqueId UniqueId,
string Culture,
string Text,
bool TranslateManual,
JsonUniqueId TextElementUniqueId
);
public async Task ExportAsync(string path)
{
var jsonSettings = new JsonSerializerOptions
{
WriteIndented = true,
Converters = { new JsonUniqueIdConverter() },
};
await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
await JsonSerializer.SerializeAsync(fileStream,
new JsonData
{
Settings = this.Settings.Select(n => n.ToJsonSetting()),
Sections = this.Sections.Select(n => n.ToJsonSection()),
TextElements = this.TextElements.Select(n => n.ToJsonTextElement()),
Translations = this.Translations.Select(n => n.ToJsonTranslation()),
}, jsonSettings);
}
2023-01-02 19:50:11 +00:00
#endregion
2022-06-12 15:15:30 +00:00
}