Allgemeiner Rat für .NET Backend Junior [geschlossen]C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Allgemeiner Rat für .NET Backend Junior [geschlossen]

Post by Anonymous »

Ich bin ein Junior .NET -Backend -Entwickler, ich habe jetzt ein paar Projekte durchgeführt und ich möchte wissen, welche allgemeinen Rat ich möglicherweise verpasst habe, da ich Architektur und Best Practices lernen musste, während ich Merkmale unter sehr kurzen Fristen kodieren musste. Service).
I implementiert Ergebnis Muster- und Basisdienste und Repositories.[Entity, Controller, Service, Repository]
< /code>
Entität: < /p>
[Table("parches")]
public class Parche
: _BaseEntity
{
[Required]
[StringLength(100)]
[Column("nombre")]
public string Nombre { get; set; } = null!;

[StringLength(500)]
[Column("descripcion")]
public string? Descripcion { get; set; }

[StringLength(200)]
[Column("ubicacion")]
public string? Ubicacion { get; set; }

[Column("capacidad")]
public int? Capacidad { get; set; }

[Column("precio")]
[Precision(10, 2)]
public decimal? Precio { get; set; }

[Column("portada_url")]
[StringLength(500)]
public string? PortadaUrl { get; set; }

[Column("latitud")]
[Precision(18, 15)]
public decimal? Latitud { get; set; }

[Column("estado")]
public EstadoParche Estado { get; set; } = EstadoParche.Creado;

[Required]
[Column("fecha_inicio")]
public DateTime FechaInicio { get; set; }

[Required]
[Column("fecha_fin")]
public DateTime FechaFin { get; set; }

[Required]
[Column("fecha_creacion")]
public DateTime FechaCreacion { get; set; } = DateTime.UtcNow;

[Column("ultima_actualizacion")]
public DateTime? UltimaActualizacion { get; set; }

public virtual ICollection
? Horarios { get; set; }
}
< /code>
Controller: < /p>
[ApiController]
[Route("api/[controller]")]
public class ParcheController(IParcheService parcheService) : ControllerBase
{
protected readonly IParcheService _parcheService = parcheService;

[HttpGet]
public async Task ListParches()
{
IResult result = await _parcheService.GetProjectedOrderedAsync(parche => parche.Nombre, true);

return result.ToHttpResponse();
}

[HttpGet("{id}")]
public async Task GetParcheById(Guid id)
{
IResult result = await _parcheService.GetProjectedByIdAsync(id);

return result.ToHttpResponse();
}

[HttpPost]
public async Task CreateParche([FromBody] CreateParcheDto parcheDto)
{
IResult result = await _parcheService.CreateFromDto(parcheDto);

return result.ToHttpResponse();
}

[HttpPut("{id}")]
public async Task UpdateParche(Guid id, [FromBody] UpdateParcheDto parcheDto)
{
IResult result = await _parcheService.UpdateFromDto(id, parcheDto);

return result.ToHttpResponse();
}

[HttpDelete("{id}")]
public async Task DeleteParche(Guid id)
{
IResult result = await this._parcheService.DeleteAsync(id);

return result.ToHttpResponse();
}
}
< /code>
public class ParcheService : _BaseService, IParcheService
{
public ParcheService(_IBaseRepository repository, IMapper mapper) : base(repository, mapper)
{
}
}
< /code>
public class ParcheRepository : _BaseRepository, IParcheRepository
{
public ParcheRepository(ApplicationDbContext context, IMapper mapper) : base(context, mapper)
{
}
}
< /code>
Base repository (I like using projections for my queries):
public class _BaseRepository : _IBaseRepository where T : _BaseEntity where ID : notnull
{
protected readonly ApplicationDbContext _context;
protected readonly DbSet _dbSet;
protected readonly IMapper _mapper;

public _BaseRepository(ApplicationDbContext context, IMapper mapper)
{
_context = context;
_dbSet = context.Set();
_mapper = mapper;
}

public virtual async Task GetAllAsync()
{
return await _dbSet.ToListAsync();
}

public virtual async Task GetByIdAsync(ID id)
{
return await _dbSet.FindAsync(id);
}

public virtual async Task GetByIdWithIncludeAsync(ID id, string includeProperties)
{
IQueryable query = _dbSet;

foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}

return await query.FirstOrDefaultAsync(e => e.Id.Equals(id));
}

public virtual DbContext GetContext()
{
return _context;
}

public virtual async Task AddAsync(T entity)
{
await _dbSet.AddAsync(entity);
return entity;
}

public virtual Task UpdateAsync(T entity)
{
_dbSet.Attach(entity);
_context.Entry(entity).State = EntityState.Modified;
return Task.CompletedTask;
}

public virtual async Task DeleteAsync(ID id)
{
var entity = await GetByIdAsync(id);
if (entity != null)
{
_dbSet.Remove(entity);
}
}

public virtual async Task FindAsync(Expression predicate)
{
return await _dbSet.Where(predicate).ToListAsync();
}

public virtual async Task ExistsAsync(ID id)
{
return await _dbSet.AnyAsync(e => e.Id.Equals(id));
}

public virtual async Task SaveChangesAsync()
{
await _context.SaveChangesAsync();
}

///
/// Consulta proyectada a un DTO específico para mejorar la eficiencia.
/// Solo selecciona los campos necesarios para el DTO.
///
/// Tipo del DTO al que se proyectará la entidad
///
Expresión de filtro opcional
/// Colección de DTOs proyectados
public virtual async Task GetProjectedAsync(Expression? predicate = null)
{
IQueryable query = _dbSet;

if (predicate != null)
query = query.Where(predicate);

return await query
.ProjectTo(_mapper.ConfigurationProvider)
.ToListAsync();
}

