Refactors repositories for improved structure
Improves repository structure by introducing a generic DbCrud class and dedicated repositories for each entity. This change enhances code maintainability and testability by separating concerns. It also introduces soft delete functionality to the generic repository.
This commit is contained in:
@@ -3,4 +3,9 @@ namespace LiquidCode.Api.Authentication.Requests;
|
||||
/// <summary>
|
||||
/// Модель запроса для входа пользователя
|
||||
/// </summary>
|
||||
public record LoginRequest(string Username, string Password);
|
||||
/// <param name="Username">Имя пользователя</param>
|
||||
/// <param name="Password">Пароль</param>
|
||||
public record LoginRequest(
|
||||
string Username,
|
||||
string Password
|
||||
);
|
||||
|
||||
@@ -35,12 +35,12 @@ public interface IMissionRepository : IRepository<DbMission>
|
||||
/// <summary>
|
||||
/// Добавляет текстовые данные миссии
|
||||
/// </summary>
|
||||
Task AddMissionTextAsync(DbMissionPublicTextData textData, CancellationToken cancellationToken = default);
|
||||
Task CreateMissionTextAsync(DbMissionPublicTextData textData, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Добавляет несколько записей текстовых данных миссии
|
||||
/// </summary>
|
||||
Task AddMissionTextsAsync(IEnumerable<DbMissionPublicTextData> textData, CancellationToken cancellationToken = default);
|
||||
Task CreateMissionTextsAsync(IEnumerable<DbMissionPublicTextData> textData, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Подсчитывает общее количество миссий
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using LiquidCode.Infrastructure.Database.Entities;
|
||||
|
||||
namespace LiquidCode.Domain.Interfaces.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый интерфейс репозитория для общих операций CRUD
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">Тип сущности, управляемой этим репозиторием</typeparam>
|
||||
public interface IRepository<TEntity> where TEntity : class
|
||||
public interface IRepository<TEntity> where TEntity : class, ISoftDeletable
|
||||
{
|
||||
/// <summary>
|
||||
/// Находит сущность по ее ID
|
||||
@@ -12,14 +14,19 @@ public interface IRepository<TEntity> where TEntity : class
|
||||
Task<TEntity?> FindByIdAsync(int id, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Получает все сущности
|
||||
/// Получает все сущности с пагинацией
|
||||
/// </summary>
|
||||
Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = default);
|
||||
/// <param name="pageSize">Количество элементов на странице</param>
|
||||
/// <param name="pageNumber">Номер страницы (начиная с 0)</param>
|
||||
/// <param name="cancellationToken">Токен отмены</param>
|
||||
/// <returns>Кортеж (сущности, естьСледующаяСтраница)</returns>
|
||||
Task<(IEnumerable<TEntity> Items, bool HasNextPage)> GetPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Добавляет новую сущность
|
||||
/// </summary>
|
||||
Task AddAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
Task CreateAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет существующую сущность
|
||||
@@ -29,7 +36,12 @@ public interface IRepository<TEntity> where TEntity : class
|
||||
/// <summary>
|
||||
/// Удаляет сущность
|
||||
/// </summary>
|
||||
Task RemoveAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Мягко удаляет сущность
|
||||
/// </summary>
|
||||
Task SoftDeleteAsync(TEntity entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Сохраняет все изменения, сделанные в базе данных
|
||||
|
||||
@@ -55,7 +55,7 @@ public class AuthenticationService : IAuthenticationService
|
||||
Salt = "" // BCrypt управляет солью внутренне
|
||||
};
|
||||
|
||||
await _userRepository.AddAsync(newUser, cancellationToken);
|
||||
await _userRepository.CreateAsync(newUser, cancellationToken);
|
||||
_logger.LogInformation("User registered successfully: {Username}", request.Username);
|
||||
|
||||
// Автоматически войти пользователю
|
||||
|
||||
@@ -83,7 +83,7 @@ public class MissionService : IMissionService
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await _missionRepository.AddAsync(dbMission, cancellationToken);
|
||||
await _missionRepository.CreateAsync(dbMission, cancellationToken);
|
||||
|
||||
// Распарсить и сохранить текстовые данные миссии
|
||||
var missionTexts = ExtractMissionTexts(statementSectionsPath, dbMission.Id);
|
||||
@@ -104,7 +104,7 @@ public class MissionService : IMissionService
|
||||
}
|
||||
|
||||
// Добавить текстовые данные миссии в базу данных
|
||||
await _missionRepository.AddMissionTextsAsync(missionTexts, cancellationToken);
|
||||
await _missionRepository.CreateMissionTextsAsync(missionTexts, cancellationToken);
|
||||
await _missionRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_logger.LogInformation("Mission uploaded successfully: {MissionId}", dbMission.Id);
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SubmitService : ISubmitService
|
||||
Solution = solution
|
||||
};
|
||||
|
||||
await _submitRepository.AddAsync(submission, cancellationToken);
|
||||
await _submitRepository.CreateAsync(submission, cancellationToken);
|
||||
_logger.LogInformation("Solution submitted: UserId={UserId}, MissionId={MissionId}, SolutionId={SolutionId}", userId, missionId, solution.Id);
|
||||
|
||||
return solution;
|
||||
|
||||
70
LiquidCode/Infrastructure/Database/Repositories/DbCrud.cs
Normal file
70
LiquidCode/Infrastructure/Database/Repositories/DbCrud.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using LiquidCode.Domain.Interfaces.Repositories;
|
||||
using LiquidCode.Infrastructure.Database;
|
||||
using LiquidCode.Infrastructure.Database.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LiquidCode.Infrastructure.Database.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Базовая реализация репозитория, предоставляющая общие операции CRUD
|
||||
/// </summary>
|
||||
public class DbCrud<TEntity> : IRepository<TEntity> where TEntity : class, ISoftDeletable
|
||||
{
|
||||
private readonly LiquidDbContext _dbContext;
|
||||
public readonly DbSet<TEntity> DbSet;
|
||||
|
||||
public DbCrud(LiquidDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
DbSet = dbContext.Set<TEntity>();
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity?> FindByIdAsync(int id, CancellationToken cancellationToken = default) =>
|
||||
await DbSet.FindAsync(new object?[] { id }, cancellationToken);
|
||||
|
||||
public virtual async Task<(IEnumerable<TEntity> Items, bool HasNextPage)> GetPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (pageSize <= 0 || pageNumber < 0)
|
||||
throw new ArgumentException("Page size must be positive, page number must be non-negative");
|
||||
|
||||
var totalCount = await DbSet.CountAsync(cancellationToken);
|
||||
var hasNextPage = totalCount > pageSize * (pageNumber + 1);
|
||||
|
||||
var items = await DbSet
|
||||
.OrderBy(x => EF.Property<int>(x, "Id"))
|
||||
.Skip(pageSize * pageNumber)
|
||||
.Take(pageSize)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return (items, hasNextPage);
|
||||
}
|
||||
|
||||
public virtual async Task CreateAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await DbSet.AddAsync(entity, cancellationToken);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
DbSet.Update(entity);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
DbSet.Remove(entity);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task SoftDeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
entity.IsDeleted = true;
|
||||
DbSet.Update(entity);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task SaveChangesAsync(CancellationToken cancellationToken = default) =>
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
@@ -8,52 +8,63 @@ namespace LiquidCode.Infrastructure.Database.Repositories;
|
||||
/// <summary>
|
||||
/// Реализация репозитория для операций с базой данных, связанных с миссиями
|
||||
/// </summary>
|
||||
public class MissionRepository : Repository<DbMission>, IMissionRepository
|
||||
public class MissionRepository : IMissionRepository
|
||||
{
|
||||
public MissionRepository(LiquidDbContext dbContext) : base(dbContext)
|
||||
private readonly LiquidDbContext _dbContext;
|
||||
private readonly DbCrud<DbMission> _missionRepository;
|
||||
|
||||
public MissionRepository(LiquidDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_missionRepository = new DbCrud<DbMission>(dbContext);
|
||||
}
|
||||
|
||||
public async Task<(IEnumerable<DbMission> Missions, bool HasNextPage)> GetMissionsPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (pageSize <= 0 || pageNumber < 0)
|
||||
throw new ArgumentException("Page size must be positive, page number must be non-negative");
|
||||
// IRepository<DbMission> implementation (delegated to _missionRepository)
|
||||
public Task<DbMission?> FindByIdAsync(int id, CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.FindByIdAsync(id, cancellationToken);
|
||||
|
||||
var totalCount = await DbSet.CountAsync(cancellationToken);
|
||||
var hasNextPage = totalCount > pageSize * (pageNumber + 1);
|
||||
public Task<(IEnumerable<DbMission> Items, bool HasNextPage)> GetPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.GetPageAsync(pageSize, pageNumber, cancellationToken);
|
||||
|
||||
var missions = await DbSet
|
||||
.OrderBy(m => m.Id)
|
||||
.Skip(pageSize * pageNumber)
|
||||
.Take(pageSize)
|
||||
.ToListAsync(cancellationToken);
|
||||
public Task CreateAsync(DbMission entity, CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.CreateAsync(entity, cancellationToken);
|
||||
|
||||
return (missions, hasNextPage);
|
||||
}
|
||||
public Task UpdateAsync(DbMission entity, CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.UpdateAsync(entity, cancellationToken);
|
||||
|
||||
public Task DeleteAsync(DbMission entity, CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.DeleteAsync(entity, cancellationToken);
|
||||
|
||||
public Task SoftDeleteAsync(DbMission entity, CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.SoftDeleteAsync(entity, cancellationToken);
|
||||
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default) =>
|
||||
_missionRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// IMissionRepository specific methods
|
||||
public async Task<IEnumerable<DbMission>> GetMissionsByAuthorAsync(int authorId, CancellationToken cancellationToken = default) =>
|
||||
await DbSet
|
||||
await _dbContext.Set<DbMission>()
|
||||
.Where(m => m.Author.Id == authorId)
|
||||
.OrderByDescending(m => m.CreatedAt)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
public async Task<DbMissionPublicTextData?> GetMissionTextAsync(int missionId, string language, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.MissionsTextData
|
||||
await _dbContext.MissionsTextData
|
||||
.FirstOrDefaultAsync(m => m.MissionId == missionId && m.Language == language, cancellationToken);
|
||||
|
||||
public async Task<IEnumerable<string>> GetMissionLanguagesAsync(int missionId, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.MissionsTextData
|
||||
await _dbContext.MissionsTextData
|
||||
.Where(m => m.MissionId == missionId)
|
||||
.Select(m => m.Language)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
public async Task AddMissionTextAsync(DbMissionPublicTextData textData, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.MissionsTextData.AddAsync(textData, cancellationToken);
|
||||
public async Task CreateMissionTextAsync(DbMissionPublicTextData textData, CancellationToken cancellationToken = default) =>
|
||||
await _dbContext.MissionsTextData.AddAsync(textData, cancellationToken);
|
||||
|
||||
public async Task AddMissionTextsAsync(IEnumerable<DbMissionPublicTextData> textData, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.MissionsTextData.AddRangeAsync(textData, cancellationToken);
|
||||
public async Task CreateMissionTextsAsync(IEnumerable<DbMissionPublicTextData> textData, CancellationToken cancellationToken = default) =>
|
||||
await _dbContext.MissionsTextData.AddRangeAsync(textData, cancellationToken);
|
||||
|
||||
public async Task<int> CountMissionsAsync(CancellationToken cancellationToken = default) =>
|
||||
await DbSet.CountAsync(cancellationToken);
|
||||
await _dbContext.Set<DbMission>().CountAsync(cancellationToken);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using LiquidCode.Domain.Interfaces.Repositories;
|
||||
using LiquidCode.Infrastructure.Database;
|
||||
using LiquidCode.Infrastructure.Database.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LiquidCode.Infrastructure.Database.Repositories;
|
||||
@@ -7,24 +8,39 @@ namespace LiquidCode.Infrastructure.Database.Repositories;
|
||||
/// <summary>
|
||||
/// Базовая реализация репозитория, предоставляющая общие операции CRUD
|
||||
/// </summary>
|
||||
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
|
||||
public class DbCrud<TEntity> : IRepository<TEntity> where TEntity : class, ISoftDeletable
|
||||
{
|
||||
protected readonly LiquidDbContext DbContext;
|
||||
protected readonly DbSet<TEntity> DbSet;
|
||||
private readonly LiquidDbContext _dbContext;
|
||||
public readonly DbSet<TEntity> DbSet;
|
||||
|
||||
public Repository(LiquidDbContext dbContext)
|
||||
public DbCrud(LiquidDbContext dbContext)
|
||||
{
|
||||
DbContext = dbContext;
|
||||
_dbContext = dbContext;
|
||||
DbSet = dbContext.Set<TEntity>();
|
||||
}
|
||||
|
||||
public virtual async Task<TEntity?> FindByIdAsync(int id, CancellationToken cancellationToken = default) =>
|
||||
await DbSet.FindAsync(new object?[] { id }, cancellationToken);
|
||||
|
||||
public virtual async Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = default) =>
|
||||
await DbSet.ToListAsync(cancellationToken);
|
||||
public virtual async Task<(IEnumerable<TEntity> Items, bool HasNextPage)> GetPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (pageSize <= 0 || pageNumber < 0)
|
||||
throw new ArgumentException("Page size must be positive, page number must be non-negative");
|
||||
|
||||
public virtual async Task AddAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
var totalCount = await DbSet.CountAsync(cancellationToken);
|
||||
var hasNextPage = totalCount > pageSize * (pageNumber + 1);
|
||||
|
||||
var items = await DbSet
|
||||
.OrderBy(x => EF.Property<int>(x, "Id"))
|
||||
.Skip(pageSize * pageNumber)
|
||||
.Take(pageSize)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return (items, hasNextPage);
|
||||
}
|
||||
|
||||
public virtual async Task CreateAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await DbSet.AddAsync(entity, cancellationToken);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
@@ -36,12 +52,19 @@ public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
public virtual async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
DbSet.Remove(entity);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task SoftDeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
|
||||
{
|
||||
entity.IsDeleted = true;
|
||||
DbSet.Update(entity);
|
||||
await SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task SaveChangesAsync(CancellationToken cancellationToken = default) =>
|
||||
await DbContext.SaveChangesAsync(cancellationToken);
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
@@ -8,34 +8,63 @@ namespace LiquidCode.Infrastructure.Database.Repositories;
|
||||
/// <summary>
|
||||
/// Реализация репозитория для операций с базой данных, связанных с отправками пользователей
|
||||
/// </summary>
|
||||
public class SubmitRepository : Repository<DbUserSubmit>, ISubmitRepository
|
||||
public class SubmitRepository : ISubmitRepository
|
||||
{
|
||||
public SubmitRepository(LiquidDbContext dbContext) : base(dbContext)
|
||||
private readonly LiquidDbContext _dbContext;
|
||||
private readonly DbCrud<DbUserSubmit> _submitRepository;
|
||||
|
||||
public SubmitRepository(LiquidDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_submitRepository = new DbCrud<DbUserSubmit>(dbContext);
|
||||
}
|
||||
|
||||
// IRepository<DbUserSubmit> implementation (delegated to _submitRepository)
|
||||
public Task<DbUserSubmit?> FindByIdAsync(int id, CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.FindByIdAsync(id, cancellationToken);
|
||||
|
||||
public Task<(IEnumerable<DbUserSubmit> Items, bool HasNextPage)> GetPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.GetPageAsync(pageSize, pageNumber, cancellationToken);
|
||||
|
||||
public Task CreateAsync(DbUserSubmit entity, CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.CreateAsync(entity, cancellationToken);
|
||||
|
||||
public Task UpdateAsync(DbUserSubmit entity, CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.UpdateAsync(entity, cancellationToken);
|
||||
|
||||
public Task DeleteAsync(DbUserSubmit entity, CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.DeleteAsync(entity, cancellationToken);
|
||||
|
||||
public Task SoftDeleteAsync(DbUserSubmit entity, CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.SoftDeleteAsync(entity, cancellationToken);
|
||||
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default) =>
|
||||
_submitRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// ISubmitRepository specific methods
|
||||
public async Task<IEnumerable<DbUserSubmit>> GetSubmissionsByUserAsync(int userId, CancellationToken cancellationToken = default) =>
|
||||
await DbSet
|
||||
await _dbContext.Set<DbUserSubmit>()
|
||||
.Where(s => s.User.Id == userId)
|
||||
.OrderByDescending(s => s.Solution!.Time)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
public async Task<IEnumerable<DbUserSubmit>> GetSubmissionsByMissionAsync(int missionId, CancellationToken cancellationToken = default) =>
|
||||
await DbSet
|
||||
await _dbContext.Set<DbUserSubmit>()
|
||||
.Where(s => s.Solution!.Mission.Id == missionId)
|
||||
.OrderByDescending(s => s.Solution!.Time)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
public async Task<DbUserSubmit?> GetSubmissionWithDetailsAsync(int submissionId, CancellationToken cancellationToken = default) =>
|
||||
await DbSet
|
||||
await _dbContext.Set<DbUserSubmit>()
|
||||
.Include(s => s.User)
|
||||
.Include(s => s.Solution)
|
||||
.FirstOrDefaultAsync(s => s.Id == submissionId, cancellationToken);
|
||||
|
||||
public async Task<DbSolution?> GetSolutionAsync(int solutionId, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.Solutions
|
||||
await _dbContext.Solutions
|
||||
.FirstOrDefaultAsync(s => s.Id == solutionId, cancellationToken);
|
||||
|
||||
public async Task AddSolutionAsync(DbSolution solution, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.Solutions.AddAsync(solution, cancellationToken);
|
||||
await _dbContext.Solutions.AddAsync(solution, cancellationToken);
|
||||
}
|
||||
|
||||
@@ -8,39 +8,68 @@ namespace LiquidCode.Infrastructure.Database.Repositories;
|
||||
/// <summary>
|
||||
/// Реализация репозитория для операций с базой данных, связанных с пользователями
|
||||
/// </summary>
|
||||
public class UserRepository : Repository<DbUser>, IUserRepository
|
||||
public class UserRepository : IUserRepository
|
||||
{
|
||||
public UserRepository(LiquidDbContext dbContext) : base(dbContext)
|
||||
private readonly LiquidDbContext _dbContext;
|
||||
private readonly DbCrud<DbUser> _userRepository;
|
||||
|
||||
public UserRepository(LiquidDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_userRepository = new DbCrud<DbUser>(dbContext);
|
||||
}
|
||||
|
||||
// IRepository<DbUser> implementation (delegated to _userRepository)
|
||||
public Task<DbUser?> FindByIdAsync(int id, CancellationToken cancellationToken = default) =>
|
||||
_userRepository.FindByIdAsync(id, cancellationToken);
|
||||
|
||||
public Task<(IEnumerable<DbUser> Items, bool HasNextPage)> GetPageAsync(
|
||||
int pageSize, int pageNumber, CancellationToken cancellationToken = default) =>
|
||||
_userRepository.GetPageAsync(pageSize, pageNumber, cancellationToken);
|
||||
|
||||
public Task CreateAsync(DbUser entity, CancellationToken cancellationToken = default) =>
|
||||
_userRepository.CreateAsync(entity, cancellationToken);
|
||||
|
||||
public Task UpdateAsync(DbUser entity, CancellationToken cancellationToken = default) =>
|
||||
_userRepository.UpdateAsync(entity, cancellationToken);
|
||||
|
||||
public Task DeleteAsync(DbUser entity, CancellationToken cancellationToken = default) =>
|
||||
_userRepository.DeleteAsync(entity, cancellationToken);
|
||||
|
||||
public Task SoftDeleteAsync(DbUser entity, CancellationToken cancellationToken = default) =>
|
||||
_userRepository.SoftDeleteAsync(entity, cancellationToken);
|
||||
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default) =>
|
||||
_userRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// IUserRepository specific methods
|
||||
public async Task<DbUser?> FindByUsernameAsync(string username, CancellationToken cancellationToken = default) =>
|
||||
await DbSet.FirstOrDefaultAsync(u => u.Username == username, cancellationToken);
|
||||
await _dbContext.Users.FirstOrDefaultAsync(u => u.Username == username, cancellationToken);
|
||||
|
||||
public async Task<bool> UserExistsAsync(string username, CancellationToken cancellationToken = default) =>
|
||||
await DbSet.AnyAsync(u => u.Username == username, cancellationToken);
|
||||
await _dbContext.Users.AnyAsync(u => u.Username == username, cancellationToken);
|
||||
|
||||
public async Task<int> GetRefreshTokenCountAsync(int userId, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.RefreshTokens.CountAsync(t => t.DbUser.Id == userId, cancellationToken);
|
||||
await _dbContext.RefreshTokens.CountAsync(t => t.DbUser.Id == userId, cancellationToken);
|
||||
|
||||
public async Task<DbRefreshToken?> GetOldestRefreshTokenAsync(int userId, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.RefreshTokens
|
||||
await _dbContext.RefreshTokens
|
||||
.Where(t => t.DbUser.Id == userId)
|
||||
.OrderBy(t => t.Expires)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
public async Task AddRefreshTokenAsync(DbRefreshToken token, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.RefreshTokens.AddAsync(token, cancellationToken);
|
||||
await _dbContext.RefreshTokens.AddAsync(token, cancellationToken);
|
||||
|
||||
public async Task RemoveRefreshTokenAsync(string tokenString, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var token = await DbContext.RefreshTokens.FirstOrDefaultAsync(t => t.Token == tokenString, cancellationToken);
|
||||
var token = await _dbContext.RefreshTokens.FirstOrDefaultAsync(t => t.Token == tokenString, cancellationToken);
|
||||
if (token != null)
|
||||
DbContext.RefreshTokens.Remove(token);
|
||||
_dbContext.RefreshTokens.Remove(token);
|
||||
}
|
||||
|
||||
public async Task<DbRefreshToken?> FindRefreshTokenAsync(string tokenString, CancellationToken cancellationToken = default) =>
|
||||
await DbContext.RefreshTokens
|
||||
await _dbContext.RefreshTokens
|
||||
.Include(t => t.DbUser)
|
||||
.FirstOrDefaultAsync(t => t.Token == tokenString, cancellationToken);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user