Глобальное обновление #1

Merged
kozhilya merged 33 commits from dev into master 2025-06-01 22:28:15 +04:00
36 changed files with 200 additions and 360 deletions
Showing only changes of commit 2b61669e7a - Show all commits
+3
View File
@@ -6,3 +6,6 @@ OUTPUT_DIR=D:\path\to\output\directory
# Строка подключения к БД # Строка подключения к БД
DATABASE_CONNECTION=Host=localhost;Port=5433;Database=usersdb2;Username=postgres;Password=password DATABASE_CONNECTION=Host=localhost;Port=5433;Database=usersdb2;Username=postgres;Password=password
# Максимальное количество потоков.
MAX_THREADS=60
+1 -1
View File
@@ -30,7 +30,7 @@ public class ProcessorAttribute(string name) : Attribute
/// <summary> /// <summary>
/// Разрешить выполнять процессов в параллельном режиме /// Разрешить выполнять процессов в параллельном режиме
/// </summary> /// </summary>
public bool Parallel { get; init; } = true; public bool Parallel { get; init; } = false;
/// <summary> /// <summary>
/// Обработчик набора элементов /// Обработчик набора элементов
@@ -90,6 +90,7 @@ internal class ProcessorCollection
InnerType = innerType, InnerType = innerType,
Compendium = compendium, Compendium = compendium,
Active = processorAttribute.Active, Active = processorAttribute.Active,
Parallel = processorAttribute.Parallel,
}; };
} }
@@ -241,4 +242,9 @@ internal class ProcessorCollectionItem
/// <c>null</c> - обработать все типы. /// <c>null</c> - обработать все типы.
/// </summary> /// </summary>
public ProcessorCompendiumEnum? Compendium { get; init; } public ProcessorCompendiumEnum? Compendium { get; init; }
/// <summary>
/// Разрешить выполнять процессов в параллельном режиме
/// </summary>
public bool Parallel { get; init; } = true;
} }
+10
View File
@@ -19,6 +19,7 @@ internal class ApplicationSettings
DataDirPath = EnvReader.GetStringValue("DATA_DIR"); DataDirPath = EnvReader.GetStringValue("DATA_DIR");
OutputDirPath = EnvReader.GetStringValue("OUTPUT_DIR"); OutputDirPath = EnvReader.GetStringValue("OUTPUT_DIR");
DatabaseConnection = EnvReader.GetStringValue("DATABASE_CONNECTION"); DatabaseConnection = EnvReader.GetStringValue("DATABASE_CONNECTION");
MaxThreads = Convert.ToInt32(EnvReader.GetStringValue("MAX_THREADS"));
} }
#region Настройки из .env #region Настройки из .env
@@ -62,6 +63,15 @@ internal class ApplicationSettings
[Description("Редактирование через .env-файл.")] [Description("Редактирование через .env-файл.")]
public string DatabaseConnection { get; } public string DatabaseConnection { get; }
/// <summary>
/// Максимальное количество потоков.
/// </summary>
[Browsable(true)]
[ReadOnly(true)]
[DisplayName("Максимальное количество потоков.")]
[Description("Редактирование через .env-файл.")]
public int MaxThreads { get; }
#endregion #endregion
#region Основные настройки #region Основные настройки
@@ -1,4 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using Pf2eDataScrapper.Forms.Controls.EntityTreeViewer;
namespace Pf2eViewer.EntityTreeViewer; namespace Pf2eViewer.EntityTreeViewer;
@@ -1,4 +1,5 @@
using FontAwesome.Sharp; using FontAwesome.Sharp;
using Pf2eDataScrapper.Forms.Controls.EntityTreeViewer;
using Font = System.Drawing.Font; using Font = System.Drawing.Font;
using FontStyle = System.Drawing.FontStyle; using FontStyle = System.Drawing.FontStyle;
using Image = System.Drawing.Image; using Image = System.Drawing.Image;
@@ -3,7 +3,7 @@ using System.Reflection;
using LinqToDB.Extensions; using LinqToDB.Extensions;
using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Common.I18n;
namespace Pf2eViewer.EntityTreeViewer; namespace Pf2eDataScrapper.Forms.Controls.EntityTreeViewer;
/// <summary> /// <summary>
/// Класс для построения структуры данных класса. /// Класс для построения структуры данных класса.
@@ -54,7 +54,7 @@ internal partial class ProcessorCollectionControl : UserControl
FlowDirection = FlowDirection.LeftToRight, FlowDirection = FlowDirection.LeftToRight,
WrapContents = true, WrapContents = true,
BorderStyle = BorderStyle.FixedSingle, BorderStyle = BorderStyle.FixedSingle,
Margin = new Padding(10, 0, 10, 15), Margin = new(10, 0, 10, 15),
}; };
RootFlowLayoutPanel.Controls.Add(GroupCheckBoxes[group]); RootFlowLayoutPanel.Controls.Add(GroupCheckBoxes[group]);
@@ -125,7 +125,6 @@ internal class ProcessProgress : AbstractLogger
/// </summary> /// </summary>
public void End() public void End()
{ {
_text = "";
_current++; _current++;
Update?.Invoke(); Update?.Invoke();
} }
+5
View File
@@ -177,7 +177,12 @@ internal sealed class ImportApplication : ApplicationContext
public static void RegisterServices(IServiceCollection services) public static void RegisterServices(IServiceCollection services)
{ {
// Контекст базы данных // Контекст базы данных
services.AddEntityFrameworkNpgsql();
services.AddDbContext<Pf2eDbContext>(); services.AddDbContext<Pf2eDbContext>();
//services.AddDbContextPool<Pf2eDbContext>(options =>
//{
// options.Us
//});
// Основная программа // Основная программа
services.AddSingleton<ImportApplication>(); services.AddSingleton<ImportApplication>();
@@ -30,7 +30,6 @@ internal class AonprdImporter : AbstractImporter
services.AddSingleton<AonprdCompendium>(); services.AddSingleton<AonprdCompendium>();
services.AddSingleton<AonprdBuilderGlobals>(); services.AddSingleton<AonprdBuilderGlobals>();
services.AddSingleton<LegacyEntityHandler>();
services.AddSingleton<RuleTocCollection>(); services.AddSingleton<RuleTocCollection>();
services.AddTransient<StringHelper>(); services.AddTransient<StringHelper>();
@@ -4,14 +4,23 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
/// <summary> /// <summary>
/// Класс-помощник, хранящий необходимые глобальные данные. /// Класс-помощник, хранящий необходимые глобальные данные.
/// Реализует шаблон <c>Singleton</c>.
/// </summary> /// </summary>
internal class AonprdBuilderGlobals internal class AonprdBuilderGlobals
{ {
/// <summary> /// <summary>
/// Цель внешних ссылок Архивов Нефисов. /// Цель внешних ссылок Архивов Нефисов.
/// </summary> /// </summary>
public ExternalTarget AonprdTarget = null!; public ExternalTarget AonprdTarget { get; set; } = null!;
/// <summary>
/// Словарь идентификаторов источников.
/// </summary>
public Dictionary<string, int> SourceIds { get; set; } = [];
/// <summary>
/// Словарь идентификаторов признаков.
/// </summary>
public Dictionary<string, int> TraitIds { get; set; } = [];
/// <summary> /// <summary>
/// Конструктор класса <see cref="AonprdBuilderGlobals"/>. /// Конструктор класса <see cref="AonprdBuilderGlobals"/>.
@@ -1,105 +0,0 @@
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Common.I18n;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
/// <summary>
/// Обработчик сущностей, помеченных как устаревшие.
/// </summary>
internal class LegacyEntityHandler
{
/// <summary>
/// Идентификатор устаревшей сущности.
/// </summary>
public string LegacyId { get; private set; }
/// <summary>
/// Название устаревшей сущности.
/// </summary>
public string LegacyName { get; private set; } = "";
/// <summary>
/// Коллекция источников устревшей сущности.
/// </summary>
public List<EntitySource> LegacySources { get; private set; } = [];
/// <summary>
/// Флаг, указывающий, что сведения об устаревшей сущности готовы к добавлению в обновлённые.
/// </summary>
public bool LegacyPrepared { get; private set; } = false;
/// <summary>
/// Список обновлённых сущностей, что отметели устаревшую сущность как предшественника.
/// </summary>
public List<Entity> RemasterEntities { get; } = [];
/// <summary>
/// Конструктор класса <see cref="LegacyEntityHandler"/>, если сущность сама отмечена как устаревшая.
/// </summary>
/// <param name="processor">Обработчик устаревшей сущности.</param>
public LegacyEntityHandler(AbstractEntityProcessor processor)
{
LegacyId = processor.Input.GetRequired<string>("id");
Prepare(processor);
}
/// <summary>
/// Конструктор класса <see cref="LegacyEntityHandler"/>, если обновлённая сущность указывает на ещё недобавленную устаревшую сущность.
/// </summary>
/// <param name="legacyId">Идентификатор устаревшей сущности.</param>
/// <param name="remasterEntity">Обновлённая сущность.</param>
public LegacyEntityHandler(string legacyId, Entity remasterEntity)
{
LegacyId = legacyId;
LegacyPrepared = false;
RemasterEntities.Add(remasterEntity);
}
/// <summary>
/// Подготовить данные об устравшей сущности.
/// </summary>
/// <param name="processor">Обработчик устаревшей сущности.</param>
public void Prepare(AbstractEntityProcessor processor)
{
if (LegacyPrepared)
{
return;
}
LegacyName = processor.Input.GetRequired<string>("name");
LegacySources = processor.GetSources();
LegacyPrepared = true;
foreach (Entity remasterEntity in RemasterEntities)
{
Apply(remasterEntity);
}
}
/// <summary>
/// Применить данные устаревшей сущности к обновлённой.
/// </summary>
/// <param name="remasterEntity">Обновлённая сущность.</param>
public void Apply(Entity remasterEntity)
{
if (!remasterEntity.Name.Contains(LegacyName))
{
remasterEntity.Name[LocaleType.LegacyEnglish] = LegacyName;
}
foreach (EntitySource legacySource in LegacySources)
{
EntitySource entitySource = new()
{
Entity = remasterEntity,
Source = legacySource.Source,
Suffix = legacySource.Suffix,
IsRemaster = false,
};
remasterEntity.Sources.Add(entitySource);
}
}
}
@@ -1,8 +1,4 @@
using System.Collections.Concurrent; using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Pf2eDataScrapper.App; using Pf2eDataScrapper.App;
@@ -31,13 +27,12 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
/// <seealso cref="ProcessorAttribute"/> /// <seealso cref="ProcessorAttribute"/>
internal abstract class AbstractEntityProcessor( internal abstract class AbstractEntityProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractInputProcessor(input) ) : AbstractInputProcessor(input)
{ {
public Pf2eDbContext Context { get; } = context; public Pf2eDbContext Context { get; } = new();
public StringHelper StringHelper { get; } = stringHelper; public StringHelper StringHelper { get; } = stringHelper;
public DatabaseHelper Helper { get; } = helper; public DatabaseHelper Helper { get; } = helper;
public AonprdBuilderGlobals Globals { get; } = globals; public AonprdBuilderGlobals Globals { get; } = globals;
@@ -60,19 +55,22 @@ internal abstract class AbstractEntityProcessor(
/// <summary> /// <summary>
/// Добавление основной сущности в контекст базы данных. /// Добавление основной сущности в контекст базы данных.
/// </summary> /// </summary>
public abstract void Add(); protected abstract void Add();
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
{ {
ProcessRemaster(); if (Input.GetOptional<JArray>("remaster_id") is not null)
{
throw new LegacyItemException(Input.GetOptional<string>("name", ""));
}
AddEntity(); AddEntity();
AddSource(); AddSource();
AddExternal(); AddExternal();
AddTraits(); AddTraits();
ProcessLegacy(); AddLegacy();
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -116,6 +114,23 @@ internal abstract class AbstractEntityProcessor(
protected virtual string GetDescription() => protected virtual string GetDescription() =>
Input.GetRequired<string>("markdown") + AddedDescription(AddedDescriptionPaths()); Input.GetRequired<string>("markdown") + AddedDescription(AddedDescriptionPaths());
/// <summary>
/// Генерация JSON-строки из объектов, располагаюхися по путям, указанным в <paramref name="paths"/>.
/// </summary>
/// <param name="paths">Коллекция путей, из которых необходимо достатить объекты.</param>
/// <returns>JSON-строка.</returns>
protected string GenerateJsonString(params ICollection<string> paths)
{
Dictionary<string, object?> data = [];
foreach (string key in paths)
{
data.Add(key, Input.Input.SelectToken(key));
}
return JsonConvert.SerializeObject(data, new JsonSerializerSettings());
}
#endregion #endregion
#region "Генерация сущности" #region "Генерация сущности"
@@ -146,8 +161,29 @@ internal abstract class AbstractEntityProcessor(
/// </summary> /// </summary>
protected virtual void AddSource() protected virtual void AddSource()
{ {
foreach (EntitySource entitySource in GetSources()) string[] sourceNames = Input
.GetRequired<JArray>("source")
.Select(token => token.ToString())
.ToArray();
if (sourceNames.Length == 0)
{ {
throw new(
$"Источники для сущности \"{Entity.Name[LocaleType.English]}\" "
+ $"(Aonprd id \"{Input.GetRequired<string>("id")}\") не найдены."
);
}
foreach (string sourceName in sourceNames)
{
EntitySource entitySource = new()
{
Entity = Entity,
SourceId = Globals.SourceIds[sourceName],
Suffix = StringHelper.ResolveSource(Input.GetRequired<string>("source_markdown")),
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null,
};
Entity.Sources.Add(entitySource); Entity.Sources.Add(entitySource);
} }
} }
@@ -160,7 +196,7 @@ internal abstract class AbstractEntityProcessor(
EntityExternal external = new() EntityExternal external = new()
{ {
Entity = Entity, Entity = Entity,
Target = Globals.AonprdTarget, TargetId = Globals.AonprdTarget.Id,
ExternalId = Input.GetRequired<string>("id"), ExternalId = Input.GetRequired<string>("id"),
Suffix = Input.GetRequired<string>("url"), Suffix = Input.GetRequired<string>("url"),
Md5 = Input.Md5(), Md5 = Input.Md5(),
@@ -182,26 +218,11 @@ internal abstract class AbstractEntityProcessor(
return; return;
} }
IEnumerable<string> names = traitsJson.ToArray().Select(jToken => jToken.ToString()); List<string> names = traitsJson.ToArray().Select(jToken => jToken.ToString()).ToList();
List<Entity> traitEntities = Context
.Traits.Select(t => t.Entity)
// ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall
.Where(e => Pf2eDbContext.LocaleSearchArray(e.Name, names))
.ToList();
List<Trait> traits = Context List<int> traitIds = names.Select(name => Globals.TraitIds[name]).ToList();
.Traits.Include(t => t.Entity)
.Where(t => traitEntities.Contains(t.Entity))
.ToList();
foreach (string name in names) List<Trait> traits = Context.Traits.Where(t => traitIds.Contains(t.Id)).ToList();
{
if (!traits.Any(t => t.Entity.Name.Contains(name)))
{
//TODO
//throw new Exception($"Trait '{name}' is not found!!!");
}
}
foreach (Trait trait in traits) foreach (Trait trait in traits)
{ {
@@ -209,138 +230,29 @@ internal abstract class AbstractEntityProcessor(
} }
} }
#endregion
/// <summary> /// <summary>
/// Обработка сущности, отмеченной как устаревшей. /// Добавление устаревших сущностей.
///
/// Обработка происходит в классе <see cref="LegacyEntityHandler"/>
/// </summary> /// </summary>
protected virtual void ProcessLegacy() protected virtual void AddLegacy()
{ {
JArray? legacyIdArray = Input.GetOptional<JArray>("legacy_id"); JArray? legacyIdArray = Input.GetOptional<JArray>("legacy_id");
if (legacyIdArray is null) if (legacyIdArray is null || legacyIdArray.Count == 0)
{ {
return; return;
} }
string[] legacyIds = legacyIdArray.ToArray().Select(t => t.ToString()).ToArray(); string[] legacyIds = legacyIdArray.ToArray().Select(t => t.ToString()).ToArray();
List<LegacyEntity> legacyEntities = Context
.LegacyEntityExternals.Where(lee => legacyIds.Contains(lee.ExternalId))
.Select(lee => lee.LegacyEntity)
.ToList();
if (legacyIds.Length == 0) foreach (LegacyEntity legacyEntity in legacyEntities)
{ {
return; Entity.LegacyEntities.Add(legacyEntity);
}
foreach (string legacyId in legacyIds)
{
LegacyEntityHandler? handler = LegacyHandlers.FirstOrDefault(h =>
h.LegacyId == legacyId
);
if (handler is not null)
{
handler.Apply(Entity);
}
else
{
handler = new(legacyId, Entity);
LegacyHandlers.Add(handler);
}
} }
} }
protected virtual void ProcessRemaster() #endregion
{
JArray? remasterIdArray = Input.GetOptional<JArray>("remaster_id");
if (remasterIdArray is null)
{
return;
}
if (remasterIdArray.Count > 1)
{
throw new("Несколько отметок ремастер-сущности на устаревшие!");
}
string[] remasterIds = remasterIdArray.ToArray().Select(t => t.ToString()).ToArray();
foreach (string remasterId in remasterIds)
{
LegacyEntityHandler? handler = null;
//LegacyHandlers.FirstOrDefault(h =>
// h.RemasterEntities.Contains(remasterId)
//);
if (handler is null)
{
handler = new(this);
LegacyHandlers.Add(handler);
}
else { }
}
throw new LegacyItemException(Input.GetRequired<string>("name"));
}
/// <summary>
/// Получение списка источников сущности.
/// </summary>
/// <returns></returns>
public List<EntitySource> GetSources()
{
string[] sourceNames = Input
.GetRequired<JArray>("source")
.Select(token => token.ToString())
.ToArray();
if (sourceNames.Length == 0)
{
throw new(
$"Source for entity with id \"{Entity.Name[LocaleType.English]}\" "
+ $"(Aonprd id \"{Input.GetRequired<string>("id")}\") is not found"
);
}
List<EntitySource> entitySources = [];
foreach (string sourceName in sourceNames)
{
Source source =
Context.Sources.FirstOrDefault(s => s.Name == sourceName)
?? throw new($"Source \"{sourceName}\" did not found");
EntitySource entitySource = new()
{
Entity = Entity,
Source = source,
Suffix = StringHelper.ResolveSource(Input.GetRequired<string>("source_markdown")),
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null,
};
entitySources.Add(entitySource);
}
return entitySources;
}
/// <summary>
/// Генерация JSON-строки из объектов, располагаюхися по путям, указанным в <paramref name="paths"/>.
/// </summary>
/// <param name="paths">Коллекция путей, из которых необходимо достатить объекты.</param>
/// <returns>JSON-строка.</returns>
public string GenerateJsonString(params ICollection<string> paths)
{
Dictionary<string, object?> data = [];
foreach (string key in paths)
{
data.Add(key, Input.Input.SelectToken(key));
}
return JsonConvert.SerializeObject(data, new JsonSerializerSettings());
}
protected static readonly ConcurrentBag<LegacyEntityHandler> LegacyHandlers = [];
} }
@@ -18,11 +18,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors;
/// </summary> /// </summary>
internal abstract class AbstractSubclassProcessor( internal abstract class AbstractSubclassProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Subclass; public override EntityType Type => EntityType.Subclass;
@@ -41,7 +40,7 @@ internal abstract class AbstractSubclassProcessor(
public abstract string GroupName { get; } public abstract string GroupName { get; }
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Subclasses.Add(Object); protected override void Add() => Context.Subclasses.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -12,10 +12,9 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
Group = ProcessorGroupEnum.AonprdPreparation Group = ProcessorGroupEnum.AonprdPreparation
)] )]
[ProcessorDependencies(["aonprd:repository"])] [ProcessorDependencies(["aonprd:repository"])]
internal class ExternalProcessor(Pf2eDbContext context, AonprdBuilderGlobals globals) internal class ExternalProcessor(AonprdBuilderGlobals globals) : AbstractProcessor
: AbstractProcessor
{ {
public Pf2eDbContext Context { get; } = context; public Pf2eDbContext Context { get; } = new();
public AonprdBuilderGlobals Globals { get; } = globals; public AonprdBuilderGlobals Globals { get; } = globals;
public ExternalTarget AonprdTarget = null!; public ExternalTarget AonprdTarget = null!;
@@ -33,6 +32,7 @@ internal class ExternalProcessor(Pf2eDbContext context, AonprdBuilderGlobals glo
public override void Save() public override void Save()
{ {
Context.ExternalTargets.Add(AonprdTarget); Context.ExternalTargets.Add(AonprdTarget);
Context.SaveChanges();
Globals.AonprdTarget = AonprdTarget; Globals.AonprdTarget = AonprdTarget;
} }
@@ -5,7 +5,6 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
using Pf2eDataScrapper.Processors; using Pf2eDataScrapper.Processors;
using Pf2eModel; using Pf2eModel;
using Pf2eModel.Model.Base.Legacy; using Pf2eModel.Model.Base.Legacy;
using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Common.I18n;
namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common; namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
@@ -15,17 +14,17 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
InnerType = null, InnerType = null,
CompendiumType = ProcessorCompendiumEnum.Aonprd, CompendiumType = ProcessorCompendiumEnum.Aonprd,
Description = "Создание ссылок на устаревшие сущности", Description = "Создание ссылок на устаревшие сущности",
Group = ProcessorGroupEnum.AonprdPreparation Group = ProcessorGroupEnum.AonprdPreparation,
Parallel = true
)] )]
[ProcessorDependencies(["aonprd:source", "aonprd:external"])] [ProcessorDependencies(["aonprd:source", "aonprd:external"])]
internal class LegacyProcessor( internal class LegacyProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
AonprdBuilderGlobals globals, AonprdBuilderGlobals globals,
StringHelper stringHelper StringHelper stringHelper
) : AbstractInputProcessor(input) ) : AbstractInputProcessor(input)
{ {
public Pf2eDbContext Context { get; } = context; public Pf2eDbContext Context { get; } = new();
public AonprdBuilderGlobals Globals { get; } = globals; public AonprdBuilderGlobals Globals { get; } = globals;
public StringHelper StringHelper { get; } = stringHelper; public StringHelper StringHelper { get; } = stringHelper;
@@ -33,8 +32,6 @@ internal class LegacyProcessor(
public override void Process() public override void Process()
{ {
JArray? remasterIdArray = Input.GetOptional<JArray>("remaster_id");
if (Input.GetOptional<JArray>("remaster_id") is null) if (Input.GetOptional<JArray>("remaster_id") is null)
{ {
throw new SilentSkipItemException(); throw new SilentSkipItemException();
@@ -53,18 +50,6 @@ internal class LegacyProcessor(
/// Генерация источников сущности. /// Генерация источников сущности.
/// </summary> /// </summary>
protected virtual void AddSource() protected virtual void AddSource()
{
foreach (LegacyEntitySource entitySource in GetSources())
{
LegacyEntity.Sources.Add(entitySource);
}
}
/// <summary>
/// Получение списка источников сущности.
/// </summary>
/// <returns></returns>
public List<LegacyEntitySource> GetSources()
{ {
string[] sourceNames = Input string[] sourceNames = Input
.GetRequired<JArray>("source") .GetRequired<JArray>("source")
@@ -78,27 +63,25 @@ internal class LegacyProcessor(
+ $"(Aonprd id \"{Input.GetRequired<string>("id")}\") is not found" + $"(Aonprd id \"{Input.GetRequired<string>("id")}\") is not found"
); );
} }
/*
List<LegacyEntitySource> entitySources = []; Dictionary<string, int> sourceIds = Context
.Sources.AsNoTracking()
.Where(s => sourceNames.Contains(s.Name))
.ToDictionary(s => s.Name, s => s.Id);
*/
foreach (string sourceName in sourceNames) foreach (string sourceName in sourceNames)
{ {
Source source =
Context.Sources.FirstOrDefault(s => s.Name == sourceName)
?? throw new($"Source \"{sourceName}\" did not found");
LegacyEntitySource entitySource = new() LegacyEntitySource entitySource = new()
{ {
LegacyEntity = LegacyEntity, LegacyEntity = LegacyEntity,
Source = source, SourceId = Globals.SourceIds[sourceName],
Suffix = StringHelper.ResolveSource(Input.GetRequired<string>("source_markdown")), Suffix = StringHelper.ResolveSource(Input.GetRequired<string>("source_markdown")),
IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null, IsRemaster = Input.GetOptional<JArray>("legacy_id") is not null,
}; };
entitySources.Add(entitySource); Context.LegacyEntitySources.Add(entitySource);
LegacyEntity.Sources.Add(entitySource);
} }
return entitySources;
} }
/// <summary> /// <summary>
@@ -109,7 +92,7 @@ internal class LegacyProcessor(
LegacyEntityExternal external = new() LegacyEntityExternal external = new()
{ {
LegacyEntity = LegacyEntity, LegacyEntity = LegacyEntity,
Target = Globals.AonprdTarget, TargetId = Globals.AonprdTarget.Id,
ExternalId = Input.GetRequired<string>("id"), ExternalId = Input.GetRequired<string>("id"),
Suffix = Input.GetRequired<string>("url"), Suffix = Input.GetRequired<string>("url"),
Md5 = Input.Md5(), Md5 = Input.Md5(),
@@ -121,5 +104,10 @@ internal class LegacyProcessor(
public override void Save() public override void Save()
{ {
Context.LegacyEntities.Add(LegacyEntity); Context.LegacyEntities.Add(LegacyEntity);
Context.SaveChanges(false);
Context.Dispose();
} }
private static readonly Lock Lock = new();
} }
@@ -1,4 +1,5 @@
using Pf2eDataScrapper.App; using Pf2eDataScrapper.App;
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
using Pf2eDataScrapper.Processors; using Pf2eDataScrapper.Processors;
using Pf2eModel; using Pf2eModel;
using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Base.Source;
@@ -14,10 +15,11 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Common;
Group = ProcessorGroupEnum.AonprdPreparation Group = ProcessorGroupEnum.AonprdPreparation
)] )]
[ProcessorDependencies(["aonprd:compendium"])] [ProcessorDependencies(["aonprd:compendium"])]
internal class SourceProcessor(ProcessorInput input, Pf2eDbContext context) internal class SourceProcessor(ProcessorInput input, AonprdBuilderGlobals globals)
: AbstractInputProcessor(input) : AbstractInputProcessor(input)
{ {
public Pf2eDbContext Context { get; } = context; public AonprdBuilderGlobals Globals { get; } = globals;
public Pf2eDbContext Context { get; } = new();
/// <summary> /// <summary>
/// Источник сущности. /// Источник сущности.
@@ -39,5 +41,8 @@ internal class SourceProcessor(ProcessorInput input, Pf2eDbContext context)
public override void Save() public override void Save()
{ {
Context.Sources.Add(Source); Context.Sources.Add(Source);
Context.SaveChanges();
Globals.SourceIds.Add(Source.Name, Source.Id);
} }
} }
@@ -24,11 +24,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Subclasse
)] )]
internal class ApparitionProcessor( internal class ApparitionProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractSubclassProcessor(input, context, stringHelper, helper, globals) ) : AbstractSubclassProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override Subclass Object { get; } = new(); public override Subclass Object { get; } = new();
@@ -18,11 +18,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
internal class ActionProcessor( internal class ActionProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Action; public override EntityType Type => EntityType.Action;
@@ -31,7 +30,7 @@ internal class ActionProcessor(
public override Pf2eModel.Model.Structure.Action Object { get; } = new(); public override Pf2eModel.Model.Structure.Action Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Actions.Add(Object); protected override void Add() => Context.Actions.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -20,11 +20,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:language"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:language"])]
internal class AncestryProcessor( internal class AncestryProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Ancestry; public override EntityType Type => EntityType.Ancestry;
@@ -33,7 +32,7 @@ internal class AncestryProcessor(
public override Ancestry Object { get; } = new(); public override Ancestry Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Ancestries.Add(Object); protected override void Add() => Context.Ancestries.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -19,11 +19,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
internal class ArchetypeProcessor( internal class ArchetypeProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Archetype; public override EntityType Type => EntityType.Archetype;
@@ -32,7 +31,7 @@ internal class ArchetypeProcessor(
public override Archetype Object { get; } = new(); public override Archetype Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Archetypes.Add(Object); protected override void Add() => Context.Archetypes.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -21,11 +21,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
internal class BackgroundProcessor( internal class BackgroundProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Background; public override EntityType Type => EntityType.Background;
@@ -34,7 +33,7 @@ internal class BackgroundProcessor(
public override Background Object { get; } = new(); public override Background Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Backgrounds.Add(Object); protected override void Add() => Context.Backgrounds.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -25,11 +25,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])]
internal partial class ClassProcessor( internal partial class ClassProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Class; public override EntityType Type => EntityType.Class;
@@ -38,7 +37,7 @@ internal partial class ClassProcessor(
public override Class Object { get; } = new(); public override Class Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Classes.Add(Object); protected override void Add() => Context.Classes.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -20,11 +20,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:archetype"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:archetype"])]
internal class FeatProcessor( internal class FeatProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Feat; public override EntityType Type => EntityType.Feat;
@@ -33,7 +32,7 @@ internal class FeatProcessor(
public override Feat Object { get; } = new(); public override Feat Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Feats.Add(Object); protected override void Add() => Context.Feats.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -19,11 +19,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
internal class LanguageProcessor( internal class LanguageProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Language; public override EntityType Type => EntityType.Language;
@@ -32,5 +31,5 @@ internal class LanguageProcessor(
public override Language Object { get; } = new(); public override Language Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Languages.Add(Object); protected override void Add() => Context.Languages.Add(Object);
} }
@@ -23,11 +23,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:skill"])]
internal partial class RitualProcessor( internal partial class RitualProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Ritual; public override EntityType Type => EntityType.Ritual;
@@ -36,7 +35,7 @@ internal partial class RitualProcessor(
public override Ritual Object { get; } = new(); public override Ritual Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Rituals.Add(Object); protected override void Add() => Context.Rituals.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -5,7 +5,6 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
using Pf2eDataScrapper.Processors; using Pf2eDataScrapper.Processors;
using Pf2eModel; using Pf2eModel;
using Pf2eModel.Model.Base.Legacy;
using Pf2eModel.Model.Base.Source; using Pf2eModel.Model.Base.Source;
using Pf2eModel.Model.Base.Targets; using Pf2eModel.Model.Base.Targets;
using Pf2eModel.Model.Common.I18n; using Pf2eModel.Model.Common.I18n;
@@ -18,17 +17,16 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types.Rul
"aonprd:rules", "aonprd:rules",
InnerType = "rules", InnerType = "rules",
CompendiumType = ProcessorCompendiumEnum.Aonprd, CompendiumType = ProcessorCompendiumEnum.Aonprd,
Description = "Создание цели внешних ссылок", Description = "Правила",
Group = ProcessorGroupEnum.AonprdEntities Group = ProcessorGroupEnum.AonprdEntities
)] )]
[ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:rules-toc"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source", "aonprd:rules-toc"])]
internal class RuleProcessor( internal class RuleProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Rule; public override EntityType Type => EntityType.Rule;
@@ -37,7 +35,7 @@ internal class RuleProcessor(
public override Rule Object { get; } = new(); public override Rule Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Rules.Add(Object); protected override void Add() => Context.Rules.Add(Object);
/// <summary> /// <summary>
/// Структура генерации содержания правил. /// Структура генерации содержания правил.
@@ -22,11 +22,10 @@ namespace Pf2eDataScrapper.Importers.Implementations.Aonprd.Processors.Types;
[ProcessorDependencies(["aonprd:trait", "aonprd:source"])] [ProcessorDependencies(["aonprd:trait", "aonprd:source"])]
internal class SpellProcessor( internal class SpellProcessor(
ProcessorInput input, ProcessorInput input,
Pf2eDbContext context,
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Spell; public override EntityType Type => EntityType.Spell;
@@ -35,7 +34,7 @@ internal class SpellProcessor(
public override Spell Object { get; } = new(); public override Spell Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Spells.Add(Object); protected override void Add() => Context.Spells.Add(Object);
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -4,6 +4,8 @@ using Pf2eDataScrapper.Importers.Implementations.Aonprd.DataBuilder.Helpers;
using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers; using Pf2eDataScrapper.Importers.Implementations.Aonprd.Helpers;
using Pf2eDataScrapper.Processors; using Pf2eDataScrapper.Processors;
using Pf2eModel; using Pf2eModel;
using Pf2eModel.Model.Base.Legacy;
using Pf2eModel.Model.Common.I18n;
using Pf2eModel.Model.Enum; using Pf2eModel.Model.Enum;
using Pf2eModel.Model.Structure; using Pf2eModel.Model.Structure;
@@ -23,7 +25,7 @@ internal class TraitProcessor(
StringHelper stringHelper, StringHelper stringHelper,
DatabaseHelper helper, DatabaseHelper helper,
AonprdBuilderGlobals globals AonprdBuilderGlobals globals
) : AbstractEntityProcessor(input, context, stringHelper, helper, globals) ) : AbstractEntityProcessor(input, stringHelper, helper, globals)
{ {
/// <inheritdoc/> /// <inheritdoc/>
public override EntityType Type => EntityType.Trait; public override EntityType Type => EntityType.Trait;
@@ -32,7 +34,17 @@ internal class TraitProcessor(
public override Trait Object { get; } = new(); public override Trait Object { get; } = new();
/// <inheritdoc/> /// <inheritdoc/>
public override void Add() => Context.Traits.Add(Object); protected override void Add()
{
Context.Traits.Add(Object);
Globals.TraitIds[Entity.Name[LocaleType.English]] = Entity.Id;
foreach (LegacyEntity legacyEntity in Entity.LegacyEntities)
{
Globals.TraitIds[legacyEntity.Name[LocaleType.English]] = Entity.Id;
}
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Process() public override void Process()
@@ -1,4 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Pf2eDataScrapper.App; using Pf2eDataScrapper.App;
@@ -16,15 +17,16 @@ internal sealed class ProcessorExecutor(
ProcessProgress progress, ProcessProgress progress,
Pf2eDbContext context, Pf2eDbContext context,
AonprdCompendium aonprdCompendium, AonprdCompendium aonprdCompendium,
FoundryEnCompendium foundryEnCompendium FoundryEnCompendium foundryEnCompendium,
ApplicationSettings settings
) )
{ {
public IServiceProvider ServiceProvider { get; } = serviceProvider; public IServiceProvider ServiceProvider { get; } = serviceProvider;
public ProcessorCollection Collection { get; } = collection; public ProcessorCollection Collection { get; } = collection;
public ProcessProgress Progress { get; } = progress; public ProcessProgress Progress { get; } = progress;
public Pf2eDbContext Context { get; } = context;
public AonprdCompendium AonprdCompendium { get; } = aonprdCompendium; public AonprdCompendium AonprdCompendium { get; } = aonprdCompendium;
public FoundryEnCompendium FoundryEnCompendium { get; } = foundryEnCompendium; public FoundryEnCompendium FoundryEnCompendium { get; } = foundryEnCompendium;
public ApplicationSettings Settings { get; } = settings;
public void Start() public void Start()
{ {
@@ -48,7 +50,19 @@ internal sealed class ProcessorExecutor(
worker.DoWork += (_, _) => worker.DoWork += (_, _) =>
{ {
foreach (IProcessor processor in IterateProcessors(item)) Parallel.ForEach(
IterateProcessors(item),
new() { MaxDegreeOfParallelism = item.Parallel ? Settings.MaxThreads : 1 },
RunProcessor
);
};
worker.RunWorkerCompleted += (_, _) => Continue();
worker.RunWorkerAsync();
}
private void RunProcessor(IProcessor processor, ParallelLoopState state, long arg3)
{ {
try try
{ {
@@ -64,15 +78,8 @@ internal sealed class ProcessorExecutor(
// //
} }
} }
Context.SaveChanges();
};
worker.RunWorkerCompleted += Continue; private void Continue()
worker.RunWorkerAsync();
}
private void Continue(object? sender, RunWorkerCompletedEventArgs e)
{ {
Progress.Processors.End(); Progress.Processors.End();
_currentIndex++; _currentIndex++;
+2 -2
View File
@@ -69,7 +69,7 @@ public static class EfCleanHelper
public static string Truncate<T>(this DbSet<T> dbSet) public static string Truncate<T>(this DbSet<T> dbSet)
where T : class where T : class
{ {
string cmd = $"TRUNCATE TABLE {TableName(dbSet)} CASCADE;"; string cmd = $"TRUNCATE TABLE {TableName(dbSet)} RESTART IDENTITY CASCADE;";
DbContext context = dbSet.GetService<ICurrentDbContext>().Context; DbContext context = dbSet.GetService<ICurrentDbContext>().Context;
context.Database.ExecuteSqlRaw(cmd); context.Database.ExecuteSqlRaw(cmd);
return cmd; return cmd;
@@ -87,7 +87,7 @@ public static class EfCleanHelper
foreach (IEntityType entityType in tables) foreach (IEntityType entityType in tables)
{ {
string cmd = $"TRUNCATE TABLE {GetName(entityType)} CASCADE;"; string cmd = $"TRUNCATE TABLE {GetName(entityType)} RESTART IDENTITY CASCADE;";
context.Database.ExecuteSqlRaw(cmd); context.Database.ExecuteSqlRaw(cmd);
cmdList.Add(cmd); cmdList.Add(cmd);
} }
@@ -13,7 +13,7 @@ using Pf2eModel.Model.Enum;
namespace Pf2eModel.Migrations namespace Pf2eModel.Migrations
{ {
[DbContext(typeof(Pf2eDbContext))] [DbContext(typeof(Pf2eDbContext))]
[Migration("20250514102154_1")] [Migration("20250514120355_1")]
partial class _1 partial class _1
{ {
/// <inheritdoc /> /// <inheritdoc />
+1 -1
View File
@@ -104,5 +104,5 @@ public class Entity
/// <summary> /// <summary>
/// Коллекция устаревших сущностей. /// Коллекция устаревших сущностей.
/// </summary> /// </summary>
public IEnumerable<LegacyEntity> LegacyEntities { get; set; } = []; public ICollection<LegacyEntity> LegacyEntities { get; set; } = [];
} }
+1
View File
@@ -136,6 +136,7 @@ public partial class Pf2eDbContext : DbContext
// optionsBuilder.LogTo(Console.WriteLine); // optionsBuilder.LogTo(Console.WriteLine);
optionsBuilder.UseSnakeCaseNamingConvention(); optionsBuilder.UseSnakeCaseNamingConvention();
optionsBuilder.EnableSensitiveDataLogging(); optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder.UseNpgsql( optionsBuilder.UseNpgsql(
databaseConnection, databaseConnection,