using System.Collections.Concurrent; using Pf2eModel; using Pf2eModel.Model.Base; using Pf2eModel.Model.Enum; namespace Pf2eViewer.DatabaseViewer; /// /// Класс, выполняющий страничные запросы к базе данных. /// internal class DatabaseQueryPerformer { /// /// Тип сущностей, которую необходимо получить. /// public required EntityType Type; /// /// Номер страницы, которую необходимо получить. /// public required int Page; /// /// Количество элементов на странице. /// public required int PerPage; /// /// Поисковая строка, по которой будет производиться фильтрация. /// public required string Search = ""; /// /// Поток, в котором будет выполняться запрос к базе данных. /// private readonly Thread _queryThread; /// /// Конструктор класса, который инициализирует поток для выполнения запроса к базе данных. /// public DatabaseQueryPerformer() { _queryThread = new(PerformQuery); } /// /// Запускает поток для выполнения запроса к базе данных. /// public void Query() { _queryThread.Start(); } /// /// Прерывает выполнение потока, если он ещё не завершён. /// public void Abort() { _queryThread.Interrupt(); } /// /// Выполняет запрос к базе данных и обрабатывает результаты. /// private void PerformQuery() { try { Pf2eDbContext dbContext = new(); IQueryable query = Search == "" ? dbContext.Entities.Where(e => e.Type == Type) : // ReSharper disable once EntityFramework.UnsupportedServerSideFunctionCall dbContext.Entities.Where(e => e.Type == Type && Pf2eDbContext.LocaleSearch(e.Name, Search) ); int count = query.Count(); List entities = query .OrderBy(e => e.Id) .Skip((Page - 1) * PerPage) .Take(PerPage) .ToList(); DatabaseQueryResult result = new(count, entities); OnQueryCompleted?.Invoke(this, result); } catch (ThreadInterruptedException) { // Ignore } } /// /// Делегат, который будет вызван по завершении выполнения запроса к базе данных. /// /// Объект класса, выполневшего запрос. /// Результат запроса. public delegate void DatabaseQueryPerformerDelegate( DatabaseQueryPerformer sender, DatabaseQueryResult result ); /// /// Событие, которое будет вызвано по завершении выполнения запроса к базе данных. /// public event DatabaseQueryPerformerDelegate? OnQueryCompleted; } /// /// Класс, который содержит результат выполнения запроса к базе данных. /// /// Общее количество найденных сущностей. /// Набор найденных сущностей. internal class DatabaseQueryResult(int count, ICollection entities) { /// /// Общее количество найденных сущностей. /// public int Count { get; } = count; /// /// Набор найденных сущностей. /// public ConcurrentBag Entities { get; } = new(entities); }