fix and refactor WellService.

This commit is contained in:
Фролов 2021-12-22 11:41:18 +05:00
parent a9f03c2ecf
commit c5ed3c467f
12 changed files with 147 additions and 66 deletions

View File

@ -2,11 +2,15 @@
namespace AsbCloudApp.Data namespace AsbCloudApp.Data
{ {
public class TelemetryDto : IId public class TelemetryBaseDto : IId
{ {
public int Id { get; set; } public int Id { get; set; }
public string RemoteUid { get; set; } public string RemoteUid { get; set; }
public TelemetryInfoDto Info { get; set; } public TelemetryInfoDto Info { get; set; }
}
public class TelemetryDto : TelemetryBaseDto
{
public int? IdWell { get; set; } public int? IdWell { get; set; }
public WellInfoDto Well { get; set; } public WellInfoDto Well { get; set; }
} }

View File

@ -20,7 +20,7 @@ namespace AsbCloudApp.Data
public int IdState { get; set; } public int IdState { get; set; }
public DateTime LastTelemetryDate { get; set; } public DateTime LastTelemetryDate { get; set; }
public int? IdTelemetry { get; set; } public int? IdTelemetry { get; set; }
public TelemetryDto Telemetry { get; set; } public TelemetryBaseDto Telemetry { get; set; }
public IEnumerable<CompanyDto> Companies { get; set; } public IEnumerable<CompanyDto> Companies { get; set; }
} }
} }

View File

