#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
}
}
}