$mermaidjs
Clean Architecture Demo
Loading...
Searching...
No Matches
TaskReadRepository.cs
Go to the documentation of this file.
1// TaskManagement.Infrastructure/Persistence/Repositories/TaskReadRepository.cs
2using Dapper;
3using Microsoft.Data.Sqlite;
4using Microsoft.Extensions.Configuration;
9
11
12#pragma warning disable CS1570 // XML comment has badly formed XML
58#pragma warning restore CS1570 // XML comment has badly formed XML
60{
61 private readonly string _connectionString;
62
63 public TaskReadRepository(IConfiguration configuration)
64 {
65 _connectionString = configuration.GetConnectionString("DefaultConnection")
66 ?? throw new InvalidOperationException("DefaultConnection is not configured.");
67 }
68
69 public async Task<TaskDto?> GetByIdAsync(
70 Guid id,
71 CancellationToken cancellationToken = default)
72 {
73 const string sql = @"
74 SELECT
75 t.Id,
76 t.Title,
77 t.Description,
78 t.Status,
79 t.Priority,
80 t.DueDate,
81 t.CreatedAt,
82 t.CreatedBy as CreatedBy,
83 t.AssignedTo as AssignedTo
84 FROM Tasks t
85 WHERE t.Id = @Id";
86
87 using var connection = CreateConnection();
88 var command = new CommandDefinition(
89 sql,
90 new {
91 Id = id
92 },
93 cancellationToken: cancellationToken);
94
95 return await connection.QueryFirstOrDefaultAsync<TaskDto>(command).ConfigureAwait(false);
96 }
97
98 public async Task<PagedResult<TaskDto>> SearchAsync(
99 TaskSearchRequest request,
100 CancellationToken cancellationToken = default)
101 {
102 ArgumentNullException.ThrowIfNull(request);
103
104 const string selectSql = @"
105 SELECT
106 t.Id, t.Title, t.Description, t.Status, t.Priority,
107 t.DueDate, t.CreatedAt, t.CreatedBy as CreatedBy,
108 t.AssignedTo as AssignedTo
109 FROM Tasks t";
110 const string countSql = "SELECT COUNT(*) FROM Tasks t";
111 var whereClause = BuildWhereClause(request);
112 var orderClause = $"ORDER BY {request.SortBy} {request.SortDirection}";
113 var pagedSql = $"{selectSql} {whereClause} {orderClause} LIMIT @PageSize OFFSET @Offset";
114 var parameters = new DynamicParameters(request);
115 parameters.Add("Offset", (request.Page - 1) * request.PageSize);
116
117 using var connection = CreateConnection();
118 var command = new CommandDefinition(
119 $"{pagedSql}; {countSql} {whereClause}",
120 parameters,
121 cancellationToken: cancellationToken);
122
123 var multi = await connection.QueryMultipleAsync(command).ConfigureAwait(false);
124 var items = (await multi.ReadAsync<TaskDto>().ConfigureAwait(false)).ToList();
125 var totalCount = await multi.ReadSingleAsync<int>().ConfigureAwait(false);
127 }
128
129 private SqliteConnection CreateConnection() => new(_connectionString);
130
131 private static string BuildWhereClause(TaskSearchRequest request)
132 {
133 var filters = new List<string>();
134
135 if (!string.IsNullOrWhiteSpace(request.Title))
136 {
137 filters.Add("t.Title LIKE '%' || @Title || '%'");
138 }
139
140 if (!string.IsNullOrWhiteSpace(request.Status))
141 {
142 filters.Add("t.Status = @Status");
143 }
144
145 if (!string.IsNullOrWhiteSpace(request.Priority))
146 {
147 filters.Add("t.Priority = @Priority");
148 }
149
150 if (request.AssignedTo.HasValue)
151 {
152 filters.Add("t.AssignedTo = @AssignedTo");
153 }
154
155 return filters.Count == 0 ? string.Empty : $"WHERE {string.Join(" AND ", filters)}";
156 }
157}
PagedResult es un DTO para devolver resultados de consultas paginadas.
TaskReadRepository es el repositorio de lectura para consultas de tarea optimizadas.
async Task< PagedResult< TaskDto > > SearchAsync(TaskSearchRequest request, CancellationToken cancellationToken=default)
async Task< TaskDto?> GetByIdAsync(Guid id, CancellationToken cancellationToken=default)
ITaskReadRepository es la abstracción para consultas de sólo lectura de tareas.
record TaskSearchRequest(string? Title=null, string? Status=null, string? Priority=null, Guid? AssignedTo=null, int Page=1, int PageSize=20, string SortBy="CreatedAt", string SortDirection="DESC")
TaskSearchRequest es el DTO de entrada para operaciones avanzadas de búsqueda de tareas.