///
/// Obtiene un DTO proyectado por ID
///
/// Tipo del DTO
/// ID de la entidad
/// DTO proyectado
public virtual async Task GetProjectedByIdAsync(ID id)
{
return await _dbSet
.Where(e => e.Id.Equals(id))
.ProjectTo(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync();
}

///
/// Consulta proyectada con paginación
///
/// Tipo del DTO
/// Número de página (comienza en 1)
/// Tamaño de página
/// Expresión de filtro opcional
/// Colección paginada de DTOs
public virtual async Task GetProjectedPagedAsync(
int page,
int pageSize,
Expression? predicate = null)
{
IQueryable query = _dbSet;

if (predicate != null)
query = query.Where(predicate);

var totalCount = await query.CountAsync();

var items = await query
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ProjectTo(_mapper.ConfigurationProvider)
.ToListAsync();

return (items, totalCount);
}

///
/// Consulta proyectada con ordenamiento
///
/// Tipo del DTO
/// Tipo de la propiedad por la que se ordenará
/// Expresión de ordenamiento
/// Verdadero para ordenar ascendente, falso para descendente
/// Expresión de filtro opcional
/// Colección ordenada de DTOs
public virtual async Task GetProjectedOrderedAsync(
Expression orderBy,
bool ascending = true,
Expression? predicate = null)
{
IQueryable query = _dbSet;

if (predicate != null)
query = query.Where(predicate);

query = ascending ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);

return await query
.ProjectTo(_mapper.ConfigurationProvider)
.ToListAsync();
}
}
< /code>
Base service:
public class _BaseService : _IBaseService
where T : _BaseEntity
where ID : notnull
{
protected readonly _IBaseRepository _repository;
protected readonly IMapper _mapper;

public _BaseService(_IBaseRepository repository, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}

public virtual async Task GetAllAsync()
{
try
{
var entities = await _repository.GetAllAsync();

if (entities == null || !entities.Any())
return Result.NotFound("No se encontraron registros.");

return Result.Success(entities);
}
catch (Exception ex)
{
return Result.Failure("Error al obtener los registros.", ex.Message);
}
}

public virtual async Task GetByIdAsync(ID id)
{
try
{
var entity = await _repository.GetByIdAsync(id);

if (entity == null)
return Result.NotFound($"No se encontró el registro con Id: {id}");

return Result.Success(entity);
}
catch (Exception ex)
{
return Result.Failure($"Error al obtener el registro con Id: {id}", ex.Message);
}
}

public virtual async Task CreateAsync(T entity)
{
try
{
var result = await _repository.AddAsync(entity);
await _repository.SaveChangesAsync();

return Result.Success(result, "Registro creado exitosamente.");
}
catch (Exception ex)
{
return Result.Failure("Error al crear el registro.", ex.Message);
}
}

public virtual async Task UpdateAsync(T entity)
{
try
{
var exists = await _repository.ExistsAsync(entity.Id);
if (!exists)
return Result.NotFound($"No se encontró el registro con Id: {entity.Id}");

await _repository.UpdateAsync(entity);
await _repository.SaveChangesAsync();

return Result.Success(entity, "Registro actualizado exitosamente.");
}
catch (Exception ex)
{
return Result.Failure($"Error al actualizar el registro con Id: {entity.Id}", ex.Message);
}
}

public virtual async Task DeleteAsync(ID id)
{
try
{
var entity = await _repository.GetByIdAsync(id);
if (entity == null)
return Result.NotFound($"No se encontró el registro con Id: {id}");

await _repository.DeleteAsync(id);
await _repository.SaveChangesAsync();

return Result.Success();
}
catch (Exception ex)
{
return Result.Failure($"Error al eliminar el registro con Id: {id}", ex.Message);
}
}

public virtual async Task FindAsync(Expression predicate)
{
try
{
var entities = await _repository.FindAsync(predicate);

if (entities == null || !entities.Any())
return Result.NotFound("No se encontraron registros con los criterios especificados.");

return Result.Success(entities);
}
catch (Exception ex)
{
return Result.Failure("Error al buscar registros.", ex.Message);
}
}

public virtual async Task ExistsAsync(ID id)
{
try
{
var exists = await _repository.ExistsAsync(id);

return Result.Success(exists);
}
catch (Exception ex)
{
return Result.Failure($"Error al verificar la existencia del registro con Id: {id}", ex.Message);
}
}

public virtual async Task GetProjectedByIdAsync(ID id)
{
try
{
TDto? result = await this._repository.GetProjectedByIdAsync(id);

if (result == null) return Result.NotFound($"No se ha encontrado el registro con id: {id}");

return Result.Success(result);
}
catch (Exception ex)
{
Console.Write(ex.Message);
return Result.Failure($"Error obteniendo el registro con id: {id}");
}
}

public virtual async Task GetProjectedAsync(Expression? predicate = null)
{
try
{
IEnumerable result = await _repository.GetProjectedAsync(predicate);

if (result == null || !result.Any())
return Result.NotFound("No se encontraron registros con los criterios especificados.");

return Result.Success(result);
}
catch (Exception ex)
{
Console.Write(ex.Message);
return Result.Failure("Error obteniendo los registros proyectados", ex.Message);
}
}

public virtual async Task GetProjectedPagedAsync(int page, int pageSize, Expression? predicate = null)
{
try
{
var result = await _repository.GetProjectedPagedAsync(page, pageSize, predicate);

if (result.Items == null || !result.Items.Any())
return Result.Failure("No se encontraron registros con los criterios especificados.");

return Result.Failure(result);
}
catch (Exception ex)
{
Console.Write(ex.Message);
return Result.Failure("Error obteniendo los registros paginados", ex.Message);
}
}

public virtual async Task GetProjectedOrderedAsync(Expression orderBy, bool ascending = true, Expression? predicate = null)
{
try
{
IEnumerable result = await _repository.GetProjectedOrderedAsync(orderBy, ascending, predicate);

if (result == null || !result.Any())
return Result.NotFound("No se encontraron registros con los criterios especificados.");

return Result.Success(result);
}
catch (Exception ex)
{
Console.Write(ex.Message);
return Result.Failure("Error obteniendo los registros ordenados", ex.Message);
}
}

public virtual async Task CreateFromDto(TCreateDto createDto)
{
try
{
T entity = _mapper.Map(createDto);

T createdEntity = await _repository.AddAsync(entity);
await _repository.SaveChangesAsync();

TShowDto responseDto = _mapper.Map(createdEntity);
return Result.Success(responseDto);
}
catch (Exception ex)
{
Console.Write(ex.Message);
return Result.Failure("Error creando registro");
}
}

public virtual async Task UpdateFromDto(ID entityId, TUpdateDto updateDto)
{
try
{
IResult entityResult = await GetByIdAsync(entityId);
if (!entityResult.Successful.GetValueOrDefault()) return Result.Failure("Error actualizando registro");
T entity = entityResult.Data;

_mapper.Map(updateDto, entity);

await _repository.UpdateAsync(entity);

await _repository.SaveChangesAsync();

TShowDto responseDto = _mapper.Map(entity);
return Result.Success(responseDto);
}
catch (Exception ex)
{
Console.Write(ex.Message);
return Result.Failure("Error creando registro");
}
}
}
< /code>
I just would like to read some advice about general practices and if I'm doing something wrong.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post