2023-05-17 16:30:13 +10:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2024-10-07 15:08:46 +10:00
|
|
|
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
2026-04-22 16:13:23 +10:00
|
|
|
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
2023-05-17 16:30:13 +10:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
2026-04-14 09:56:31 +10:00
|
|
|
|
using PARR.Core.Repositories.Base;
|
2023-05-17 16:30:13 +10:00
|
|
|
|
using PARR.DAL.Context;
|
2026-04-14 09:56:31 +10:00
|
|
|
|
using PARR.Domain.Common.Pagination;
|
2026-04-22 16:13:23 +10:00
|
|
|
|
using PARR.Domain.Entities.Attributes;
|
2026-04-13 16:58:30 +10:00
|
|
|
|
using PARR.Domain.Entities.Base;
|
|
|
|
|
|
using PARR.Domain.Entities.Base.History;
|
|
|
|
|
|
using PARR.Domain.Entities.Base.History.Base;
|
2024-10-07 15:08:46 +10:00
|
|
|
|
using System.Reflection;
|
2023-05-17 16:30:13 +10:00
|
|
|
|
|
2026-04-14 09:56:31 +10:00
|
|
|
|
namespace PARR.DAL.Repositories.Base
|
2023-05-17 16:30:13 +10:00
|
|
|
|
{
|
2026-04-14 09:56:31 +10:00
|
|
|
|
internal abstract class BaseRepository<T> : IBaseRepository<T> where T : class, IBaseEntity
|
2023-05-17 16:30:13 +10:00
|
|
|
|
{
|
2026-04-14 09:56:31 +10:00
|
|
|
|
//private readonly ILogger<BaseRepository<T>> logger;
|
2023-05-17 16:30:13 +10:00
|
|
|
|
|
2026-04-14 09:56:31 +10:00
|
|
|
|
//protected abstract DbSet<T> EntitySet { get; }
|
|
|
|
|
|
//protected abstract DataContext EntitiContext { get; }
|
2023-05-17 16:30:13 +10:00
|
|
|
|
|
2026-04-14 09:56:31 +10:00
|
|
|
|
//public BaseRepository(ILogger<BaseRepository<T>> logger)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// this.logger = logger;
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
protected readonly ILogger logger;
|
|
|
|
|
|
protected readonly DbSet<T> EntitySet;
|
|
|
|
|
|
protected readonly DataContext EntityContext;
|
|
|
|
|
|
|
|
|
|
|
|
protected BaseRepository(ILogger logger, DataContext dataContext)
|
2023-05-17 16:30:13 +10:00
|
|
|
|
{
|
|
|
|
|
|
this.logger = logger;
|
2026-04-14 09:56:31 +10:00
|
|
|
|
this.EntityContext = dataContext;
|
|
|
|
|
|
this.EntitySet = dataContext.Set<T>();
|
2023-05-17 16:30:13 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-14 09:56:31 +10:00
|
|
|
|
|
2023-05-17 16:30:13 +10:00
|
|
|
|
public virtual async Task<bool> AddRangeAsync(List<T> objs)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Начинаю добавление диапазона объектов типа {EntityType}, количество: {Count}",
|
|
|
|
|
|
typeof(T).Name, objs.Count);
|
|
|
|
|
|
|
2023-05-17 16:30:13 +10:00
|
|
|
|
objs.ForEach(item => item.DateCreated = DateTimeOffset.UtcNow);
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
await EntitySet.AddRangeAsync(objs);
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Успешно добавлено {Count} объектов типа {EntityType}",
|
|
|
|
|
|
objs.Count, typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError(ex, "Ошибка при добавлении диапазона объектов типа {EntityType}", typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-08 10:29:34 +10:00
|
|
|
|
public async Task<bool> CommitAsync(IHistoryInitiator? initiator = null)
|
2023-05-17 16:30:13 +10:00
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Начинаю сохранение изменений в БД для объектов типа {EntityType}", typeof(T).Name);
|
|
|
|
|
|
|
2024-10-07 17:00:56 +10:00
|
|
|
|
#region Изменения
|
2026-04-14 09:56:31 +10:00
|
|
|
|
var modifiedEntrities = EntityContext.ChangeTracker.Entries()
|
2024-10-07 15:08:46 +10:00
|
|
|
|
.Where(t => t.State == EntityState.Modified/* || t.State == EntityState.Deleted*/);
|
2024-10-03 16:38:21 +10:00
|
|
|
|
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Найдено {Count} измененных сущностей для обработки истории", modifiedEntrities.Count());
|
|
|
|
|
|
|
2024-10-07 15:08:46 +10:00
|
|
|
|
foreach (var obj in modifiedEntrities)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
// Если нужно, обновляем дату изменения
|
2024-10-07 15:08:46 +10:00
|
|
|
|
DateModifiedResolver(obj);
|
2024-10-03 16:38:21 +10:00
|
|
|
|
|
2024-10-07 15:08:46 +10:00
|
|
|
|
//Если нужно, пишем историю
|
|
|
|
|
|
TableHistoryResolver(obj);
|
|
|
|
|
|
}
|
2024-10-07 17:00:56 +10:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-10-08 09:40:08 +10:00
|
|
|
|
SetInitiator(initiator);
|
2024-10-03 16:38:21 +10:00
|
|
|
|
|
2023-05-17 16:30:13 +10:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2026-04-14 09:56:31 +10:00
|
|
|
|
var changedCount = await EntityContext.SaveChangesAsync();
|
2026-02-27 09:33:27 +10:00
|
|
|
|
logger.LogDebug("Успешно сохранено {ChangedCount} изменений в БД для объектов типа {EntityType}",
|
2026-02-09 12:00:46 +10:00
|
|
|
|
changedCount, typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError(ex, "Ошибка при сохранении изменений в БД для объектов типа {EntityType}", typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-07 17:00:56 +10:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Установить инициатора
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="initiator"></param>
|
2024-10-08 09:40:08 +10:00
|
|
|
|
private void SetInitiator(IHistoryInitiator? initiator)
|
2024-10-07 17:00:56 +10:00
|
|
|
|
{
|
2026-04-15 16:48:23 +10:00
|
|
|
|
if (initiator == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Устанавливаю инициатора для изменений");
|
|
|
|
|
|
|
2024-10-21 11:58:01 +10:00
|
|
|
|
// Задаем инициатора только для новых и измененных записей
|
2026-04-14 09:56:31 +10:00
|
|
|
|
var entrities = EntityContext.ChangeTracker.Entries()
|
2024-10-07 17:00:56 +10:00
|
|
|
|
.Where(t => t.State == EntityState.Modified || t.State == EntityState.Added);
|
|
|
|
|
|
|
2026-02-09 12:00:46 +10:00
|
|
|
|
var entityCount = entrities.Count();
|
|
|
|
|
|
logger.LogDebug("Найдено {Count} сущностей для установки инициатора", entityCount);
|
|
|
|
|
|
|
2024-10-07 17:00:56 +10:00
|
|
|
|
// смотрим есть ли у объекта интерфейс IHistoryInitiator, если есть, задаём значения
|
|
|
|
|
|
foreach (var obj in entrities)
|
|
|
|
|
|
{
|
|
|
|
|
|
// для всех объектов которые наследуются от IHistoryInitiator и не являются наследниками IHistoryTable
|
|
|
|
|
|
if (obj.Entity is IHistoryInitiator && obj.Entity is IHistoryTable == false)
|
|
|
|
|
|
{
|
2024-10-08 09:40:08 +10:00
|
|
|
|
(obj.Entity as IHistoryInitiator)!.InitiatorIp = initiator?.InitiatorIp ?? null;
|
|
|
|
|
|
(obj.Entity as IHistoryInitiator)!.InitiatorParrComponentId = initiator?.InitiatorParrComponentId ?? null;
|
|
|
|
|
|
(obj.Entity as IHistoryInitiator)!.InitiatorComment = initiator?.InitiatorComment ?? null;
|
2026-02-09 12:00:46 +10:00
|
|
|
|
|
|
|
|
|
|
logger.LogDebug("Установлен инициатор для сущности типа {EntityType}", obj.Entity.GetType().Name);
|
2024-10-07 17:00:56 +10:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-10-07 15:08:46 +10:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Обновления DateModified у таблиц с IBase
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
|
private void DateModifiedResolver(EntityEntry obj)
|
|
|
|
|
|
{
|
2026-04-22 16:13:23 +10:00
|
|
|
|
if (obj.Entity is IBaseEntityDateModified entity)
|
2026-02-09 12:00:46 +10:00
|
|
|
|
{
|
2026-04-22 16:13:23 +10:00
|
|
|
|
//logger.LogDebug("Обновляю DateModified для сущности типа {EntityType}", obj.Entity.GetType().Name);
|
|
|
|
|
|
//(obj.Entity as IBaseEntityDateModified)!.DateModified = DateTimeOffset.UtcNow;
|
|
|
|
|
|
|
|
|
|
|
|
var entityType = entity.GetType();
|
|
|
|
|
|
|
|
|
|
|
|
//Ищем DateModified
|
|
|
|
|
|
var properyInfo = entityType.GetProperty(nameof(IBaseEntityDateModified.DateModified));
|
|
|
|
|
|
|
|
|
|
|
|
// Проверяем наличие атрибута ManualControlAttribute на этом свойстве
|
|
|
|
|
|
bool isManual = properyInfo?.GetCustomAttributes(typeof(ManualControlAttribute), false).Any() ?? false;
|
|
|
|
|
|
|
|
|
|
|
|
if (!isManual)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogDebug("Обновляю DateModified для сущности типа {EntityType}", obj.Entity.GetType().Name);
|
|
|
|
|
|
entity.DateModified = DateTimeOffset.UtcNow;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogDebug("Пропуск обновления DateModified (ManualControl) для {EntityType}", entityType.Name);
|
|
|
|
|
|
}
|
2026-02-09 12:00:46 +10:00
|
|
|
|
}
|
2024-10-07 15:08:46 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// При необходимости, записывать историю таблиц
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj"></param>
|
|
|
|
|
|
private void TableHistoryResolver(EntityEntry obj)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Проверяю необходимость создания истории для сущности типа {EntityType}", obj.Entity.GetType().Name);
|
|
|
|
|
|
|
2024-10-07 15:08:46 +10:00
|
|
|
|
var myHistoryInterface = obj.Entity.GetType().GetInterfaces()
|
|
|
|
|
|
.Where(t => t.IsGenericType)
|
|
|
|
|
|
.Where(t => t.GetGenericTypeDefinition() == typeof(IMyHistory<>))
|
|
|
|
|
|
.FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
|
|
// у этого объекта нет интерфейса IMyHistory<>. Не ведем историю
|
|
|
|
|
|
if (myHistoryInterface == null)
|
2026-02-09 12:00:46 +10:00
|
|
|
|
{
|
|
|
|
|
|
logger.LogDebug("Сущность типа {EntityType} не требует ведения истории", obj.Entity.GetType().Name);
|
2024-10-07 15:08:46 +10:00
|
|
|
|
return;
|
2026-02-09 12:00:46 +10:00
|
|
|
|
}
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
|
|
|
|
|
// !!! Эта таблица хочет хранить историю !!!
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем тип таблицы где хранится история
|
|
|
|
|
|
var historyType = myHistoryInterface.GetGenericArguments().First();
|
|
|
|
|
|
var historyProps = historyType.GetProperties(/*BindingFlags.DeclaredOnly | */ /*BindingFlags.Public*/).ToList();
|
|
|
|
|
|
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Создаю историю для сущности типа {EntityType}, тип истории: {HistoryType}",
|
|
|
|
|
|
obj.Entity.GetType().Name, historyType.Name);
|
|
|
|
|
|
|
2024-10-07 15:08:46 +10:00
|
|
|
|
var historyInstance = Activator.CreateInstance(historyType);
|
|
|
|
|
|
if (historyInstance == null)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError("Не смог создать инстанс для ведения истории {HistoryType}", historyType.Name);
|
2024-10-07 15:08:46 +10:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Заполняем поля истории, полями которые есть в исходной таблице
|
|
|
|
|
|
FillHistoryProps(obj, ref historyInstance, historyProps);
|
|
|
|
|
|
|
|
|
|
|
|
// Заполняем поля интерфейса IHistoryTable
|
2024-10-07 16:20:04 +10:00
|
|
|
|
FillHistoryProp(ref historyInstance, nameof(IHistoryTable.DateAddedToHistory), DateTimeOffset.UtcNow);
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
|
|
|
|
|
// Заполняем Id
|
2026-04-13 16:58:30 +10:00
|
|
|
|
FillHistoryProp(ref historyInstance, nameof(IBaseEntity.Id), Guid.NewGuid());
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
2024-10-07 16:20:04 +10:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2026-04-14 09:56:31 +10:00
|
|
|
|
EntityContext.Add(historyInstance);
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("История добавлена для сущности типа {EntityType}", obj.Entity.GetType().Name);
|
2024-10-07 16:20:04 +10:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError(ex, "Ошибка при добавлении объекта в историю {HistoryType}", historyType.Name);
|
2024-10-07 16:20:04 +10:00
|
|
|
|
}
|
2024-10-07 15:08:46 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Заполнить объект истории
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="originalObj"></param>
|
|
|
|
|
|
/// <param name="historyInstance"></param>
|
|
|
|
|
|
/// <param name="propsList"></param>
|
|
|
|
|
|
private void FillHistoryProps(EntityEntry originalObj, ref object historyInstance, List<PropertyInfo> propsList)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Заполняю историю для сущности типа {EntityType}", originalObj.Entity.GetType().Name);
|
|
|
|
|
|
|
2024-10-07 15:08:46 +10:00
|
|
|
|
foreach (var prop in propsList)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (originalObj.OriginalValues.Properties.FirstOrDefault(t => t.Name == prop.Name) == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
var sourceObjProp = originalObj.Property(prop.Name);
|
|
|
|
|
|
if (sourceObjProp == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
//Смотрим, если это Id, записываем его в ParentId
|
2026-04-13 16:58:30 +10:00
|
|
|
|
var histPropName = prop.Name == nameof(IBaseEntity.Id) ? nameof(IHistoryTable.ParentId) : prop.Name;
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
|
|
|
|
|
var histProp = historyInstance.GetType().GetProperty(histPropName);
|
|
|
|
|
|
if (histProp == null) continue;
|
|
|
|
|
|
|
|
|
|
|
|
//сравним типы
|
|
|
|
|
|
if (sourceObjProp.Metadata.PropertyInfo?.PropertyType != histProp.PropertyType)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
var origValues = originalObj.Property(prop.Name).OriginalValue;
|
|
|
|
|
|
histProp.SetValue(historyInstance, origValues);
|
|
|
|
|
|
}
|
2026-02-09 12:00:46 +10:00
|
|
|
|
|
|
|
|
|
|
logger.LogDebug("Завершено заполнение истории для сущности типа {EntityType}", originalObj.Entity.GetType().Name);
|
2024-10-07 15:08:46 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-10-07 16:20:04 +10:00
|
|
|
|
/// <summary>
|
2024-10-07 17:00:56 +10:00
|
|
|
|
/// Заполнить поле объекта
|
2024-10-07 16:20:04 +10:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
2024-10-07 17:00:56 +10:00
|
|
|
|
/// <param name="instanceObj"></param>
|
2024-10-07 16:20:04 +10:00
|
|
|
|
/// <param name="propName"></param>
|
|
|
|
|
|
/// <param name="value"></param>
|
2024-10-08 09:40:08 +10:00
|
|
|
|
private void FillHistoryProp<TValue>(ref object instanceObj, string propName, TValue value)
|
2024-10-07 16:20:04 +10:00
|
|
|
|
{
|
2024-10-07 17:00:56 +10:00
|
|
|
|
var histProp = instanceObj.GetType().GetProperty(propName);
|
2024-10-07 16:20:04 +10:00
|
|
|
|
if (histProp == null)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError("При изменении объекта для БД, не найдено свойство {PropertyName}", propName);
|
2024-10-07 16:20:04 +10:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
2024-10-07 16:20:04 +10:00
|
|
|
|
// сравним типы
|
2024-10-08 09:40:08 +10:00
|
|
|
|
if (histProp.PropertyType != typeof(TValue))
|
2024-10-07 16:20:04 +10:00
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError("При изменении объекта для БД, не совпадают типы у свойства {PropertyName}, {PropertyType}!={ValueType}",
|
|
|
|
|
|
propName, histProp.PropertyType.Name, typeof(TValue).Name);
|
2024-10-07 16:20:04 +10:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
2024-10-07 17:00:56 +10:00
|
|
|
|
histProp.SetValue(instanceObj, value);
|
2024-10-07 16:20:04 +10:00
|
|
|
|
}
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-07 16:20:04 +10:00
|
|
|
|
#region test, comments
|
2024-10-07 15:08:46 +10:00
|
|
|
|
//private void SaveHistory(EntityEntry obj)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // пока просто попробуем для шаблонов
|
|
|
|
|
|
// if (obj.Entity is Template == false)
|
|
|
|
|
|
// return;
|
|
|
|
|
|
|
|
|
|
|
|
// var template = (Template)obj.Entity;
|
2026-02-09 12:00:46 +10:00
|
|
|
|
// // https://stackoverflow.com/questions/15012621/how-to-get-original-entity-from-changetracker
|
2024-10-07 15:08:46 +10:00
|
|
|
|
// var history = new TemplateHistory();
|
|
|
|
|
|
// // {
|
|
|
|
|
|
// history.Id = Guid.NewGuid();
|
|
|
|
|
|
// history.ParentId = template.Id;
|
|
|
|
|
|
// history.DateAddedToHistory = DateTimeOffset.UtcNow;
|
|
|
|
|
|
// history.InitiatorIp = null;
|
|
|
|
|
|
// history.InitiatorParrComponentId = null;
|
|
|
|
|
|
// history.InitiatorComment = null;
|
|
|
|
|
|
// //---
|
|
|
|
|
|
// //DateModified="",
|
|
|
|
|
|
// //Name ="",
|
|
|
|
|
|
// //IsActiveTemplate = null,
|
|
|
|
|
|
// //IsActiveSchedule = null,
|
|
|
|
|
|
// //LastRun = null,
|
|
|
|
|
|
// //NextRun = null
|
|
|
|
|
|
|
|
|
|
|
|
// // DateModified = template.DateModified,
|
|
|
|
|
|
// // Name = template.Name,
|
|
|
|
|
|
// // IsActiveTemplate = template.IsActiveTemplate,
|
|
|
|
|
|
// // IsActiveSchedule = template.IsActiveSchedule,
|
|
|
|
|
|
// // LastRun = template.LastRun,
|
|
|
|
|
|
// // NextRun = template.NextRun
|
|
|
|
|
|
// //};
|
|
|
|
|
|
|
|
|
|
|
|
// // obj.OriginalValues.GetValue
|
|
|
|
|
|
|
|
|
|
|
|
// //ITemplateBase хочу получить все поля из интерфейса, потом заполнить по ним в хистори
|
|
|
|
|
|
// var interfaceType = typeof(ITemplateGeneralProps);
|
|
|
|
|
|
// foreach (var prop in interfaceType.GetProperties())
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var propName = prop.Name;
|
|
|
|
|
|
// //var propType = prop.PropertyType;
|
|
|
|
|
|
|
|
|
|
|
|
// var originalPropValue = obj.OriginalValues.GetValue<object>(propName);
|
|
|
|
|
|
|
|
|
|
|
|
// var histProp = history.GetType().GetProperty(propName);
|
|
|
|
|
|
// histProp.SetValue(histProp, originalPropValue);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// EntitiContext.Add(history);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}
|
2024-10-07 16:20:04 +10:00
|
|
|
|
#endregion
|
2024-10-07 15:08:46 +10:00
|
|
|
|
|
|
|
|
|
|
|
2023-05-17 16:30:13 +10:00
|
|
|
|
public virtual async Task<bool> CreateAsync(T obj)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Начинаю создание объекта типа {EntityType}", typeof(T).Name);
|
|
|
|
|
|
|
2026-04-21 16:54:39 +10:00
|
|
|
|
if (obj.DateCreated == DateTimeOffset.MinValue)
|
|
|
|
|
|
obj.DateCreated = DateTimeOffset.UtcNow;
|
2023-05-17 16:30:13 +10:00
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
await EntitySet.AddAsync(obj);
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Объект типа {EntityType} добавлен в контекст", typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError(ex, "Ошибка при добавлении объекта типа {EntityType} в БД", typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual bool Delete(T obj)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Начинаю удаление объекта типа {EntityType}", obj.GetType().Name);
|
|
|
|
|
|
|
2023-05-17 16:30:13 +10:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
EntitySet.Remove(obj);
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Объект типа {EntityType} удален из контекста", obj.GetType().Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError(ex, "Ошибка при удалении объекта типа {EntityType} из БД", obj.GetType().Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual async Task<bool> DeleteAsync(Guid id)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Начинаю удаление объекта типа {EntityType} по ID: {Id}", typeof(T).Name, id);
|
|
|
|
|
|
|
2023-05-17 16:30:13 +10:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var exist = await GetAsync(id);
|
|
|
|
|
|
if (exist == null)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError("Ошибка при удалении из БД. Не найдена запись в БД типа {EntityType} с id: {Id}",
|
|
|
|
|
|
typeof(T).Name, id);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EntitySet.Remove(exist);
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Объект типа {EntityType} с ID {Id} удален из контекста", typeof(T).Name, id);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogError(ex, "Ошибка при удалении объекта типа {EntityType} из БД по ID: {Id}", typeof(T).Name, id);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual IQueryable<T> Get()
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Получаю набор объектов типа {EntityType}", typeof(T).Name);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return EntitySet;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public virtual async Task<T?> GetAsync(Guid id)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Получаю объект типа {EntityType} по ID: {Id}", typeof(T).Name, id);
|
2023-05-17 16:30:13 +10:00
|
|
|
|
return await EntitySet.FirstOrDefaultAsync(t => t.Id == id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-06-16 15:00:11 +10:00
|
|
|
|
public virtual IQueryable<T> GetPage(IQueryable<T> query, PaginationFilter paginationFilter)
|
|
|
|
|
|
{
|
2026-02-09 12:00:46 +10:00
|
|
|
|
logger.LogDebug("Получаю страницу объектов типа {EntityType}, страница: {PageNumber}, размер: {PageSize}",
|
|
|
|
|
|
typeof(T).Name, paginationFilter.PageNumber, paginationFilter.PageSize);
|
2024-03-12 15:09:12 +10:00
|
|
|
|
|
2023-06-16 15:00:11 +10:00
|
|
|
|
int skip = (paginationFilter.PageNumber - 1) * paginationFilter.PageSize;
|
2023-05-17 16:30:13 +10:00
|
|
|
|
|
2023-06-16 15:00:11 +10:00
|
|
|
|
return query.Skip(skip).Take(paginationFilter.PageSize);
|
|
|
|
|
|
}
|
2023-05-17 16:30:13 +10:00
|
|
|
|
}
|
2026-02-09 12:00:46 +10:00
|
|
|
|
}
|