Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@

builder.Services
.AddDbContext<DataContext>(opts => opts.UseInMemoryDatabase("DemoDb"))
.AddScoped(typeof(IRepository<>), typeof(Repository<>))
.AddScoped<IUnitOfWork, UnitOfWork>();
.AddScoped(typeof(IRepository<>), typeof(Repository<>));

builder.Services.AddApiVersioning(options =>
{
Expand Down
47 changes: 41 additions & 6 deletions src/Domain/Interfaces/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,50 @@ public interface IRepository<TEntity> : IAsyncDisposable where TEntity : class

Task<TEntity?> GetByIdAsync<TKey>(TKey id, CancellationToken cancellationToken = default);

Task<List<TEntity>> ListAsync(Expression<Func<TEntity, bool>>? predicate = null, CancellationToken cancellationToken = default);
Task<List<TEntity>> ListAsync(Expression<Func<TEntity, bool>>? predicate = null, bool asNoTracking = true, CancellationToken cancellationToken = default);

Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<int> CountAsync(Expression<Func<TEntity, bool>>? predicate = null, CancellationToken cancellationToken = default);

Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);
TEntity Add(TEntity entity);
Task<TEntity> AddAsync(
TEntity entity,
CancellationToken cancellationToken = default);

Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
void AddRange(params TEntity[] entities);

Task<int> UpdateAsync(Expression<Func<TEntity, bool>> predicate, object updateDefinition, CancellationToken cancellationToken = default);
void AddRange(IEnumerable<TEntity> entities);

Task AddRangeAsync(params TEntity[] entities);

Task AddRangeAsync(
IEnumerable<TEntity> entities,
CancellationToken cancellationToken = default);

TEntity Attach(TEntity entity);
void AttachRange(params TEntity[] entities);

void AttachRange(IEnumerable<TEntity> entities);

TEntity Update(TEntity entity);

void UpdateRange(params TEntity[] entities);

void UpdateRange(IEnumerable<TEntity> entities);

TEntity Remove(TEntity entity);

void RemoveRange(params TEntity[] entities);

void RemoveRange(IEnumerable<TEntity> entities);

Task<int> ExecuteDeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

Task<int> ExecuteUpdateAsync(
Expression<Func<TEntity, bool>> predicate,
object updateDefinition,
CancellationToken cancellationToken = default);

Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
9 changes: 0 additions & 9 deletions src/Domain/Interfaces/IUnitOfWork.cs

This file was deleted.

106 changes: 74 additions & 32 deletions src/Infra/Repositories/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Infra.Repositories;

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, new()
{
private readonly DataContext _dataContext;
private readonly DbSet<TEntity> _dbSet;
Expand All @@ -18,61 +18,103 @@ public Repository(DataContext dataContext)
_dbSet = dataContext.Set<TEntity>();
}

public IQueryable<TEntity> Query(bool asNoTracking = true) => (asNoTracking ? _dbSet.AsNoTracking() : _dbSet).AsQueryable();
public IQueryable<TEntity> Query(bool asNoTracking = true) =>
asNoTracking ? _dbSet.AsNoTracking() : _dbSet.AsQueryable();

public Task<TEntity?> GetByIdAsync<TKey>(TKey id, CancellationToken cancellationToken = default)
{
return _dbSet.FindAsync(new object?[] { id }!, cancellationToken).AsTask();
}
=> _dbSet.FindAsync(new object?[] { id }!, cancellationToken).AsTask();

public Task<List<TEntity>> ListAsync(Expression<Func<TEntity, bool>>? predicate = null, CancellationToken cancellationToken = default)
public Task<List<TEntity>> ListAsync(
Expression<Func<TEntity, bool>>? predicate = null,
bool asNoTracking = true,
CancellationToken cancellationToken = default)
{
IQueryable<TEntity> query = _dbSet;
if (predicate is not null) query = query.Where(predicate);
IQueryable<TEntity> query = Query(asNoTracking);
if (predicate != null) query = query.Where(predicate);
return query.ToListAsync(cancellationToken);
}

public async Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default)
{
await _dbSet.AddAsync(entity, cancellationToken);
public Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
=> _dbSet.AnyAsync(predicate, cancellationToken);

return entity;
}
public Task<int> CountAsync(Expression<Func<TEntity, bool>>? predicate = null, CancellationToken cancellationToken = default)
=> predicate == null
? _dbSet.CountAsync(cancellationToken)
: _dbSet.CountAsync(predicate, cancellationToken);

public Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
{
_dbSet.Update(entity);
public TEntity Add(TEntity entity)
=> _dbSet.Add(entity).Entity;

return Task.CompletedTask;
}
public async Task<TEntity> AddAsync(
TEntity entity,
CancellationToken cancellationToken = default)
=> (await _dbSet.AddAsync(entity, cancellationToken)).Entity;

public Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
{
_dbSet.Remove(entity);
public void AddRange(params TEntity[] entities)
=> _dbSet.AddRange(entities);

return Task.CompletedTask;
}
public void AddRange(IEnumerable<TEntity> entities)
=> _dbSet.AddRange(entities);

public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
{
return _dbSet.Where(predicate).ExecuteDeleteAsync(cancellationToken);
}
public Task AddRangeAsync(params TEntity[] entities)
=> _dbSet.AddRangeAsync(entities);

public Task AddRangeAsync(
IEnumerable<TEntity> entities,
CancellationToken cancellationToken = default)
=> _dbSet.AddRangeAsync(entities, cancellationToken);

public Task<int> UpdateAsync(Expression<Func<TEntity, bool>> predicate, object updateDefinition, CancellationToken cancellationToken = default)
public TEntity Attach(TEntity entity)
=> _dbSet.Attach(entity).Entity;

public void AttachRange(params TEntity[] entities)
=> _dbSet.AttachRange(entities);

public void AttachRange(IEnumerable<TEntity> entities)
=> _dbSet.AttachRange(entities);

public TEntity Update(TEntity entity)
=> _dbSet.Update(entity).Entity;

public void UpdateRange(params TEntity[] entities)
=> _dbSet.UpdateRange(entities);

public void UpdateRange(IEnumerable<TEntity> entities)
=> _dbSet.UpdateRange(entities);

public TEntity Remove(TEntity entity)
=> _dbSet.Remove(entity).Entity;

public void RemoveRange(params TEntity[] entities)
=> _dbSet.RemoveRange(entities);

public void RemoveRange(IEnumerable<TEntity> entities)
=> _dbSet.RemoveRange(entities);

public Task<int> ExecuteDeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
=> _dbSet.Where(predicate).ExecuteDeleteAsync(cancellationToken);

public Task<int> ExecuteUpdateAsync(
Expression<Func<TEntity, bool>> predicate,
object updateDefinition,
CancellationToken cancellationToken = default)
{
if (updateDefinition is not Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> expression)
if (updateDefinition is not Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> updateExpression)
{
throw new InvalidOperationException($"Invalid update definition for type '{typeof(TEntity).Name}'. Expected an expression of type Expression<Func<SetPropertyCalls<{typeof(TEntity).Name}>, SetPropertyCalls<{typeof(TEntity).Name}>>>.");
throw new ArgumentException("Invalid update expression for EF Core", nameof(updateDefinition));
}

return _dbSet.Where(predicate).ExecuteUpdateAsync(expression, cancellationToken);
return _dbSet.Where(predicate).ExecuteUpdateAsync(updateExpression, cancellationToken);
}

public Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) => _dataContext.SaveChangesAsync(cancellationToken);

public async ValueTask DisposeAsync()
{
if (Interlocked.Exchange(ref _disposed, 1) == 0)
{
await _dataContext.DisposeAsync();
GC.SuppressFinalize(this);
}
}
}
}
22 changes: 0 additions & 22 deletions src/Infra/Repositories/UnitOfWork.cs

This file was deleted.