Some checks failed
Docker Build & Deploy / Build Docker Image (push) Failing after 6s
Docker Build & Deploy / Deploy to Production (push) Has been skipped
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s
- Added BudgetArchiveJob for monthly budget archiving. - Created BudgetArchive entity and BudgetArchiveRepository for managing archived budgets. - Introduced JobController for handling job execution, pausing, and resuming. - Developed ScheduledTasksView for displaying and managing scheduled tasks in the frontend. - Updated PeriodicBillJob to improve scope handling. - Enhanced OpenAiService with increased HTTP timeout. - Added archiveBudgets API endpoint for archiving budgets by year and month. - Refactored BudgetController to utilize new repository patterns and improved error handling. - Introduced rich-content styles for better rendering of HTML content in Vue components. - Updated various Vue components to support rich HTML content display.
186 lines
4.5 KiB
C#
186 lines
4.5 KiB
C#
namespace Repository;
|
||
|
||
/// <summary>
|
||
/// 仓储基础接口
|
||
/// </summary>
|
||
/// <typeparam name="T">实体类型</typeparam>
|
||
public interface IBaseRepository<T> where T : BaseEntity
|
||
{
|
||
/// <summary>
|
||
/// 获取所有数据
|
||
/// </summary>
|
||
Task<IEnumerable<T>> GetAllAsync();
|
||
|
||
/// <summary>
|
||
/// 根据ID获取单条数据
|
||
/// </summary>
|
||
Task<T?> GetByIdAsync(long id);
|
||
|
||
/// <summary>
|
||
/// 根据ID获取单条数据
|
||
/// </summary>
|
||
Task<T[]> GetByIdsAsync(long[] ids);
|
||
|
||
/// <summary>
|
||
/// 添加数据
|
||
/// </summary>
|
||
Task<bool> AddAsync(T entity);
|
||
|
||
/// <summary>
|
||
/// 添加数据
|
||
/// </summary>
|
||
Task<bool> AddRangeAsync(IEnumerable<T> entities);
|
||
|
||
/// <summary>
|
||
/// 更新数据
|
||
/// </summary>
|
||
Task<bool> UpdateAsync(T entity);
|
||
|
||
/// <summary>
|
||
/// 批量更新数据
|
||
/// </summary>
|
||
Task<bool> UpdateRangeAsync(IEnumerable<T> entities);
|
||
|
||
/// <summary>
|
||
/// 删除数据
|
||
/// </summary>
|
||
Task<bool> DeleteAsync(long id);
|
||
|
||
/// <summary>
|
||
/// 执行动态SQL查询,返回动态对象
|
||
/// </summary>
|
||
/// <param name="completeSql">完整的SELECT SQL语句</param>
|
||
/// <returns>动态查询结果列表</returns>
|
||
Task<List<dynamic>> ExecuteDynamicSqlAsync(string completeSql);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 仓储基类实现 - 基于 FreeSql
|
||
/// </summary>
|
||
/// <typeparam name="T">实体类型</typeparam>
|
||
public abstract class BaseRepository<T>(IFreeSql freeSql) : IBaseRepository<T> where T : BaseEntity
|
||
{
|
||
protected readonly IFreeSql FreeSql = freeSql ?? throw new ArgumentNullException(nameof(freeSql));
|
||
|
||
public virtual async Task<IEnumerable<T>> GetAllAsync()
|
||
{
|
||
try
|
||
{
|
||
return await FreeSql.Select<T>().ToListAsync();
|
||
}
|
||
catch
|
||
{
|
||
return [];
|
||
}
|
||
}
|
||
|
||
public virtual async Task<T?> GetByIdAsync(long id)
|
||
{
|
||
try
|
||
{
|
||
// FreeSql 会根据配置自动识别主键
|
||
return await FreeSql.Select<T>().Where(x => x.Id == id).FirstAsync();
|
||
}
|
||
catch
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public virtual async Task<T[]> GetByIdsAsync(long[] ids)
|
||
{
|
||
try
|
||
{
|
||
var result = await FreeSql.Select<T>().Where(x => ids.Contains(x.Id)).ToListAsync();
|
||
return result.ToArray();
|
||
}
|
||
catch
|
||
{
|
||
return [];
|
||
}
|
||
}
|
||
|
||
public virtual async Task<bool> AddAsync(T entity)
|
||
{
|
||
try
|
||
{
|
||
var result = await FreeSql.Insert(entity).ExecuteAffrowsAsync();
|
||
return result == 1;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> AddRangeAsync(IEnumerable<T> entities)
|
||
{
|
||
var result = await FreeSql.Insert(entities).ExecuteAffrowsAsync();
|
||
return result == entities.Count();
|
||
}
|
||
|
||
public virtual async Task<bool> UpdateAsync(T entity)
|
||
{
|
||
try
|
||
{
|
||
var affrows = await FreeSql.Update<T>()
|
||
.SetSource(entity)
|
||
.ExecuteAffrowsAsync();
|
||
return affrows > 0;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Update failed: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public virtual async Task<bool> UpdateRangeAsync(IEnumerable<T> entities)
|
||
{
|
||
try
|
||
{
|
||
var affrows = await FreeSql.Update<T>()
|
||
.SetSource(entities)
|
||
.ExecuteAffrowsAsync();
|
||
return affrows == entities.Count();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"UpdateRange failed: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public virtual async Task<bool> DeleteAsync(long id)
|
||
{
|
||
try
|
||
{
|
||
var affrows = await FreeSql.Delete<T>().Where(x => x.Id == id).ExecuteAffrowsAsync();
|
||
return affrows > 0;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<List<dynamic>> ExecuteDynamicSqlAsync(string completeSql)
|
||
{
|
||
var dt = await FreeSql.Ado.ExecuteDataTableAsync(completeSql);
|
||
var result = new List<dynamic>();
|
||
|
||
foreach (System.Data.DataRow row in dt.Rows)
|
||
{
|
||
var expando = new System.Dynamic.ExpandoObject() as IDictionary<string, object>;
|
||
foreach (System.Data.DataColumn column in dt.Columns)
|
||
{
|
||
expando[column.ColumnName] = row[column];
|
||
}
|
||
result.Add(expando);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|