Files
Pf2eDataScrapper/Pf2eViewer/DatabaseViewer/DatabaseQueryPerformer.cs
T

131 lines
4.4 KiB
C#

using System.Collections.Concurrent;
using Pf2eModel;
using Pf2eModel.Model.Base;
using Pf2eModel.Model.Enum;
namespace Pf2eViewer.DatabaseViewer;
/// <summary>
/// Класс, выполняющий страничные запросы к базе данных.
/// </summary>
internal class DatabaseQueryPerformer
{
/// <summary>
/// Тип сущностей, которую необходимо получить.
/// </summary>
public required EntityType Type;
/// <summary>
/// Номер страницы, которую необходимо получить.
/// </summary>
public required int Page;
/// <summary>
/// Количество элементов на странице.
/// </summary>
public required int PerPage;
/// <summary>
/// Поисковая строка, по которой будет производиться фильтрация.
/// </summary>
public required string Search = "";
/// <summary>
/// Поток, в котором будет выполняться запрос к базе данных.
/// </summary>
private readonly Thread _queryThread;
/// <summary>
/// Конструктор класса, который инициализирует поток для выполнения запроса к базе данных.
/// </summary>
public DatabaseQueryPerformer()
{
_queryThread = new(PerformQuery);
}
/// <summary>
/// Запускает поток для выполнения запроса к базе данных.
/// </summary>
public void Query()
{
_queryThread.Start();
}
/// <summary>
/// Прерывает выполнение потока, если он ещё не завершён.
/// </summary>
public void Abort()
{
_queryThread.Interrupt();
}
/// <summary>
/// Выполняет запрос к базе данных и обрабатывает результаты.
/// </summary>
private void PerformQuery()
{
try
{
Pf2eDbContext dbContext = new();
IQueryable<Entity> 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<Entity> 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
}
}
/// <summary>
/// Делегат, который будет вызван по завершении выполнения запроса к базе данных.
/// </summary>
/// <param name="sender">Объект класса, выполневшего запрос.</param>
/// <param name="result">Результат запроса.</param>
public delegate void DatabaseQueryPerformerDelegate(
DatabaseQueryPerformer sender,
DatabaseQueryResult result
);
/// <summary>
/// Событие, которое будет вызвано по завершении выполнения запроса к базе данных.
/// </summary>
public event DatabaseQueryPerformerDelegate? OnQueryCompleted;
}
/// <summary>
/// Класс, который содержит результат выполнения запроса к базе данных.
/// </summary>
/// <param name="count">Общее количество найденных сущностей.</param>
/// <param name="entities">Набор найденных сущностей.</param>
internal class DatabaseQueryResult(int count, ICollection<Entity> entities)
{
/// <summary>
/// Общее количество найденных сущностей.
/// </summary>
public int Count { get; } = count;
/// <summary>
/// Набор найденных сущностей.
/// </summary>
public ConcurrentBag<Entity> Entities { get; } = new(entities);
}