#if NET48 using System.Data.Entity; #else using Microsoft.EntityFrameworkCore; #endif using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; using AutoMapper; using ECMJobRunner.Domain.Interfaces; using ECMJobRunner.Infrastructure.Data; namespace ECMJobRunner.Infrastructure.Repositories { /// /// Generic repository implementation for Entity Framework /// /// Entity type public class Repository : IRepository where TEntity : class { protected readonly JobRunnerDbContext _context; protected readonly DbSet _dbSet; protected readonly IMapper _mapper; /// /// Constructor /// public Repository(JobRunnerDbContext context, IMapper mapper) { _context = context ?? throw new ArgumentNullException(nameof(context)); _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); _dbSet = context.Set(); } /// public virtual async Task GetByIdAsync(long id, CancellationToken cancellationToken = default) { #if NET48 return await Task.Run(() => _dbSet.Find(id), cancellationToken); #else return await _dbSet.FindAsync(new object[] { id }, cancellationToken); #endif } /// public virtual async Task> GetAllAsync(CancellationToken cancellationToken = default) { #if NET48 return await Task.Run(() => _dbSet.AsNoTracking().ToList(), cancellationToken); #else return await _dbSet.AsNoTracking().ToListAsync(cancellationToken); #endif } /// public virtual async Task> FindAsync(Expression> predicate, CancellationToken cancellationToken = default) { #if NET48 return await Task.Run(() => _dbSet.Where(predicate).AsNoTracking().ToList(), cancellationToken); #else return await _dbSet.Where(predicate).AsNoTracking().ToListAsync(cancellationToken); #endif } /// public virtual async Task SingleOrDefaultAsync(Expression> predicate, CancellationToken cancellationToken = default) { #if NET48 return await Task.Run(() => _dbSet.SingleOrDefault(predicate), cancellationToken); #else return await _dbSet.SingleOrDefaultAsync(predicate, cancellationToken); #endif } /// public virtual async Task AddAsync(TDto dto, CancellationToken cancellationToken = default) where TDto : class { if (dto == null) throw new ArgumentNullException(nameof(dto)); // Map DTO to new entity var entity = _mapper.Map(dto); #if NET48 await Task.Run(() => _dbSet.Add(entity), cancellationToken); #else await _dbSet.AddAsync(entity, cancellationToken); #endif await SaveChangesAsync(cancellationToken); return entity; } /// public virtual async Task AddRangeAsync(IEnumerable dtos, CancellationToken cancellationToken = default) where TDto : class { if (dtos == null) throw new ArgumentNullException(nameof(dtos)); var dtoList = dtos.ToList(); if (!dtoList.Any()) return 0; // Map DTOs to entities var entities = _mapper.Map>(dtoList); #if NET48 await Task.Run(() => _dbSet.AddRange(entities), cancellationToken); #else await _dbSet.AddRangeAsync(entities, cancellationToken); #endif return await SaveChangesAsync(cancellationToken); } /// public virtual async Task UpdateAsync(Expression> predicate, TDto dto, CancellationToken cancellationToken = default) where TDto : class { if (dto == null) throw new ArgumentNullException(nameof(dto)); // Get entities with tracking enabled for update #if NET48 var entities = await Task.Run(() => _dbSet.Where(predicate).ToList(), cancellationToken); #else var entities = await _dbSet.Where(predicate).ToListAsync(cancellationToken); #endif if (!entities.Any()) return 0; foreach (var entity in entities) { // Map DTO onto existing entity (only DTO properties are updated) _mapper.Map(dto, entity); } return await SaveChangesAsync(cancellationToken); } /// public virtual async Task UpdateSingleAsync(Expression> predicate, TDto dto, CancellationToken cancellationToken = default) where TDto : class { if (dto == null) throw new ArgumentNullException(nameof(dto)); // Get entity with tracking enabled for update var entity = await SingleOrDefaultAsync(predicate, cancellationToken); if (entity == null) return false; // Map DTO onto existing entity (only DTO properties are updated) _mapper.Map(dto, entity); await SaveChangesAsync(cancellationToken); return true; } /// public virtual async Task DeleteAsync(Expression> predicate, CancellationToken cancellationToken = default) { // Get entities with tracking enabled for delete #if NET48 var entities = await Task.Run(() => _dbSet.Where(predicate).ToList(), cancellationToken); #else var entities = await _dbSet.Where(predicate).ToListAsync(cancellationToken); #endif if (!entities.Any()) return 0; _dbSet.RemoveRange(entities); return await SaveChangesAsync(cancellationToken); } /// public virtual async Task DeleteSingleAsync(Expression> predicate, CancellationToken cancellationToken = default) { // Get entity with tracking enabled for delete var entity = await SingleOrDefaultAsync(predicate, cancellationToken); if (entity == null) return false; _dbSet.Remove(entity); await SaveChangesAsync(cancellationToken); return true; } /// public virtual async Task SaveChangesAsync(CancellationToken cancellationToken = default) { #if NET48 return await _context.SaveChangesAsync(); #else return await _context.SaveChangesAsync(cancellationToken); #endif } } }