196 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			196 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using Dapper; | ||
|  | using GestionIntegral.Api.Models.Radios; | ||
|  | using Microsoft.Extensions.Logging; | ||
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Data; | ||
|  | using System.Linq; | ||
|  | using System.Text; | ||
|  | using System.Threading.Tasks; | ||
|  | 
 | ||
|  | namespace GestionIntegral.Api.Data.Repositories.Radios | ||
|  | { | ||
|  |     public class CancionRepository : ICancionRepository | ||
|  |     { | ||
|  |         private readonly DbConnectionFactory _cf; | ||
|  |         private readonly ILogger<CancionRepository> _log; | ||
|  | 
 | ||
|  |         public CancionRepository(DbConnectionFactory cf, ILogger<CancionRepository> log) | ||
|  |         { | ||
|  |             _cf = cf; | ||
|  |             _log = log; | ||
|  |         } | ||
|  | 
 | ||
|  |         private string SelectWithAlias() => @"
 | ||
|  |             SELECT  | ||
|  |                 Id, Tema, CompositorAutor, Interprete, Sello, Placa, Pista, Introduccion,  | ||
|  |                 Ritmo AS IdRitmo, -- Mapear columna Ritmo a propiedad IdRitmo del modelo Cancion | ||
|  |                 Formato, Album | ||
|  |             FROM dbo.rad_dtCanciones";
 | ||
|  | 
 | ||
|  | 
 | ||
|  |         public async Task<IEnumerable<Cancion>> GetAllAsync(string? temaFilter, string? interpreteFilter, int? idRitmoFilter) | ||
|  |         { | ||
|  |             var sqlBuilder = new StringBuilder(SelectWithAlias()); | ||
|  |             sqlBuilder.Append(" WHERE 1=1"); | ||
|  |             var parameters = new DynamicParameters(); | ||
|  | 
 | ||
|  |             if (!string.IsNullOrWhiteSpace(temaFilter)) | ||
|  |             { | ||
|  |                 sqlBuilder.Append(" AND Tema LIKE @TemaParam"); | ||
|  |                 parameters.Add("TemaParam", $"%{temaFilter}%"); | ||
|  |             } | ||
|  |             if (!string.IsNullOrWhiteSpace(interpreteFilter)) | ||
|  |             { | ||
|  |                 sqlBuilder.Append(" AND Interprete LIKE @InterpreteParam"); | ||
|  |                 parameters.Add("InterpreteParam", $"%{interpreteFilter}%"); | ||
|  |             } | ||
|  |             if (idRitmoFilter.HasValue) | ||
|  |             { | ||
|  |                 sqlBuilder.Append(" AND Ritmo = @IdRitmoParam"); // La columna en DB es "Ritmo" | ||
|  |                 parameters.Add("IdRitmoParam", idRitmoFilter.Value); | ||
|  |             } | ||
|  |             sqlBuilder.Append(" ORDER BY Tema, Interprete;"); | ||
|  | 
 | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 return await connection.QueryAsync<Cancion>(sqlBuilder.ToString(), parameters); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error al obtener todas las Canciones."); | ||
|  |                 return Enumerable.Empty<Cancion>(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<Cancion?> GetByIdAsync(int id) | ||
|  |         { | ||
|  |             var sql = SelectWithAlias() + " WHERE Id = @IdParam"; | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 return await connection.QuerySingleOrDefaultAsync<Cancion>(sql, new { IdParam = id }); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error al obtener Canción por ID: {IdCancion}", id); | ||
|  |                 return null; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> ExistsByTemaAndInterpreteAsync(string tema, string interprete, int? excludeId = null) | ||
|  |         { | ||
|  |             // La unicidad puede ser más compleja si se consideran otros campos como Álbum. | ||
|  |             // Por ahora, un ejemplo simple. | ||
|  |             var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.rad_dtCanciones WHERE Tema = @TemaParam AND Interprete = @InterpreteParam"); | ||
|  |             var parameters = new DynamicParameters(); | ||
|  |             parameters.Add("TemaParam", tema); | ||
|  |             parameters.Add("InterpreteParam", interprete); | ||
|  |             if (excludeId.HasValue) | ||
|  |             { | ||
|  |                 sqlBuilder.Append(" AND Id != @ExcludeIdParam"); | ||
|  |                 parameters.Add("ExcludeIdParam", excludeId.Value); | ||
|  |             } | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 return await connection.ExecuteScalarAsync<bool>(sqlBuilder.ToString(), parameters); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error en ExistsByTemaAndInterpreteAsync. Tema: {Tema}, Interprete: {Interprete}", tema, interprete); | ||
|  |                 return true; // Asumir que existe en caso de error | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  | 
 | ||
|  |         public async Task<Cancion?> CreateAsync(Cancion nuevaCancion /*, int idUsuario, IDbTransaction transaction */) | ||
|  |         { | ||
|  |             // El modelo Cancion usa IdRitmo, pero la tabla rad_dtCanciones usa la columna "Ritmo" para el FK a rad_dtRitmos.Id | ||
|  |             const string sqlInsert = @"
 | ||
|  |                 INSERT INTO dbo.rad_dtCanciones (Tema, CompositorAutor, Interprete, Sello, Placa, Pista, Introduccion, Ritmo, Formato, Album) | ||
|  |                 OUTPUT INSERTED.Id, INSERTED.Tema, INSERTED.CompositorAutor, INSERTED.Interprete, INSERTED.Sello, INSERTED.Placa,  | ||
|  |                        INSERTED.Pista, INSERTED.Introduccion, INSERTED.Ritmo AS IdRitmo, INSERTED.Formato, INSERTED.Album | ||
|  |                 VALUES (@Tema, @CompositorAutor, @Interprete, @Sello, @Placa, @Pista, @Introduccion, @IdRitmo, @Formato, @Album);";
 | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 // El objeto nuevaCancion tiene la propiedad IdRitmo, que Dapper mapeará al parámetro @IdRitmo | ||
|  |                 return await connection.QuerySingleAsync<Cancion>(sqlInsert, nuevaCancion); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error al crear Canción: {Tema} por {Interprete}", nuevaCancion.Tema, nuevaCancion.Interprete); | ||
|  |                 return null; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> UpdateAsync(Cancion cancionAActualizar /*, int idUsuario, IDbTransaction transaction */) | ||
|  |         { | ||
|  |             // Similar a Create, la columna en DB es "Ritmo" | ||
|  |             const string sqlUpdate = @"
 | ||
|  |                 UPDATE dbo.rad_dtCanciones SET  | ||
|  |                     Tema = @Tema, CompositorAutor = @CompositorAutor, Interprete = @Interprete, Sello = @Sello, | ||
|  |                     Placa = @Placa, Pista = @Pista, Introduccion = @Introduccion, Ritmo = @IdRitmo,  | ||
|  |                     Formato = @Formato, Album = @Album | ||
|  |                 WHERE Id = @Id;";
 | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 var rowsAffected = await connection.ExecuteAsync(sqlUpdate, cancionAActualizar); | ||
|  |                 return rowsAffected == 1; | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error al actualizar Canción ID: {IdCancion}", cancionAActualizar.Id); | ||
|  |                 return false; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<bool> DeleteAsync(int id /*, int idUsuario, IDbTransaction transaction */) | ||
|  |         { | ||
|  |             // IsInUseAsync no se implementó porque no hay dependencias directas obvias que impidan borrar una canción | ||
|  |             // (a menos que las listas generadas se guarden y referencien IDs de canciones). | ||
|  |             const string sqlDelete = "DELETE FROM dbo.rad_dtCanciones WHERE Id = @IdParam"; | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 var rowsAffected = await connection.ExecuteAsync(sqlDelete, new { IdParam = id }); | ||
|  |                 return rowsAffected == 1; | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error al eliminar Canción ID: {IdCancion}", id); | ||
|  |                 return false; | ||
|  |             } | ||
|  |         } | ||
|  |         // IsInUseAsync podría ser relevante si las listas generadas referencian el Id de la canción | ||
|  |         // Por ahora, lo omitimos. | ||
|  |         public Task<bool> IsInUseAsync(int id) | ||
|  |         { | ||
|  |             _log.LogWarning("IsInUseAsync no implementado para CancionRepository."); | ||
|  |             return Task.FromResult(false); // Asumir que no está en uso por ahora | ||
|  |         } | ||
|  | 
 | ||
|  |         public async Task<IEnumerable<Cancion>> GetRandomCancionesAsync(int count) | ||
|  |         { | ||
|  |             // El modelo Cancion tiene la propiedad "Ritmo" que es el IdRitmo. | ||
|  |             // El SelectWithAlias no es necesario aquí si solo tomamos las columnas que ya tiene Cancion. | ||
|  |             // Si el modelo Cancion no tuviera la propiedad Ritmo (IdRitmo), entonces necesitarías el alias. | ||
|  |             // Por simplicidad, y dado que el modelo Cancion sí tiene Ritmo (que es IdRitmo), no necesitamos un alias específico aquí. | ||
|  |             var sql = $"SELECT TOP ({count}) Id, Tema, CompositorAutor, Interprete, Sello, Placa, Pista, Introduccion, Ritmo, Formato, Album FROM dbo.rad_dtCanciones ORDER BY NEWID()"; | ||
|  |             try | ||
|  |             { | ||
|  |                 using var connection = _cf.CreateConnection(); | ||
|  |                 // Dapper mapeará la columna "Ritmo" de la BD a la propiedad "Ritmo" del modelo Cancion. | ||
|  |                 return await connection.QueryAsync<Cancion>(sql); | ||
|  |             } | ||
|  |             catch (Exception ex) | ||
|  |             { | ||
|  |                 _log.LogError(ex, "Error al obtener {Count} canciones aleatorias.", count); | ||
|  |                 return Enumerable.Empty<Cancion>(); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } |