179 lines
7.2 KiB
C#
179 lines
7.2 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Pf2e.Database;
|
|
using Pf2e.Database.Model;
|
|
using Pf2e.Database.Model.Base;
|
|
using Pf2e.Database.Model.Enum;
|
|
using Pf2e.Database.Model.Structure;
|
|
|
|
namespace Pf2e.Common;
|
|
|
|
/// <summary>
|
|
/// Класс, обрабатывающий запросы к сущностям и подключающий необходимые данные.
|
|
/// </summary>
|
|
public class FullEntity
|
|
{
|
|
/// <summary>
|
|
/// Корневая сущность.
|
|
/// </summary>
|
|
public Entity Entity { get; }
|
|
|
|
/// <summary>
|
|
/// Основная сущность.
|
|
/// </summary>
|
|
public IEntity? SubEntity { get; }
|
|
|
|
/// <summary>
|
|
/// Контекст базы данных, используемый для получения сущностей.
|
|
/// </summary>
|
|
private Pf2eDbContext Context { get; }
|
|
|
|
/// <summary>
|
|
/// Конструктор класса, который получает сущность из базы данных по типу и идентификатору и заполняет её данными.
|
|
/// </summary>
|
|
/// <param name="context">Контекст базы данных.</param>
|
|
/// <param name="type">Тип запрашиваемой сущности.</param>
|
|
/// <param name="id">Идентификатор запрашиваемой сущности.</param>
|
|
public FullEntity(Pf2eDbContext context, EntityType type, int id)
|
|
{
|
|
Context = context;
|
|
Entity = GetEntity(type, id);
|
|
SubEntity = GetSubEntity(type, id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Конструктор класса, который получает сущность из базы данных по переданной сущности и заполняет её данными.
|
|
/// </summary>
|
|
/// <param name="context">Контекст базы данных.</param>
|
|
/// <param name="entity">Сущность, которую нужно обработать.</param>
|
|
public FullEntity(Pf2eDbContext context, Entity entity)
|
|
{
|
|
Context = context;
|
|
Entity = entity;
|
|
SubEntity = GetSubEntity(entity.Type, entity.Id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Получает сущность из базы данных по типу и идентификатору.
|
|
/// </summary>
|
|
/// <param name="type">Тип сущности.</param>
|
|
/// <param name="id">Идентификатор сущности.</param>
|
|
/// <returns>Сущность, соответствующая указанному типу и идентификатору.</returns>
|
|
private Entity GetEntity(EntityType type, int id) =>
|
|
Context
|
|
.Entities.Where(e => e.Id == id && e.Type == type)
|
|
.Include(e => e.Sources)
|
|
.ThenInclude(s => s.Source)
|
|
.Include(e => e.Keywords)
|
|
.Include(e => e.Externals)
|
|
.ThenInclude(x => x.Target)
|
|
.Include(e => e.Traits)
|
|
.ThenInclude(t => t.Entity)
|
|
.FirstOrDefault() ?? throw new("Entity is null");
|
|
|
|
/// <summary>
|
|
/// Получает подчинённую сущность по типу и идентификатору.
|
|
/// </summary>
|
|
/// <param name="type">Тип сущности.</param>
|
|
/// <param name="id">Идентификатор сущности.</param>
|
|
/// <returns>Подчинённая сущность, соответствующая указанному типу и идентификатору.</returns>
|
|
private IEntity? GetSubEntity(EntityType type, int id)
|
|
{
|
|
Getter? getter = _getters.FirstOrDefault(g => g.Type == type);
|
|
return (getter != null)
|
|
? getter.Get(id, this.Context)
|
|
: (IEntity?)Context.Find(EntityOfTypeAttribute.Resolve(Entity), id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Словарь, содержащий методы получения сущностей из базы данных.
|
|
/// </summary>
|
|
private readonly ICollection<Getter> _getters =
|
|
[
|
|
new Getter<Ancestry>(
|
|
EntityType.Ancestry,
|
|
context => context.Ancestries.Include(a => a.AncestryBoosts)
|
|
),
|
|
new Getter<Archetype>(
|
|
EntityType.Archetype,
|
|
context =>
|
|
context
|
|
.Archetypes.Include(a => a.DedicationFeat)
|
|
.ThenInclude(f => f.Entity)
|
|
.Include(a => a.Feats)
|
|
.ThenInclude(f => f.Entity)
|
|
),
|
|
new Getter<Background>(
|
|
EntityType.Background,
|
|
context =>
|
|
context
|
|
.Backgrounds.Include(b => b.BackgroundBoosts)
|
|
.Include(b => b.BackgroundSkills)
|
|
.ThenInclude(t => t.Training)
|
|
.Include(b => b.BackgroundItems)
|
|
),
|
|
new Getter<Class>(
|
|
EntityType.Class,
|
|
context =>
|
|
context
|
|
.Classes.Include(c => c.ClassKeyAbilities)
|
|
.Include(c => c.ClassTrainings)
|
|
.ThenInclude(t => t.Training)
|
|
.Include(c => c.ClassProgressions)
|
|
.Include(c => c.SubclassGroups)
|
|
),
|
|
new Getter<Feat>(
|
|
EntityType.Feat,
|
|
context =>
|
|
context.Feats.Include(f => f.Archetypes).ThenInclude(a => a.Entity).AsQueryable()
|
|
),
|
|
new Getter<Spell>(
|
|
EntityType.Spell,
|
|
context => context.Spells.Include(s => s.SpellAreas).Include(s => s.SpellDefenses)
|
|
),
|
|
new Getter<Ritual>(
|
|
EntityType.Ritual,
|
|
context =>
|
|
context
|
|
.Rituals.Include(r => r.Area)
|
|
.Include(r => r.Checks)
|
|
.ThenInclude(c => c.Training)
|
|
.AsQueryable()
|
|
),
|
|
new Getter<Subclass>(
|
|
EntityType.Subclass,
|
|
context =>
|
|
context
|
|
.Subclasses.Include(s => s.Trainings)
|
|
.ThenInclude(t => t.Training)
|
|
.Include(s => s.Entities)
|
|
),
|
|
];
|
|
|
|
/// <summary>
|
|
/// Абстрактный класс, который определяет метод получения сущности из базы данных.
|
|
/// </summary>
|
|
/// <param name="type">Связанный тип сущности.</param>
|
|
private abstract class Getter(EntityType type)
|
|
{
|
|
public readonly EntityType Type = type;
|
|
|
|
public abstract IEntity? Get(int id, Pf2eDbContext context);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Класс, определяющий метод получения сущности из базы данных.
|
|
/// </summary>
|
|
/// <typeparam name="T">Тип данных основной сущности.</typeparam>
|
|
/// <param name="type">Связанный тип сущности.</param>
|
|
/// <param name="method">Метод получения сущности из базы данных.</param>
|
|
private class Getter<T>(EntityType type, Func<Pf2eDbContext, IQueryable<T>> method)
|
|
: Getter(type)
|
|
where T : IEntity
|
|
{
|
|
public override IEntity? Get(int id, Pf2eDbContext context)
|
|
{
|
|
return method.Invoke(context).FirstOrDefault(c => c.Id == id);
|
|
}
|
|
}
|
|
}
|