using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.ChangeTracking; namespace AsbCloudInfrastructure.Repository { /// /// CRUD сервис для работы с БД /// /// /// public class CrudRepositoryBase : QueryContainer, ICrudRepository where TDto : AsbCloudApp.Data.IId where TEntity : class, IId { public CrudRepositoryBase(IAsbCloudDbContext context) : base(context) { } public CrudRepositoryBase(IAsbCloudDbContext context, Func, IQueryable> makeQuery) : base(context, makeQuery) { } /// public virtual async Task> GetAllAsync(CancellationToken token) { var entities = await GetQuery() .AsNoTracking() .ToListAsync(token) .ConfigureAwait(false); var dtos = entities.Select(Convert).ToList(); return dtos; } /// public virtual async Task GetOrDefaultAsync(int id, CancellationToken token) { var entity = await GetQuery() .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == id, token) .ConfigureAwait(false); if (entity == default) return default; var dto = Convert(entity); return dto; } /// public virtual TDto? GetOrDefault(int id) { var entity = GetQuery() .AsNoTracking() .FirstOrDefault(e => e.Id == id); if (entity == default) return default; var dto = Convert(entity); return dto; } /// public virtual async Task InsertAsync(TDto item, CancellationToken token) { var entity = Convert(item); entity.Id = 0; var entry = dbSet.Add(entity); await dbContext.SaveChangesAsync(token); entry.State = EntityState.Detached; return entity.Id; } /// public virtual async Task InsertRangeAsync(IEnumerable items, CancellationToken token) { if (!items.Any()) return 0; var entities = items.Select(i => { var entity = Convert(i); entity.Id = 0; return entity; }); var entries = new List(items.Count()); foreach (var entity in entities) { var entry = dbSet.Add(entity); entries.Add(entry); } var affected = await dbContext.SaveChangesAsync(token); entries.ForEach(e => e.State = EntityState.Detached); return affected; } /// public virtual async Task UpdateAsync(TDto item, CancellationToken token) { var existingEntity = await dbSet .AsNoTracking() .FirstOrDefaultAsync(e => e.Id == item.Id, token) .ConfigureAwait(false); if (existingEntity is null) return ICrudRepository.ErrorIdNotFound; var entity = Convert(item); var entry = dbSet.Update(entity); await dbContext.SaveChangesAsync(token); entry.State = EntityState.Detached; return entry.Entity.Id; } public virtual async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token) { if (!dtos.Any()) return 0; var ids = dtos.Select(d => d.Id); var countExistingEntities = await dbSet .Where(d => ids.Contains(d.Id)) .CountAsync(token); if (ids.Count() > countExistingEntities) return ICrudRepository.ErrorIdNotFound; var entities = dtos.Select(Convert); var entries = entities.Select(entity => dbSet.Update(entity)).Cast().ToList(); var affected = await dbContext.SaveChangesAsync(token); entries.ForEach(e => e.State = EntityState.Detached); return affected; } /// public virtual Task DeleteAsync(int id, CancellationToken token) { var entity = dbSet .AsNoTracking() .FirstOrDefault(e => e.Id == id); if (entity == default) return Task.FromResult(ICrudRepository.ErrorIdNotFound); var entry = dbSet.Remove(entity); var affected = dbContext.SaveChangesAsync(token); entry.State = EntityState.Detached; return affected; } public virtual async Task DeleteRangeAsync(IEnumerable ids, CancellationToken token) { if (!ids.Any()) return 0; var countExistingEntities = await dbSet .Where(d => ids.Contains(d.Id)) .CountAsync(token); if (ids.Count() > countExistingEntities) return ICrudRepository.ErrorIdNotFound; var entities = dbContext.Set().Where(e => ids.Contains(e.Id)); var entries = entities.Select(entity => dbSet.Remove(entity)).Cast().ToList(); var affected = await dbContext.SaveChangesAsync(token); entries.ForEach(e => e.State = EntityState.Detached); return affected; } protected virtual TDto Convert(TEntity src) => src.Adapt(); protected virtual TEntity Convert(TDto src) => src.Adapt(); } }