using DatabaseCore.Models; using Microsoft.EntityFrameworkCore; using ModuleTools.BindingModels; using ModuleTools.BusinessLogics; using ModuleTools.Enums; using ModuleTools.Interfaces; using ModuleTools.Models; using ModuleTools.ViewModels; using System; using System.Linq; using System.Threading.Tasks; namespace DatabaseCore { public abstract class AbstractGenerticEntityService : IGenerticEntityService where G : GetBindingModel where S : SetBindingModel where T : BaseEntity where L : ListViewModel, new() where E : ElementViewModel { public async Task CreateAsync(S model) { using var context = DatabaseManager.GetContext; var result = AdditionalCheckingWhenAdding(context, model); if (!result.IsSucceeded) { return result; } var exsistEntity = GetUniqueEntity(model, context); if (exsistEntity == null) { var entity = Mapper.MapToClass(model, true); await context.Set().AddAsync(entity); await context.SaveChangesAsync(); return OperationResultModel.Success(Mapper.MapToClass(entity, true)); } else { if (exsistEntity.IsDeleted) { exsistEntity = Mapper.MapToClass(model, exsistEntity, true); exsistEntity.IsDeleted = false; await context.SaveChangesAsync(); return OperationResultModel.Success(Mapper.MapToClass(exsistEntity, true)); } else { return OperationResultModel.Error("Error:", "Элемент уже существует", ResultServiceStatusCode.ExsistItem); } } } public async Task DeleteAsync(G model) { using var context = DatabaseManager.GetContext; using var transaction = context.Database.BeginTransaction(); try { var entity = await context.Set().FirstOrDefaultAsync(x => x.Id == model.Id); if (entity == null) { return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); } else if (entity.IsDeleted) { return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); } var result = AdditionalCheckingWhenDeleting(context, entity, model); if (!result.IsSucceeded) { return result; } entity.IsDeleted = true; entity.DateDelete = DateTime.Now; await context.SaveChangesAsync(); AdditionalDeleting(context, entity, model); await transaction.CommitAsync(); } catch (Exception) { await transaction.RollbackAsync(); throw; } return OperationResultModel.Success(true); } public async Task RestoreAsync(G model) { if (model.Id.HasValue || AdditionalCheckForSingleGet(model)) { using var context = DatabaseManager.GetContext; var entity = model.Id.HasValue ? IncludingWhenReading(context.Set().AsQueryable()).FirstOrDefault(x => x.Id == model.Id.Value) : GetSingleRecord(context.Set().AsQueryable(), model); if (entity == null) { return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); } else if (!entity.IsDeleted) { return OperationResultModel.Error("Error:", "Элемент не был удален", ResultServiceStatusCode.ExsistItem); } entity.IsDeleted = false; await context.SaveChangesAsync(); return OperationResultModel.Success(Mapper.MapToClass(entity, true)); } return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); } public async Task ReadAsync(G model) { int countPages = 0; using var context = DatabaseManager.GetContext; // для одной записи if (model.Id.HasValue || AdditionalCheckForSingleGet(model)) { var entity = model.Id.HasValue ? IncludingWhenReading(context.Set().AsQueryable()).FirstOrDefault(x => x.Id == model.Id.Value) : GetSingleRecord(context.Set().AsQueryable(), model); if (entity == null) { return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); } if (entity.IsDeleted) { return OperationResultModel.Error("Error:", "Элемент удален", ResultServiceStatusCode.WasDelete); } return OperationResultModel.Success(Mapper.MapToClass(entity, model.HaveRight)); } var query = context.Set().Where(x => !x.IsDeleted).AsQueryable(); query = AdditionalCheckingWhenReadingList(query, model); query = OrderingWhenReading(query); query = IncludingWhenReading(query); return await Task.Run(() => { if (model.PageNumber.HasValue && model.PageSize.HasValue) { countPages = (int)Math.Ceiling((double)query.Count() / model.PageSize.Value); query = query .Skip(model.PageSize.Value * model.PageNumber.Value) .Take(model.PageSize.Value); } var result = new L { MaxCount = countPages, List = query.Select(x => Mapper.MapToClass(x, model.HaveRight)).ToList() }; return OperationResultModel.Success(result); }); } public async Task UpdateAsync(S model) { using var context = DatabaseManager.GetContext; var result = AdditionalCheckingWhenUpdateing(context, model); if (!result.IsSucceeded) { return result; } var exsistEntity = GetUniqueEntity(model, context); if (exsistEntity != null) { return OperationResultModel.Error("Error:", "Существует запись с такими значениями", ResultServiceStatusCode.ExsistItem); } var entity = context.Set().FirstOrDefault(x => x.Id == model.Id); if (entity == null) { return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); } else if (entity.IsDeleted) { return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); } entity = Mapper.MapToClass(model, entity, true); await context.SaveChangesAsync(); return OperationResultModel.Success(Mapper.MapToClass(entity, true)); } /// /// Поиск записи с уникальными значениями /// /// /// protected abstract T GetUniqueEntity(S model, DbContext context); /// /// Возможные дополнительные проверки при добавлении /// /// /// /// protected abstract OperationResultModel AdditionalCheckingWhenAdding(DbContext context, S model); /// /// Возможные дополнительные проверки при удалении /// /// /// /// protected abstract OperationResultModel AdditionalCheckingWhenDeleting(DbContext context, T entity, G model); /// /// Добавление дополнительных фильтров /// /// /// /// protected abstract IQueryable AdditionalCheckingWhenReadingList(IQueryable query, G model); /// /// Возможные дополнительные проверки модели при изменении /// /// protected abstract OperationResultModel AdditionalCheckingWhenUpdateing(DbContext context, S model); /// /// Дополнительные удаления зависимых сущностей /// /// protected abstract void AdditionalDeleting(DbContext context, T entity, G model); /// /// Установка сортировок /// /// /// protected abstract IQueryable OrderingWhenReading(IQueryable query); /// /// Добавление Include /// /// /// protected abstract IQueryable IncludingWhenReading(IQueryable query); protected virtual bool AdditionalCheckForSingleGet(G model) => false; protected virtual T GetSingleRecord(IQueryable list, G model) => null; } }