forked from ddrilling/AsbCloudServer
186 lines
6.1 KiB
C#
186 lines
6.1 KiB
C#
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;
|
||
|
||
namespace AsbCloudInfrastructure.Repository
|
||
{
|
||
|
||
/// <summary>
|
||
/// CRUD сервис для работы с БД
|
||
/// </summary>
|
||
/// <typeparam name="TDto"></typeparam>
|
||
/// <typeparam name="TEntity"></typeparam>
|
||
public class CrudServiceBase<TDto, TEntity> : ICrudService<TDto>
|
||
where TDto : AsbCloudApp.Data.IId
|
||
where TEntity : class, IId
|
||
{
|
||
protected readonly IAsbCloudDbContext dbContext;
|
||
protected readonly DbSet<TEntity> dbSet;
|
||
protected readonly Func<IQueryable<TEntity>> GetQuery;
|
||
|
||
public CrudServiceBase(IAsbCloudDbContext context)
|
||
{
|
||
dbContext = context;
|
||
dbSet = context.Set<TEntity>();
|
||
GetQuery = () => dbSet;
|
||
}
|
||
|
||
public CrudServiceBase(IAsbCloudDbContext dbContext, ISet<string> includes)
|
||
{
|
||
this.dbContext = dbContext;
|
||
dbSet = dbContext.Set<TEntity>();
|
||
|
||
GetQuery = () =>
|
||
{
|
||
IQueryable<TEntity> query = dbSet;
|
||
foreach (var include in includes)
|
||
query = query.Include(include);
|
||
return query;
|
||
};
|
||
}
|
||
|
||
public CrudServiceBase(IAsbCloudDbContext context, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
|
||
{
|
||
dbContext = context;
|
||
dbSet = context.Set<TEntity>();
|
||
GetQuery = () => makeQuery(dbSet);
|
||
}
|
||
|
||
/// <inheritdoc/>
|
||
public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token = default)
|
||
{
|
||
var entities = await GetQuery()
|
||
//.OrderBy(e => e.Id)
|
||
.AsNoTracking()
|
||
.ToListAsync(token)
|
||
.ConfigureAwait(false);
|
||
var dtos = entities.Select(Convert).ToList();
|
||
return dtos;
|
||
}
|
||
|
||
/// <inheritdoc/>
|
||
public virtual async Task<TDto?> GetOrDefaultAsync(int id, CancellationToken token = default)
|
||
{
|
||
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 = default)
|
||
{
|
||
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 = default)
|
||
{
|
||
if (!items.Any())
|
||
return 0;
|
||
var entities = items.Select(i =>
|
||
{
|
||
var entity = Convert(i);
|
||
entity.Id = 0;
|
||
return entity;
|
||
});
|
||
var entries = new List<Microsoft.EntityFrameworkCore.ChangeTracking.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 = default)
|
||
{
|
||
var existingEntity = await dbSet
|
||
.AsNoTracking()
|
||
.FirstOrDefaultAsync(e => e.Id == item.Id, token)
|
||
.ConfigureAwait(false);
|
||
|
||
if (existingEntity is null)
|
||
return ICrudService<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)
|
||
{
|
||
var ids = dtos.Select(d => d.Id);
|
||
var existingEntities = await dbSet
|
||
.AsNoTracking()
|
||
.Where(d => ids.Contains(d.Id))
|
||
.Select(d => d.Id)
|
||
.ToListAsync(token)
|
||
.ConfigureAwait(false);
|
||
|
||
if (ids.Count() > existingEntities.Count)
|
||
return ICrudService<TDto>.ErrorIdNotFound;
|
||
|
||
foreach (var dto in dtos)
|
||
{
|
||
var entity = Convert(dto);
|
||
var entry = dbSet.Update(entity);
|
||
}
|
||
|
||
var affected = await dbContext.SaveChangesAsync(token);
|
||
return affected;
|
||
}
|
||
|
||
/// <inheritdoc/>
|
||
public virtual Task<int> DeleteAsync(int id, CancellationToken token = default)
|
||
{
|
||
var entity = dbSet
|
||
.AsNoTracking()
|
||
.FirstOrDefault(e => e.Id == id);
|
||
if (entity == default)
|
||
return Task.FromResult(ICrudService<TDto>.ErrorIdNotFound);
|
||
var entry = dbSet.Remove(entity);
|
||
var affected = dbContext.SaveChangesAsync(token);
|
||
entry.State = EntityState.Detached;
|
||
return affected;
|
||
}
|
||
|
||
protected virtual TDto Convert(TEntity src) => src.Adapt<TDto>();
|
||
|
||
protected virtual TEntity Convert(TDto src) => src.Adapt<TEntity>();
|
||
}
|
||
#nullable disable
|
||
}
|