DD.WellWorkover.Cloud/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs
2024-08-19 10:01:07 +05:00

188 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Exceptions;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace AsbCloudInfrastructure.Repository;
/// <summary>
/// CRUD сервис для работы с БД
/// </summary>
/// <typeparam name="TDto"></typeparam>
/// <typeparam name="TEntity"></typeparam>
public class CrudRepositoryBase<TDto, TEntity> : QueryContainer<TEntity>, ICrudRepository<TDto>
where TDto : AsbCloudApp.Data.IId
where TEntity : class, IId
{
public CrudRepositoryBase(IAsbCloudDbContext context)
: base(context)
{ }
public CrudRepositoryBase(IAsbCloudDbContext context, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
: base(context, makeQuery)
{ }
/// <inheritdoc/>
public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token)
{
var entities = await GetQuery()
.AsNoTracking()
.ToListAsync(token)
.ConfigureAwait(false);
var dtos = entities.Select(Convert).ToList();
return dtos;
}
/// <inheritdoc/>
public virtual async Task<TDto?> GetOrDefaultAsync(int id, CancellationToken token)
{
var entity = await GetQuery()
.AsNoTracking()
.FirstOrDefaultAsync(e => e.Id == id, token)
.ConfigureAwait(false);
if (entity == default)
return default;
var dto = Convert(entity);
return dto;
}
/// <inheritdoc/>
public virtual TDto? GetOrDefault(int id)
{
var entity = GetQuery()
.AsNoTracking()
.FirstOrDefault(e => e.Id == id);
if (entity == default)
return default;
var dto = Convert(entity);
return dto;
}
/// <inheritdoc/>
public virtual async Task<int> InsertAsync(TDto item, CancellationToken token)
{
var entity = Convert(item);
entity.Id = 0;
var entry = dbSet.Add(entity);
await dbContext.SaveChangesAsync(token);
entry.State = EntityState.Detached;
return entity.Id;
}
/// <inheritdoc/>
public virtual async Task<int> InsertRangeAsync(IEnumerable<TDto> items, CancellationToken token)
{
if (!items.Any())
return 0;
var entities = items.Select(i =>
{
var entity = Convert(i);
entity.Id = 0;
return entity;
});
var entries = new List<EntityEntry>(items.Count());
foreach (var entity in entities)
{
var entry = dbSet.Add(entity);
entries.Add(entry);
}
var affected = await dbContext.SaveChangesAsync(token);
entries.ForEach(e => e.State = EntityState.Detached);
return affected;
}
/// <inheritdoc/>
public virtual async Task<int> UpdateAsync(TDto item, CancellationToken token)
{
var existingEntity = await dbSet
.AsNoTracking()
.FirstOrDefaultAsync(e => e.Id == item.Id, token)
.ConfigureAwait(false);
if (existingEntity is null)
return ICrudRepository<TDto>.ErrorIdNotFound;
var entity = Convert(item);
var entry = dbSet.Update(entity);
await dbContext.SaveChangesAsync(token);
entry.State = EntityState.Detached;
return entry.Entity.Id;
}
public virtual async Task<int> UpdateRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
{
if (!dtos.Any())
return 0;
var ids = dtos
.Select(o => o.Id)
.Distinct()
.ToArray();
if (ids.Any(id => id == default))
throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id");
if (ids.Length != dtos.Count())
throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id");
var existingEntitiesCount = await dbContext.Set<TEntity>()
.Where(o => ids.Contains(o.Id))
.CountAsync(token);
if (ids.Length != existingEntitiesCount)
throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД");
var entities = dtos.Select(Convert);
var entries = entities.Select(entity => dbContext.Set<TEntity>().Update(entity)).ToList();
var affected = await dbContext.SaveChangesAsync(token);
entries.ForEach(entry => entry.State = EntityState.Detached);
return affected;
}
/// <inheritdoc/>
public virtual Task<int> DeleteAsync(int id, CancellationToken token)
{
var entity = dbSet
.AsNoTracking()
.FirstOrDefault(e => e.Id == id);
if (entity == default)
return Task.FromResult(ICrudRepository<TDto>.ErrorIdNotFound);
dbSet.Remove(entity);
var affected = dbContext.SaveChangesAsync(token);
return affected;
}
public virtual async Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token)
{
if (!ids.Any())
return 0;
var countExistingEntities = await dbSet
.Where(d => ids.Contains(d.Id))
.CountAsync(token);
if (ids.Count() > countExistingEntities)
return ICrudRepository<TDto>.ErrorIdNotFound;
var entities = dbContext.Set<TEntity>().Where(e => ids.Contains(e.Id));
dbContext.Set<TEntity>().RemoveRange(entities);
return await dbContext.SaveChangesAsync(token);
}
protected virtual TDto Convert(TEntity src) => src.Adapt<TDto>();
protected virtual TEntity Convert(TDto src) => src.Adapt<TEntity>();
}