131 lines
4.4 KiB
C#
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);
|
|
}
|