using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using DramaLing.Api.Data;
using DramaLing.Api.Contracts.Repositories;
namespace DramaLing.Api.Repositories;
///
/// 基礎 Repository 實作,提供通用的數據存取邏輯
///
/// 實體類型
public class BaseRepository : IRepository where T : class
{
protected readonly DramaLingDbContext _context;
protected readonly DbSet _dbSet;
protected readonly ILogger> _logger;
public BaseRepository(DramaLingDbContext context, ILogger> logger)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_dbSet = _context.Set();
}
#region 查詢操作
public virtual async Task GetByIdAsync(object id)
{
try
{
return await _dbSet.FindAsync(id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting entity by id: {Id}", id);
throw;
}
}
public virtual async Task> GetAllAsync()
{
try
{
return await _dbSet.AsNoTracking().ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting all entities of type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task> FindAsync(Expression> predicate)
{
try
{
return await _dbSet.AsNoTracking().Where(predicate).ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error finding entities with predicate for type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task FirstOrDefaultAsync(Expression> predicate)
{
try
{
return await _dbSet.AsNoTracking().FirstOrDefaultAsync(predicate);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting first entity with predicate for type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task ExistsAsync(Expression> predicate)
{
try
{
return await _dbSet.AnyAsync(predicate);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error checking entity existence for type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task CountAsync(Expression>? predicate = null)
{
try
{
return predicate == null
? await _dbSet.CountAsync()
: await _dbSet.CountAsync(predicate);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error counting entities for type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task<(IEnumerable Items, int TotalCount)> GetPagedAsync(
int pageNumber,
int pageSize,
Expression>? filter = null,
Func, IOrderedQueryable>? orderBy = null)
{
try
{
var query = _dbSet.AsNoTracking();
if (filter != null)
query = query.Where(filter);
var totalCount = await query.CountAsync();
if (orderBy != null)
query = orderBy(query);
var items = await query
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return (items, totalCount);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting paged entities for type {EntityType}, page: {PageNumber}, size: {PageSize}",
typeof(T).Name, pageNumber, pageSize);
throw;
}
}
#endregion
#region 修改操作
public virtual async Task AddAsync(T entity)
{
try
{
var result = await _dbSet.AddAsync(entity);
return result.Entity;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding entity of type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task> AddRangeAsync(IEnumerable entities)
{
try
{
var entityList = entities.ToList();
await _dbSet.AddRangeAsync(entityList);
return entityList;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding entities of type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual Task UpdateAsync(T entity)
{
try
{
_dbSet.Update(entity);
return Task.CompletedTask;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating entity of type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual Task UpdateRangeAsync(IEnumerable entities)
{
try
{
_dbSet.UpdateRange(entities);
return Task.CompletedTask;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating entities of type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual Task DeleteAsync(T entity)
{
try
{
_dbSet.Remove(entity);
return Task.CompletedTask;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting entity of type {EntityType}", typeof(T).Name);
throw;
}
}
public virtual async Task DeleteAsync(object id)
{
try
{
var entity = await GetByIdAsync(id);
if (entity != null)
{
_dbSet.Remove(entity);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting entity by id: {Id} of type {EntityType}", id, typeof(T).Name);
throw;
}
}
public virtual Task DeleteRangeAsync(IEnumerable entities)
{
try
{
_dbSet.RemoveRange(entities);
return Task.CompletedTask;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting entities of type {EntityType}", typeof(T).Name);
throw;
}
}
#endregion
#region 工作單元
public virtual async Task SaveChangesAsync()
{
try
{
return await _context.SaveChangesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error saving changes for type {EntityType}", typeof(T).Name);
throw;
}
}
#endregion
}