@ -7,7 +7,7 @@ namespace AsbCloudApp.Services
public interface ICrudService<Tdto> public interface ICrudService<Tdto>
where Tdto : Data.IId where Tdto : Data.IId
{ {
List<string> Includes { get; } ISet<string> Includes { get; }
Task<int> InsertAsync(Tdto newItem, CancellationToken token = default); Task<int> InsertAsync(Tdto newItem, CancellationToken token = default);
Task<int> InsertRangeAsync(IEnumerable<Tdto> newItems, CancellationToken token = default); Task<int> InsertRangeAsync(IEnumerable<Tdto> newItems, CancellationToken token = default);
Task<IEnumerable<Tdto>> GetAllAsync(CancellationToken token = default); Task<IEnumerable<Tdto>> GetAllAsync(CancellationToken token = default);

33
AsbCloudApp/Tree.cs Normal file
View File

@ -0,0 +1,33 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AsbCloudApp
{
public class Tree<T> : Dictionary<T, Tree<T>>
{
public Tree()
{}
public Tree(T key, Tree<T> node = null)
{
Add(key, node);
}
public Tree(Tree<T> other)
:base(other)
{}
public Tree(IEnumerable<T> keys)
{
foreach (var key in keys)
Add(key);
}
public void Add(T key) => Add(key, null);
}
}

View File

@ -437,27 +437,6 @@ namespace AsbCloudDb.Model
}); });
}); });
//modelBuilder.Entity<ModeType>(entity =>
//{
// entity.HasData(new List<ModeType>{
// new ModeType{ Id = 1, Caption = "Нагрузка" },
// new ModeType{ Id = 2, Caption = "Дифф. давление" },
// new ModeType{ Id = 3, Caption = "Момент на ВСП" },
// new ModeType{ Id = 4, Caption = "Обороты на ВСП" },
// new ModeType{ Id = 5, Caption = "Расход" }
// });
//});
}
public IQueryable<Well> GetWellsForCompany(int idCompany)
{
return from well in Wells
.Include(w => w.RelationCompaniesWells)
.ThenInclude(r => r.Company)
.Include(w => w.Cluster)
.ThenInclude(c => c.Deposit)
where well.RelationCompaniesWells.Any(c => c.IdCompany == idCompany)
select well;
} }
public async Task<(DateTime From, DateTime To)> GetDatesRangeAsync<TEntity>(int idTelemetry, public async Task<(DateTime From, DateTime To)> GetDatesRangeAsync<TEntity>(int idTelemetry,

View File

@ -64,7 +64,7 @@ namespace AsbCloudInfrastructure.Services
public async Task<IEnumerable<ClusterDto>> GetClustersAsync(int idCompany, public async Task<IEnumerable<ClusterDto>> GetClustersAsync(int idCompany,
CancellationToken token = default) CancellationToken token = default)
{ {
var entities = await db.GetWellsForCompany(idCompany) var entities = await GetWellsForCompany(idCompany)
.Select(e => e.Cluster) .Select(e => e.Cluster)
.Distinct() .Distinct()
.AsNoTracking() .AsNoTracking()
@ -79,7 +79,7 @@ namespace AsbCloudInfrastructure.Services
public async Task<IEnumerable<ClusterDto>> GetClustersAsync(int idCompany, public async Task<IEnumerable<ClusterDto>> GetClustersAsync(int idCompany,
int depositId, CancellationToken token = default) int depositId, CancellationToken token = default)
{ {
var entities = await db.GetWellsForCompany(idCompany) var entities = await GetWellsForCompany(idCompany)
.Select(e => e.Cluster) .Select(e => e.Cluster)
.Where(e => e.IdDeposit == depositId) .Where(e => e.IdDeposit == depositId)
.Distinct() .Distinct()
@ -95,7 +95,7 @@ namespace AsbCloudInfrastructure.Services
public async Task<IEnumerable<WellDto>> GetWellsAsync(int idCompany, public async Task<IEnumerable<WellDto>> GetWellsAsync(int idCompany,
int idCluster, CancellationToken token = default) int idCluster, CancellationToken token = default)
{ {
var entities = await db.GetWellsForCompany(idCompany) var entities = await GetWellsForCompany(idCompany)
.Where(e => e.IdCluster == idCluster) .Where(e => e.IdCluster == idCluster)
.AsNoTracking() .AsNoTracking()
.ToListAsync(token) .ToListAsync(token)
@ -121,6 +121,16 @@ namespace AsbCloudInfrastructure.Services
.GroupBy(c => c.Key.Deposit); .GroupBy(c => c.Key.Deposit);
} }
private IQueryable<Well> GetWellsForCompany(int idCompany)
{
return db.Wells
.Include(w => w.RelationCompaniesWells)
.ThenInclude(r => r.Company)
.Include(w => w.Cluster)
.ThenInclude(c => c.Deposit)
.Where(w => w.RelationCompaniesWells.Any(c => c.IdCompany == idCompany));
}
private IEnumerable<DepositDto> CreateDepositDto(IEnumerable<IGrouping<Deposit,IGrouping<Cluster, Well>>>gDepositEntities) private IEnumerable<DepositDto> CreateDepositDto(IEnumerable<IGrouping<Deposit,IGrouping<Cluster, Well>>>gDepositEntities)
{ {
return gDepositEntities.Select(gDeposit => new DepositDto return gDepositEntities.Select(gDeposit => new DepositDto

View File

@ -1,3 +1,4 @@
using AsbCloudApp;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache; using AsbCloudInfrastructure.Services.Cache;
@ -18,7 +19,7 @@ namespace AsbCloudInfrastructure.Services
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly CacheDb cacheDb; private readonly CacheDb cacheDb;
public List<string> Includes { get; } = new (); public ISet<string> Includes { get; } = new SortedSet<string>();
protected CacheTable<TModel> Cache { protected CacheTable<TModel> Cache {
get { get {

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data; using AsbCloudApp;
using AsbCloudApp.Data;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using Mapster; using Mapster;
@ -18,7 +19,7 @@ namespace AsbCloudInfrastructure.Services
protected readonly IAsbCloudDbContext context; protected readonly IAsbCloudDbContext context;
protected readonly DbSet<TModel> dbSet; protected readonly DbSet<TModel> dbSet;
public List<string> Includes { get; } = new List<string>(); public ISet<string> Includes { get; } = new SortedSet<string>();
public CrudServiceBase(IAsbCloudDbContext context) public CrudServiceBase(IAsbCloudDbContext context)
{ {

View File

@ -35,10 +35,8 @@ namespace AsbCloudInfrastructure.Services
{ {
cacheSetpoints = cacheDb.GetCachedTable<SetpointsRequest>( cacheSetpoints = cacheDb.GetCachedTable<SetpointsRequest>(
(AsbCloudDbContext)db, (AsbCloudDbContext)db,
new List<string> { nameof(SetpointsRequest.Author),
nameof(SetpointsRequest.Author), nameof(SetpointsRequest.Well));
nameof(SetpointsRequest.Well),
});
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
} }
@ -125,7 +123,6 @@ namespace AsbCloudInfrastructure.Services
return 1; return 1;
} }
public SetpointsRequest Convert(SetpointsRequestDto src) public SetpointsRequest Convert(SetpointsRequestDto src)
{ {
var entity = src.Adapt<SetpointsRequest>(); var entity = src.Adapt<SetpointsRequest>();

View File

@ -16,9 +16,7 @@ namespace AsbCloudInfrastructure.Services
public class TelemetryService : ITelemetryService public class TelemetryService : ITelemetryService
{ {
private readonly CacheTable<Telemetry> cacheTelemetry; private readonly CacheTable<Telemetry> cacheTelemetry;
private readonly CacheTable<Well> cacheWells; private readonly CacheTable<Well> cacheWells;//TODO: use wellService insad of this
private readonly CacheTable<Cluster> cacheClusters;
private readonly CacheTable<Deposit> cacheDeposits;
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly ITelemetryTracker telemetryTracker; private readonly ITelemetryTracker telemetryTracker;
private readonly ITimeZoneService timeZoneService; private readonly ITimeZoneService timeZoneService;
@ -33,9 +31,12 @@ namespace AsbCloudInfrastructure.Services
CacheDb cacheDb) CacheDb cacheDb)
{ {
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db); cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
cacheWells = cacheDb.GetCachedTable<Well>((AsbCloudDbContext)db); cacheWells = cacheDb.GetCachedTable<Well>(
cacheClusters = cacheDb.GetCachedTable<Cluster>((AsbCloudDbContext)db); (AsbCloudDbContext)db,
cacheDeposits = cacheDb.GetCachedTable<Deposit>((AsbCloudDbContext)db); $"{nameof(Well.Cluster)}.{nameof(Cluster.Deposit)}",
nameof(Well.Telemetry),
$"{nameof(Well.RelationCompaniesWells)}.{nameof(RelationCompanyWell.Company)}",
nameof(Well.WellType));
this.db = db; this.db = db;
this.telemetryTracker = telemetryTracker; this.telemetryTracker = telemetryTracker;
this.timeZoneService = timeZoneService; this.timeZoneService = timeZoneService;
@ -186,20 +187,16 @@ namespace AsbCloudInfrastructure.Services
if (well is null) if (well is null)
return null; return null;
if (well.Latitude is not null && well.Longitude is not null) var latitude = well.Latitude ??
return (well.Latitude ?? default, well.Longitude??default); well.Cluster?.Latitude ??
well.Cluster?.Deposit?.Latitude;
var cluster = await cacheClusters.FirstOrDefaultAsync(c => c.Id == well.IdCluster, token) var longitude = well.Longitude ??
.ConfigureAwait(false); well.Cluster?.Longitude ??
well.Cluster?.Deposit?.Longitude;
if (cluster.Latitude is not null && cluster.Longitude is not null) if (latitude is not null && longitude is not null)
return (cluster.Latitude ?? default, cluster.Longitude ?? default); return ((double)latitude, (double)longitude);
var deposit = await cacheDeposits.FirstOrDefaultAsync(d => d.Id == cluster.IdDeposit, token)
.ConfigureAwait(false);
if (deposit.Latitude is not null && deposit.Longitude is not null)
return (deposit.Latitude ?? default, deposit.Longitude ?? default);
return null; return null;
} }

View File

@ -15,8 +15,7 @@ namespace AsbCloudInfrastructure.Services
{ {
private readonly CacheTable<User> cacheUsers; private readonly CacheTable<User> cacheUsers;
private readonly CacheTable<RelationUserUserRole> cacheRelationUserToRoles; private readonly CacheTable<RelationUserUserRole> cacheRelationUserToRoles;
public ISet<string> Includes { get; } = new SortedSet<string>();
public List<string> Includes { get; }
public IUserRoleService RoleService { get; } public IUserRoleService RoleService { get; }
public UserService(IAsbCloudDbContext context, CacheDb cacheDb, IUserRoleService roleService) public UserService(IAsbCloudDbContext context, CacheDb cacheDb, IUserRoleService roleService)

View File

@ -3,7 +3,6 @@ using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache; using AsbCloudInfrastructure.Services.Cache;
using Mapster; using Mapster;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -14,14 +13,31 @@ namespace AsbCloudInfrastructure.Services
{ {
public class WellService : CrudCacheServiceBase<WellDto, Well>, IWellService public class WellService : CrudCacheServiceBase<WellDto, Well>, IWellService
{ {
private static readonly TypeAdapterConfig typeAdapterConfig = TypeAdapterConfig<WellDto, Well>
.NewConfig()
.Ignore(dst => dst.Cluster,
dst => dst.RelationCompaniesWells,
dst => dst.Telemetry,
dst => dst.WellComposites,
dst => dst.WellCompositeSrcs,
dst => dst.WellOperations,
dst => dst.WellType)
.Config;
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
private readonly CacheTable<RelationCompanyWell> cacheRelationCompaniesWells; private readonly CacheTable<RelationCompanyWell> cacheRelationCompaniesWells;
private readonly CacheTable<CompanyType> cacheCompanyWellTypes;
public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService) public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService)
:base(db, cacheDb) :base(db, cacheDb)
{ {
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
cacheRelationCompaniesWells = cacheDb.GetCachedTable<RelationCompanyWell>((AsbCloudDbContext)db, nameof(RelationCompanyWell.Company), nameof(RelationCompanyWell.Well)); cacheRelationCompaniesWells = cacheDb.GetCachedTable<RelationCompanyWell>((AsbCloudDbContext)db, nameof(RelationCompanyWell.Company), nameof(RelationCompanyWell.Well));
cacheCompanyWellTypes = cacheDb.GetCachedTable<CompanyType>((AsbCloudDbContext)db);
Includes.Add($"{nameof(Well.Cluster)}.{nameof(Cluster.Deposit)}");
Includes.Add(nameof(Well.Telemetry));
Includes.Add($"{nameof(Well.RelationCompaniesWells)}.{nameof(RelationCompanyWell.Company)}");
Includes.Add(nameof(Well.WellType));
} }
public DateTime GetLastTelemetryDate(int idWell) public DateTime GetLastTelemetryDate(int idWell)
@ -39,15 +55,36 @@ namespace AsbCloudInfrastructure.Services
{ {
var relations = await cacheRelationCompaniesWells var relations = await cacheRelationCompaniesWells
.WhereAsync(r => r.IdCompany == idCompany, token); .WhereAsync(r => r.IdCompany == idCompany, token);
var dtos = relations.Select(r => Convert(r.Well));
var wellsIds = relations.Select(r => r.IdWell);
var wells = await Cache.WhereAsync(w => wellsIds.Contains(w.Id));
var dtos = wells.Select(Convert);
return dtos; return dtos;
} }
public override Task<int> InsertAsync(WellDto newItem, CancellationToken token = default) public override async Task<int> InsertAsync(WellDto dto, CancellationToken token = default)
{ {
throw new NotImplementedException(); if (dto.IdWellType is < 1 or > 2)
implement this throw new ArgumentException("Тип скважины указан неправильно.", nameof(dto));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (dto.IdState is < 0 or > 2)
throw new ArgumentException("Текущее состояние работы скважины указано неправильно.", nameof(dto));
if (dto.Id != 0 && await Cache.ContainsAsync(w => w.Id == dto.Id, token))
throw new ArgumentException($"Нельзя повторно добавить скважину с id: {dto.Id}", nameof(dto));
var entity = Convert(dto);
var result = await Cache.InsertAsync(entity, token);
if (dto.Companies.Any())
{
var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = result.Id, IdCompany = c.Id });
await cacheRelationCompaniesWells.InsertAsync(newRelations, token);
}
return result.Id;
} }
public override Task<int> InsertRangeAsync(IEnumerable<WellDto> dtos, CancellationToken token) public override Task<int> InsertRangeAsync(IEnumerable<WellDto> dtos, CancellationToken token)
@ -69,7 +106,16 @@ namespace AsbCloudInfrastructure.Services
var entity = Convert(dto); var entity = Convert(dto);
var oldRelations = await cacheRelationCompaniesWells.FirstOrDefaultAsync(w => w.Id == idWell, token); var oldRelations = await cacheRelationCompaniesWells
.WhereAsync(r => r.IdWell == idWell, token);
if(dto.Companies.Count() != oldRelations.Count() ||
dto.Companies.Any(c => !oldRelations.Any(oldC => oldC.IdCompany == c.Id)))
{
await cacheRelationCompaniesWells.RemoveAsync(r => r.IdWell == idWell, token);
var newRelations = dto.Companies.Select(c=> new RelationCompanyWell {IdWell = idWell, IdCompany = c.Id });
await cacheRelationCompaniesWells.InsertAsync(newRelations, token);
}
var result = await Cache.UpsertAsync(entity, token); var result = await Cache.UpsertAsync(entity, token);
return result; return result;
@ -127,9 +173,21 @@ namespace AsbCloudInfrastructure.Services
return clusterWells.Select(w => w.Id); return clusterWells.Select(w => w.Id);
} }
protected override Well Convert(WellDto dto)
{
var entity = dto.Adapt<Well>(typeAdapterConfig);
//dto.WellType = entity.WellType?.Caption;
//dto.Cluster = entity.Cluster?.Caption;
//dto.Deposit = entity.Cluster?.Deposit?.Caption;
//dto.LastTelemetryDate = GetLastTelemetryDate(entity.Id);
//dto.Companies = GetCompanies(entity.Id);
return entity;
}
protected override WellDto Convert(Well entity) protected override WellDto Convert(Well entity)
{ {
var dto = base.Convert(entity); var dto = base.Convert(entity);
dto.WellType = entity.WellType?.Caption;
dto.Cluster = entity.Cluster?.Caption; dto.Cluster = entity.Cluster?.Caption;
dto.Deposit = entity.Cluster?.Deposit?.Caption; dto.Deposit = entity.Cluster?.Deposit?.Caption;
dto.LastTelemetryDate = GetLastTelemetryDate(entity.Id); dto.LastTelemetryDate = GetLastTelemetryDate(entity.Id);
@ -140,6 +198,8 @@ namespace AsbCloudInfrastructure.Services
private CompanyDto Convert(Company entity) private CompanyDto Convert(Company entity)
{ {
var dto = entity.Adapt<CompanyDto>(); var dto = entity.Adapt<CompanyDto>();
dto.CompanyTypeCaption = entity.CompanyType?.Caption
?? cacheCompanyWellTypes.FirstOrDefault(c => c.Id == entity.IdCompanyType).Caption;
return dto; return dto;
} }
} }