forked from ddrilling/AsbCloudServer
CrudService очищен от неиспользуемого кода.
CrudCacheService Адаптировано для новой схемы кеширования. Убраны extention методы для mapster.
This commit is contained in:
parent
570cec4162
commit
4db67113b4
@ -8,6 +8,6 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Well id in db
|
/// Well id in db
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int IdWell { get; set; }
|
int IdWell { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
|||||||
namespace AsbCloudApp.Services
|
namespace AsbCloudApp.Services
|
||||||
{
|
{
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сервис получения, добавления, изменения, удаления данных
|
/// Сервис получения, добавления, изменения, удаления данных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -14,9 +15,31 @@ namespace AsbCloudApp.Services
|
|||||||
where Tdto : Data.IId
|
where Tdto : Data.IId
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Включение связных данных
|
/// Код возврата ошибки: Id не найден в БД.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISet<string> Includes { get; }
|
public const int ErrorIdNotFound = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получение всех записей
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns>emptyList if nothing found</returns>
|
||||||
|
Task<IEnumerable<Tdto>> GetAllAsync(CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить запись по id
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns>null if not found</returns>
|
||||||
|
Task<Tdto?> GetAsync(int id, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить запись по id
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns>null if not found</returns>
|
||||||
|
Tdto? Get(int id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавление новой записи
|
/// Добавление новой записи
|
||||||
@ -24,7 +47,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="newItem"></param>
|
/// <param name="newItem"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns>Id новой записи</returns>
|
/// <returns>Id новой записи</returns>
|
||||||
Task<int> InsertAsync(Tdto newItem, CancellationToken token = default);
|
Task<int> InsertAsync(Tdto newItem, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавление нескольких записей
|
/// Добавление нескольких записей
|
||||||
@ -32,23 +55,7 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="newItems"></param>
|
/// <param name="newItems"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns>количество добавленных</returns>
|
/// <returns>количество добавленных</returns>
|
||||||
Task<int> InsertRangeAsync(IEnumerable<Tdto> newItems, CancellationToken token = default);
|
Task<int> InsertRangeAsync(IEnumerable<Tdto> newItems, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получение всех записей
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Obsolete("Небезопасный метод, может выполняться бесконечно долго")]
|
|
||||||
Task<IEnumerable<Tdto>> GetAllAsync(CancellationToken token = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить запись по id
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<Tdto?> GetAsync(int id, CancellationToken token = default);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Отредактировать запись
|
/// Отредактировать запись
|
||||||
@ -56,16 +63,16 @@ namespace AsbCloudApp.Services
|
|||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <param name="item"></param>
|
/// <param name="item"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns>если больше 0 - Id записи, если меньше 0 - код ошибки</returns>
|
||||||
Task<int> UpdateAsync(int id, Tdto item, CancellationToken token = default);
|
Task<int> UpdateAsync(int id, Tdto item, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить запись
|
/// Удалить запись
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns>если больше 0 - Id записи, если меньше 0 - код ошибки</returns>
|
||||||
Task<int> DeleteAsync(int id, CancellationToken token = default);
|
Task<int> DeleteAsync(int id, CancellationToken token);
|
||||||
}
|
}
|
||||||
#nullable disable
|
#nullable disable
|
||||||
}
|
}
|
@ -21,6 +21,6 @@ namespace AsbCloudApp.Services
|
|||||||
Task<IEnumerable<int>> GetClusterWellsIdsAsync(int idWell, CancellationToken token);
|
Task<IEnumerable<int>> GetClusterWellsIdsAsync(int idWell, CancellationToken token);
|
||||||
SimpleTimezoneDto GetTimezone(int idWell);
|
SimpleTimezoneDto GetTimezone(int idWell);
|
||||||
DatesRangeDto GetDatesRange(int idWell);
|
DatesRangeDto GetDatesRange(int idWell);
|
||||||
void EnshureTimezonesIsSet();
|
Task EnshureTimezonesIsSetAsync(CancellationToken token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,10 @@ namespace AsbCloudInfrastructure
|
|||||||
TypeAdapterConfig.GlobalSettings.Default.Config
|
TypeAdapterConfig.GlobalSettings.Default.Config
|
||||||
.ForType<TimeOnly, TimeDto>()
|
.ForType<TimeOnly, TimeDto>()
|
||||||
.MapWith((source) => new(source));
|
.MapWith((source) => new(source));
|
||||||
|
|
||||||
|
TypeAdapterConfig.GlobalSettings.Default.Config
|
||||||
|
.ForType<TimeOnly, TimeDto>()
|
||||||
|
.MapWith((source) => new(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||||
@ -98,12 +102,27 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IScheduleService, ScheduleService>();
|
services.AddTransient<IScheduleService, ScheduleService>();
|
||||||
|
|
||||||
// admin crud services:
|
// admin crud services:
|
||||||
services.AddTransient<ICrudService<TelemetryDto>, CrudServiceBase<TelemetryDto, Telemetry>>(); // может быть включен в сервис TelemetryService
|
services.AddTransient<ICrudService<TelemetryDto>, CrudServiceBase<TelemetryDto, Telemetry>>(s =>
|
||||||
|
new CrudCacheServiceBase<TelemetryDto, Telemetry>(
|
||||||
|
s.GetService<IAsbCloudDbContext>(),
|
||||||
|
dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService
|
||||||
services.AddTransient<ICrudService<DrillParamsDto>, DrillParamsService>();
|
services.AddTransient<ICrudService<DrillParamsDto>, DrillParamsService>();
|
||||||
services.AddTransient<ICrudService<DepositDto>, CrudCacheServiceBase<DepositDto, Deposit>>();
|
services.AddTransient<ICrudService<DepositDto>, CrudCacheServiceBase<DepositDto, Deposit>>(s =>
|
||||||
services.AddTransient<ICrudService<CompanyDto>, CrudCacheServiceBase<CompanyDto, Company>>();
|
new CrudCacheServiceBase<DepositDto, Deposit>(
|
||||||
|
s.GetService<IAsbCloudDbContext>(),
|
||||||
|
dbSet => dbSet.Include(d => d.Clusters)));
|
||||||
|
services.AddTransient<ICrudService<CompanyDto>, CrudCacheServiceBase<CompanyDto, Company>>(s =>
|
||||||
|
new CrudCacheServiceBase<CompanyDto, Company>(
|
||||||
|
s.GetService<IAsbCloudDbContext>(),
|
||||||
|
dbSet => dbSet.Include(c=>c.CompanyType)));
|
||||||
services.AddTransient<ICrudService<CompanyTypeDto>, CrudCacheServiceBase<CompanyTypeDto, CompanyType>>();
|
services.AddTransient<ICrudService<CompanyTypeDto>, CrudCacheServiceBase<CompanyTypeDto, CompanyType>>();
|
||||||
services.AddTransient<ICrudService<ClusterDto>, CrudCacheServiceBase<ClusterDto, Cluster>>(); // может быть включен в сервис ClusterService
|
services.AddTransient<ICrudService<ClusterDto>, CrudCacheServiceBase<ClusterDto, Cluster>>(s =>
|
||||||
|
new CrudCacheServiceBase<ClusterDto, Cluster>(
|
||||||
|
s.GetService<IAsbCloudDbContext>(),
|
||||||
|
dbSet => dbSet
|
||||||
|
.Include(c => c.Wells)
|
||||||
|
.Include(c => c.Deposit))); // может быть включен в сервис ClusterService
|
||||||
|
|
||||||
services.AddTransient<ICrudService<PermissionDto>, CrudCacheServiceBase<PermissionDto, Permission>>();
|
services.AddTransient<ICrudService<PermissionDto>, CrudCacheServiceBase<PermissionDto, Permission>>();
|
||||||
|
|
||||||
// TelemetryData services
|
// TelemetryData services
|
||||||
|
@ -26,6 +26,57 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
internal DateTime DateObsolete;
|
internal DateTime DateObsolete;
|
||||||
internal DateTime DateObsoleteTotal;
|
internal DateTime DateObsoleteTotal;
|
||||||
internal readonly SemaphoreSlim semaphore = new(1);
|
internal readonly SemaphoreSlim semaphore = new(1);
|
||||||
|
|
||||||
|
|
||||||
|
internal Dictionary<TKey, TEntity> GetData<TKey, TEntity>()
|
||||||
|
where TKey : notnull
|
||||||
|
{
|
||||||
|
if (Data is Dictionary<TKey, TEntity> typedData)
|
||||||
|
return typedData;
|
||||||
|
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Dictionary<TKey, TModel> GetData<TKey, TEntity, TModel>(Func<TEntity, TModel> convert, int attempt = 1)
|
||||||
|
where TKey : notnull
|
||||||
|
{
|
||||||
|
if (Data is Dictionary<TKey, TModel> typedData)
|
||||||
|
return typedData;
|
||||||
|
if (Data is Dictionary<TKey, TEntity > typedEntityData)
|
||||||
|
{
|
||||||
|
if (semaphore.Wait(0))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var convertedData = typedEntityData.ToDictionary(i => i.Key, i => convert(i.Value));
|
||||||
|
Data = convertedData;
|
||||||
|
return convertedData;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (semaphore.Wait(semaphoreTimeout))
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while converting cache data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attempt > 0)
|
||||||
|
return GetData<TKey, TEntity, TModel>(convert, --attempt);
|
||||||
|
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CacheItem GetOrAddCache(string tag, Func<IDictionary> valueFactory, TimeSpan obsolete)
|
private static CacheItem GetOrAddCache(string tag, Func<IDictionary> valueFactory, TimeSpan obsolete)
|
||||||
@ -233,15 +284,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
IDictionary factory()
|
IDictionary factory()
|
||||||
{
|
=> query.AsNoTracking().ToDictionary(keySelector);
|
||||||
var queryData = query.AsNoTracking()
|
|
||||||
.ToDictionary(keySelector);
|
|
||||||
return queryData;
|
|
||||||
}
|
|
||||||
var cache = GetOrAddCache(tag, factory, obsolescence);
|
var cache = GetOrAddCache(tag, factory, obsolescence);
|
||||||
if (cache.Data is Dictionary<TKey, TEntity> typedData)
|
return cache.GetData<TKey, TEntity>();
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -267,17 +312,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
IDictionary factory()
|
IDictionary factory()
|
||||||
{
|
=> query.AsNoTracking().ToDictionary(keySelector);
|
||||||
var queryData = query.AsNoTracking()
|
|
||||||
.ToList();
|
|
||||||
var data = queryData
|
|
||||||
.ToDictionary(keySelector, convert);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
var cache = GetOrAddCache(tag, factory, obsolescence);
|
var cache = GetOrAddCache(tag, factory, obsolescence);
|
||||||
if (cache.Data is Dictionary<TKey, TModel> typedData)
|
return cache.GetData<TKey, TEntity, TModel>(convert);
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -301,15 +338,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
async Task<IDictionary> factory(CancellationToken token)
|
async Task<IDictionary> factory(CancellationToken token)
|
||||||
{
|
=> await query.AsNoTracking().ToDictionaryAsync(keySelector, token);
|
||||||
var queryData = await query.AsNoTracking().ToDictionaryAsync(keySelector, token);
|
|
||||||
return queryData;
|
|
||||||
}
|
|
||||||
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
||||||
|
return cache.GetData<TKey, TEntity>();
|
||||||
if (cache.Data is Dictionary<TKey, TEntity> typedData)
|
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -331,16 +362,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
async Task<IDictionary> factory(CancellationToken token)
|
async Task<IDictionary> factory(CancellationToken token)
|
||||||
{
|
=> await query.AsNoTracking().ToDictionaryAsync(keySelector, token);
|
||||||
var queryData = await query.AsNoTracking().ToListAsync(token);
|
|
||||||
var data = queryData.ToDictionary(keySelector, convert);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
||||||
|
return cache.GetData<TKey, TEntity, TModel>(convert);
|
||||||
if (cache.Data is Dictionary<TKey, TModel> typedData)
|
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -26,6 +26,54 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
internal DateTime DateObsolete;
|
internal DateTime DateObsolete;
|
||||||
internal DateTime DateObsoleteTotal;
|
internal DateTime DateObsoleteTotal;
|
||||||
internal readonly SemaphoreSlim semaphore = new(1);
|
internal readonly SemaphoreSlim semaphore = new(1);
|
||||||
|
|
||||||
|
internal IEnumerable<TEntity> GetData<TEntity>()
|
||||||
|
{
|
||||||
|
if (Data is IEnumerable<TEntity> typedData)
|
||||||
|
return typedData;
|
||||||
|
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IEnumerable<TModel> GetData<TEntity, TModel>(Func<TEntity, TModel> convert, int attempt = 1)
|
||||||
|
{
|
||||||
|
if (Data is IEnumerable<TModel> typedData)
|
||||||
|
return typedData;
|
||||||
|
if (Data is IEnumerable<TEntity> typedEntityData)
|
||||||
|
{
|
||||||
|
if (semaphore.Wait(0))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var convertedData = typedEntityData.Select(convert).ToList();
|
||||||
|
Data = convertedData;
|
||||||
|
return convertedData;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (semaphore.Wait(semaphoreTimeout))
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while converting cache data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(attempt > 0)
|
||||||
|
return GetData(convert, --attempt);
|
||||||
|
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CacheItem GetOrAddCache(string tag, Func<IEnumerable> valueFactory, TimeSpan obsolete)
|
private static CacheItem GetOrAddCache(string tag, Func<IEnumerable> valueFactory, TimeSpan obsolete)
|
||||||
@ -224,16 +272,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
public static IEnumerable<TEntity> FromCache<TEntity>(this IQueryable<TEntity> query, string tag, TimeSpan obsolescence)
|
public static IEnumerable<TEntity> FromCache<TEntity>(this IQueryable<TEntity> query, string tag, TimeSpan obsolescence)
|
||||||
where TEntity : class
|
where TEntity : class
|
||||||
{
|
{
|
||||||
IEnumerable factory()
|
IEnumerable factory() => query.AsNoTracking().ToList();
|
||||||
{
|
|
||||||
var queryData = query.AsNoTracking()
|
|
||||||
.ToList();
|
|
||||||
return queryData;
|
|
||||||
}
|
|
||||||
var cache = GetOrAddCache(tag, factory, obsolescence);
|
var cache = GetOrAddCache(tag, factory, obsolescence);
|
||||||
if(cache.Data is IEnumerable<TEntity> typedData)
|
return cache.GetData<TEntity>();
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -250,19 +291,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
public static IEnumerable<TModel> FromCache<TEntity, TModel>(this IQueryable<TEntity> query, string tag, TimeSpan obsolescence, Func<TEntity, TModel> convert)
|
public static IEnumerable<TModel> FromCache<TEntity, TModel>(this IQueryable<TEntity> query, string tag, TimeSpan obsolescence, Func<TEntity, TModel> convert)
|
||||||
where TEntity : class
|
where TEntity : class
|
||||||
{
|
{
|
||||||
IEnumerable factory ()
|
IEnumerable factory () => query.AsNoTracking().ToList();
|
||||||
{
|
|
||||||
var queryData = query.AsNoTracking()
|
|
||||||
.ToList();
|
|
||||||
var data = queryData
|
|
||||||
.Select(convert)
|
|
||||||
.ToList();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
var cache = GetOrAddCache(tag, factory, obsolescence);
|
var cache = GetOrAddCache(tag, factory, obsolescence);
|
||||||
if (cache.Data is IEnumerable<TModel> typedData)
|
return cache.GetData(convert);
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -278,14 +309,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
where TEntity : class
|
where TEntity : class
|
||||||
{
|
{
|
||||||
async Task<IEnumerable> factory(CancellationToken token)
|
async Task<IEnumerable> factory(CancellationToken token)
|
||||||
{
|
=> await query.AsNoTracking().ToListAsync(token);
|
||||||
var queryData = await query.AsNoTracking().ToListAsync(token);
|
|
||||||
return queryData;
|
|
||||||
}
|
|
||||||
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
||||||
if (cache.Data is IEnumerable<TEntity> typedData)
|
return cache.GetData<TEntity>();
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -304,17 +330,9 @@ namespace AsbCloudInfrastructure.EfCache
|
|||||||
where TEntity : class
|
where TEntity : class
|
||||||
{
|
{
|
||||||
async Task<IEnumerable> factory(CancellationToken token)
|
async Task<IEnumerable> factory(CancellationToken token)
|
||||||
{
|
=> await query.AsNoTracking().ToListAsync(token);
|
||||||
var queryData = await query.AsNoTracking().ToListAsync(token);
|
|
||||||
var data = queryData
|
|
||||||
.Select(convert)
|
|
||||||
.ToList();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token);
|
||||||
if (cache.Data is IEnumerable<TModel> typedData)
|
return cache.GetData(convert);
|
||||||
return typedData;
|
|
||||||
throw new TypeAccessException("Cache data has wrong type. Possible 'tag' is not unique.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -6,35 +6,11 @@ namespace Mapster
|
|||||||
{
|
{
|
||||||
public static class MapsterExtension
|
public static class MapsterExtension
|
||||||
{
|
{
|
||||||
public static IEnumerable<TDestination> Adapt<TDestination>(this IEnumerable<object> sourceList)
|
//public static IEnumerable<TDestination> Adapt<TDestination>(this IEnumerable<object> sourceList)
|
||||||
{
|
//{
|
||||||
return sourceList.Select(item => item.Adapt<TDestination>());
|
// return sourceList.Select(item => item.Adapt<TDestination>());
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
public static TDestination Adapt<TDestination>(this object source, Action<TDestination> afterMapAction = default)
|
|
||||||
{
|
|
||||||
var dest = source.Adapt<TDestination>();
|
|
||||||
afterMapAction?.Invoke(dest);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TDestination Adapt<TDestination, TSource>(this TSource source, Action<TDestination, TSource> afterMapAction = default)
|
|
||||||
{
|
|
||||||
var dest = source.Adapt<TDestination>();
|
|
||||||
afterMapAction?.Invoke(dest, source);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<TDestination> Adapt<TDestination, TSource>(this IEnumerable<TSource> sourceList, Action<TDestination, TSource> eachAfterMapAction = default)
|
|
||||||
{
|
|
||||||
foreach (var item in sourceList)
|
|
||||||
{
|
|
||||||
var dest = item.Adapt<TDestination>();
|
|
||||||
eachAfterMapAction?.Invoke(dest, item);
|
|
||||||
yield return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ToListAsync(token)
|
.ToListAsync(token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var dtos = entities.Adapt<ClusterDto>();
|
var dtos = entities.Adapt<IEnumerable<ClusterDto>>();
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ToListAsync(token)
|
.ToListAsync(token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var dtos = entities.Adapt<ClusterDto>();
|
var dtos = entities.Adapt<IEnumerable<ClusterDto>>();
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using AsbCloudApp.Services;
|
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudInfrastructure.Services.Cache;
|
using AsbCloudInfrastructure.EfCache;
|
||||||
using Mapster;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -10,111 +9,104 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services
|
namespace AsbCloudInfrastructure.Services
|
||||||
{
|
{
|
||||||
public class CrudCacheServiceBase<TDto, TModel> : ICrudService<TDto>
|
#nullable enable
|
||||||
|
/// <summary>
|
||||||
|
/// CRUD ñåðâèñ ñ êåøåì â îïåðàòèâêå
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TDto"></typeparam>
|
||||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
|
public class CrudCacheServiceBase<TDto, TEntity>: CrudServiceBase<TDto, TEntity>
|
||||||
where TDto : AsbCloudApp.Data.IId
|
where TDto : AsbCloudApp.Data.IId
|
||||||
where TModel : class, AsbCloudDb.Model.IId
|
where TEntity : class, AsbCloudDb.Model.IId
|
||||||
{
|
{
|
||||||
private CacheTable<TModel> cache = null;
|
protected string CacheTag = typeof(TDto).Name;
|
||||||
private readonly IAsbCloudDbContext db;
|
protected TimeSpan CacheOlescence = TimeSpan.FromMinutes(5);
|
||||||
private readonly CacheDb cacheDb;
|
protected int KeySelector(TEntity entity) => entity.Id;
|
||||||
|
|
||||||
public ISet<string> Includes { get; } = new SortedSet<string>();
|
public CrudCacheServiceBase(IAsbCloudDbContext dbContext)
|
||||||
|
: base(dbContext) { }
|
||||||
|
|
||||||
protected CacheTable<TModel> Cache
|
public CrudCacheServiceBase(IAsbCloudDbContext dbContext, ISet<string> includes)
|
||||||
|
: base(dbContext, includes) { }
|
||||||
|
|
||||||
|
public CrudCacheServiceBase(IAsbCloudDbContext dbContext, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
|
||||||
|
: base(dbContext, makeQuery) { }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override async Task<int> InsertAsync(TDto newItem, CancellationToken token)
|
||||||
{
|
{
|
||||||
get
|
var result = await base.InsertAsync(newItem, token);
|
||||||
{
|
if (result > 0)
|
||||||
if (cache is null)
|
DropCache();
|
||||||
cache = cacheDb.GetCachedTable<TModel>((AsbCloudDbContext)db, Includes);
|
return result;
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CrudCacheServiceBase(IAsbCloudDbContext db, CacheDb cacheDb)
|
/// <inheritdoc/>
|
||||||
|
public override async Task<int> InsertRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
this.db = db;
|
var result = await base.InsertRangeAsync(dtos, token);
|
||||||
this.cacheDb = cacheDb;
|
if (result > 0)
|
||||||
|
DropCache();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> InsertAsync(TDto newItem, CancellationToken token = default)
|
/// <inheritdoc/>
|
||||||
|
public override async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
var entity = Convert(newItem);
|
var result = await GetQuery()
|
||||||
var insertedEntity = await Cache.InsertAsync(entity, token)
|
.FromCacheDictionaryAsync(CacheTag, CacheOlescence, KeySelector, Convert, token);
|
||||||
.ConfigureAwait(false);
|
return result.Values;
|
||||||
return insertedEntity?.Id ?? -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> InsertRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
|
/// <summary>
|
||||||
|
/// Ñèíõðîííî ïîëó÷èòü çàïèñü ïî ÈÄ
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override TDto? Get(int id)
|
||||||
{
|
{
|
||||||
var entities = dtos.Select(Convert);
|
var result = GetQuery()
|
||||||
var insertedEntities = await Cache.InsertAsync(entities, token)
|
.FromCacheDictionary(CacheTag, CacheOlescence, KeySelector, Convert);
|
||||||
.ConfigureAwait(false);
|
return result.GetValueOrDefault(id);
|
||||||
return insertedEntities?.Count() ?? 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token)
|
/// <inheritdoc/>
|
||||||
|
public override async Task<TDto?> GetAsync(int id, CancellationToken token)
|
||||||
{
|
{
|
||||||
var entities = await Cache.WhereAsync(token)
|
var result = await GetQuery()
|
||||||
.ConfigureAwait(false);
|
.FromCacheDictionaryAsync(CacheTag, CacheOlescence, KeySelector, Convert, token);
|
||||||
var dtos = entities?.Select(Convert);
|
return result.GetValueOrDefault(id);
|
||||||
return dtos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<TDto> GetAsync(int id, CancellationToken token)
|
/// <inheritdoc/>
|
||||||
|
public override async Task<int> UpdateAsync(int id, TDto dto, CancellationToken token)
|
||||||
{
|
{
|
||||||
var entity = await Cache
|
var result = await base.UpdateAsync(id, dto, token);
|
||||||
.FirstOrDefaultAsync(p => p.Id == id, token)
|
if (result > 0)
|
||||||
.ConfigureAwait(false);
|
DropCache();
|
||||||
if (entity is null)
|
return result;
|
||||||
return default;
|
|
||||||
var dto = Convert(entity);
|
|
||||||
return dto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> UpdateAsync(int id, TDto dto, CancellationToken token)
|
/// <inheritdoc/>
|
||||||
|
public override async Task<int> DeleteAsync(int id, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (dto.Id != id)
|
var result = await base.DeleteAsync(id, token);
|
||||||
{
|
if (result > 0)
|
||||||
var exist = await Cache.ContainsAsync(i => i.Id == dto.Id, token)
|
DropCache();
|
||||||
.ConfigureAwait(false);
|
return result;
|
||||||
|
|
||||||
if (exist)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
await Cache.RemoveAsync(i => i.Id == id, token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
var entity = Convert(dto);
|
|
||||||
await Cache.UpsertAsync(entity, token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> DeleteAsync(int id, CancellationToken token)
|
protected virtual Task<Dictionary<int, TDto>> GetCacheAsync(CancellationToken token)
|
||||||
{
|
=> GetQuery()
|
||||||
var affected = await Cache.RemoveAsync(p => p.Id == id, token)
|
.FromCacheDictionaryAsync(CacheTag, CacheOlescence, KeySelector, Convert, token);
|
||||||
.ConfigureAwait(false);
|
|
||||||
return affected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual async Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var affected = await Cache.RemoveAsync(p => ids.Contains(p.Id), token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
return affected;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual TModel Convert(TDto src)
|
protected virtual Dictionary<int, TDto> GetCache()
|
||||||
{
|
=> GetQuery()
|
||||||
var entity = src.Adapt<TModel>();
|
.FromCacheDictionary(CacheTag, CacheOlescence, KeySelector, Convert);
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual TDto Convert(TModel src)
|
protected virtual void DropCache()
|
||||||
{
|
=> dbSet.DropCacheDictionary(CacheTag);
|
||||||
var dto = src.Adapt<TDto>();
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudApp.Services;
|
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -11,87 +10,99 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services
|
namespace AsbCloudInfrastructure.Services
|
||||||
{
|
{
|
||||||
public class CrudServiceBase<TDto, TModel> : ICrudService<TDto>, IConverter<TDto, TModel>
|
#nullable enable
|
||||||
|
/// <summary>
|
||||||
|
/// CRUD сервис для работы с БД
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TDto"></typeparam>
|
||||||
|
/// <typeparam name="TEntity"></typeparam>
|
||||||
|
public class CrudServiceBase<TDto, TEntity> : ICrudService<TDto>
|
||||||
where TDto : AsbCloudApp.Data.IId
|
where TDto : AsbCloudApp.Data.IId
|
||||||
where TModel : class, AsbCloudDb.Model.IId
|
where TEntity : class, AsbCloudDb.Model.IId
|
||||||
{
|
{
|
||||||
protected readonly IAsbCloudDbContext context;
|
protected readonly IAsbCloudDbContext dbContext;
|
||||||
protected readonly DbSet<TModel> dbSet;
|
protected readonly DbSet<TEntity> dbSet;
|
||||||
|
protected readonly Func<IQueryable<TEntity>> GetQuery;
|
||||||
public ISet<string> Includes { get; } = new SortedSet<string>();
|
|
||||||
|
|
||||||
public CrudServiceBase(IAsbCloudDbContext context)
|
public CrudServiceBase(IAsbCloudDbContext context)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.dbContext = context;
|
||||||
dbSet = context.Set<TModel>();
|
dbSet = context.Set<TEntity>();
|
||||||
|
GetQuery = () => dbSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<PaginationContainer<TDto>> GetPageAsync(int skip = 0, int take = 32, CancellationToken token = default)
|
public CrudServiceBase(IAsbCloudDbContext dbContext, ISet<string> includes)
|
||||||
{
|
{
|
||||||
var query = GetQueryWithIncludes();
|
this.dbContext = dbContext;
|
||||||
var count = await query
|
dbSet = dbContext.Set<TEntity>();
|
||||||
.CountAsync(token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
var container = new PaginationContainer<TDto>
|
GetQuery = () => {
|
||||||
{
|
IQueryable<TEntity> query = dbSet;
|
||||||
Skip = skip,
|
foreach (var include in includes)
|
||||||
Take = take,
|
query = query.Include(include);
|
||||||
Count = count,
|
return query;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (skip >= count)
|
|
||||||
return container;
|
|
||||||
|
|
||||||
query = query
|
|
||||||
.OrderBy(e => e.Id);
|
|
||||||
|
|
||||||
if (skip > 0)
|
|
||||||
query = query.Skip(skip);
|
|
||||||
|
|
||||||
query = query.Take(take);
|
|
||||||
|
|
||||||
var entities = await query
|
|
||||||
.ToListAsync(token)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
container.Items = entities
|
|
||||||
.Select(entity => Convert(entity))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CrudServiceBase(IAsbCloudDbContext context, Func<DbSet<TEntity>, IQueryable<TEntity>> makeQuery)
|
||||||
|
{
|
||||||
|
this.dbContext = context;
|
||||||
|
dbSet = context.Set<TEntity>();
|
||||||
|
GetQuery = () => makeQuery(dbSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token = default)
|
public virtual async Task<IEnumerable<TDto>> GetAllAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var query = GetQueryWithIncludes();
|
var entities = await GetQuery()
|
||||||
var entities = await query
|
//.OrderBy(e => e.Id)
|
||||||
.OrderBy(e => e.Id)
|
.AsNoTracking()
|
||||||
.ToListAsync(token).ConfigureAwait(false);
|
.ToListAsync(token)
|
||||||
var dto = entities.Select(Convert).ToList();
|
.ConfigureAwait(false);
|
||||||
return dto;
|
var dtos = entities.Select(Convert).ToList();
|
||||||
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<TDto> GetAsync(int id, CancellationToken token = default)
|
/// <inheritdoc/>
|
||||||
|
public virtual async Task<TDto?> GetAsync(int id, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var query = GetQueryWithIncludes();
|
var entity = await GetQuery()
|
||||||
var entity = await query
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(e => e.Id == id, token).ConfigureAwait(false);
|
.FirstOrDefaultAsync(e => e.Id == id, token)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
if (entity == default)
|
||||||
|
return default;
|
||||||
var dto = Convert(entity);
|
var dto = Convert(entity);
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public virtual TDto? Get(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)
|
public virtual async Task<int> InsertAsync(TDto item, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var entity = Convert(item);
|
var entity = Convert(item);
|
||||||
entity.Id = 0;
|
entity.Id = 0;
|
||||||
dbSet.Add(entity);
|
dbSet.Add(entity);
|
||||||
await context.SaveChangesAsync(token);
|
await dbContext.SaveChangesAsync(token);
|
||||||
return entity.Id;
|
return entity.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public virtual Task<int> InsertRangeAsync(IEnumerable<TDto> items, CancellationToken token = default)
|
public virtual Task<int> InsertRangeAsync(IEnumerable<TDto> items, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
if (!items.Any())
|
||||||
|
return Task.FromResult(0);
|
||||||
var entities = items.Select(i =>
|
var entities = items.Select(i =>
|
||||||
{
|
{
|
||||||
var entity = Convert(i);
|
var entity = Convert(i);
|
||||||
@ -100,40 +111,40 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
});
|
});
|
||||||
|
|
||||||
dbSet.AddRange(entities);
|
dbSet.AddRange(entities);
|
||||||
return context.SaveChangesAsync(token);
|
return dbContext.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public virtual async Task<int> UpdateAsync(int id, TDto item, CancellationToken token = default)
|
public virtual async Task<int> UpdateAsync(int id, TDto item, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var existingEntity = await dbSet.AsNoTracking().FirstOrDefaultAsync(e => e.Id == id, token).ConfigureAwait(false);
|
var existingEntity = await dbSet
|
||||||
|
.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync(e => e.Id == id, token)
|
||||||
|
.ConfigureAwait(false);
|
||||||
if (existingEntity is null)
|
if (existingEntity is null)
|
||||||
return 0;
|
return ICrudService<TDto>.ErrorIdNotFound;
|
||||||
var entity = Convert(item);
|
var entity = Convert(item);
|
||||||
entity.Id = id;
|
entity.Id = id;
|
||||||
dbSet.Update(entity);
|
var entry = dbSet.Update(entity);
|
||||||
return await context.SaveChangesAsync(token);
|
await dbContext.SaveChangesAsync(token);
|
||||||
|
return entry.Entity.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public virtual Task<int> DeleteAsync(int id, CancellationToken token = default)
|
public virtual Task<int> DeleteAsync(int id, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var entity = dbSet.AsNoTracking()
|
var entity = dbSet
|
||||||
|
.AsNoTracking()
|
||||||
.FirstOrDefault(e => e.Id == id);
|
.FirstOrDefault(e => e.Id == id);
|
||||||
if (entity == default)
|
if (entity == default)
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(ICrudService<TDto>.ErrorIdNotFound);
|
||||||
dbSet.Remove(entity);
|
dbSet.Remove(entity);
|
||||||
return context.SaveChangesAsync(token);
|
return dbContext.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual TDto Convert(TModel src) => src.Adapt<TDto>();
|
protected virtual TDto Convert(TEntity src) => src.Adapt<TDto>();
|
||||||
|
|
||||||
public virtual TModel Convert(TDto src) => src.Adapt<TModel>();
|
protected virtual TEntity Convert(TDto src) => src.Adapt<TEntity>();
|
||||||
|
|
||||||
protected IQueryable<TModel> GetQueryWithIncludes()
|
|
||||||
{
|
|
||||||
IQueryable<TModel> query = dbSet;
|
|
||||||
foreach (var include in Includes)
|
|
||||||
query = query.Include(include);
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ToListAsync(token)
|
.ToListAsync(token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var dto = entities.Adapt<DrillParamsDto>();
|
var dto = entities.Adapt<IEnumerable<DrillParamsDto>>();
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ToListAsync(token)
|
.ToListAsync(token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var compositeDrillParamsDtos = compositeWellDrillParams.Adapt<DrillParamsDto>();
|
var compositeDrillParamsDtos = compositeWellDrillParams.Adapt<IEnumerable<DrillParamsDto>>();
|
||||||
|
|
||||||
return compositeDrillParamsDtos;
|
return compositeDrillParamsDtos;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
|||||||
.SelectMany(r => r.Company.Users)
|
.SelectMany(r => r.Company.Users)
|
||||||
.Where(u => u != null && !string.IsNullOrEmpty(u.Email))
|
.Where(u => u != null && !string.IsNullOrEmpty(u.Email))
|
||||||
.ToListAsync(token);
|
.ToListAsync(token);
|
||||||
var usersDto = users.Adapt<UserDto>();
|
var usersDto = users.Adapt<IEnumerable<UserDto>>();
|
||||||
return usersDto;
|
return usersDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,11 +46,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var timezone = wellService.GetTimezone(idWell);
|
var timezone = wellService.GetTimezone(idWell);
|
||||||
var dto = entity?.Adapt<MeasureDto, Measure>((d, s) =>
|
var dto = Convert(entity, timezone.Hours);
|
||||||
{
|
|
||||||
d.CategoryName = s.Category?.Name;
|
|
||||||
d.Timestamp = s.Timestamp.ToRemoteDateTime(timezone.Hours);
|
|
||||||
});
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,11 +65,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var timezone = wellService.GetTimezone(idWell);
|
var timezone = wellService.GetTimezone(idWell);
|
||||||
var dtos = entities.Adapt<MeasureDto, Measure>((d, s) =>
|
var dtos = entities.Select(e => Convert(e, timezone.Hours));
|
||||||
{
|
|
||||||
d.CategoryName = s.Category?.Name;
|
|
||||||
d.Timestamp = s.Timestamp.ToRemoteDateTime(timezone.Hours);
|
|
||||||
});
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +76,8 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
if (dto.Data is null)
|
if (dto.Data is null)
|
||||||
throw new ArgumentInvalidException("data.data is not optional", nameof(dto));
|
throw new ArgumentInvalidException("data.data is not optional", nameof(dto));
|
||||||
var timezone = wellService.GetTimezone(idWell);
|
var timezone = wellService.GetTimezone(idWell);
|
||||||
var entity = dto.Adapt<Measure>();
|
var entity = Convert(dto, timezone.Hours);
|
||||||
entity.IdWell = idWell;
|
entity.IdWell = idWell;
|
||||||
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours);
|
|
||||||
db.Measures.Add(entity);
|
db.Measures.Add(entity);
|
||||||
return db.SaveChangesAsync(token);
|
return db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
@ -109,7 +100,6 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
throw new ArgumentInvalidException("id doesn't exist", nameof(dto));
|
throw new ArgumentInvalidException("id doesn't exist", nameof(dto));
|
||||||
|
|
||||||
var timezone = wellService.GetTimezone(idWell);
|
var timezone = wellService.GetTimezone(idWell);
|
||||||
|
|
||||||
entity.IdWell = idWell;
|
entity.IdWell = idWell;
|
||||||
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours);
|
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours);
|
||||||
entity.Data = (RawData)dto.Data;
|
entity.Data = (RawData)dto.Data;
|
||||||
@ -138,5 +128,20 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
db.Measures.RemoveRange(db.Measures.Where(m => m.IdWell == idWell && m.Id == idData));
|
db.Measures.RemoveRange(db.Measures.Where(m => m.IdWell == idWell && m.Id == idData));
|
||||||
return db.SaveChangesAsync(token);
|
return db.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MeasureDto Convert(Measure entity, double hours)
|
||||||
|
{
|
||||||
|
var dto = entity.Adapt<MeasureDto>();
|
||||||
|
dto.CategoryName = entity.Category?.Name;
|
||||||
|
dto.Timestamp = entity.Timestamp.ToRemoteDateTime(hours);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
private Measure Convert(MeasureDto dto, double hours)
|
||||||
|
{
|
||||||
|
var entity = dto.Adapt<Measure>();
|
||||||
|
entity.Category = null;
|
||||||
|
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(hours);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
|||||||
return telemetryDtos;
|
return telemetryDtos;
|
||||||
var telemetries = cacheTelemetry
|
var telemetries = cacheTelemetry
|
||||||
.Where(t => activeTelemetriesUids.Contains(t.RemoteUid));
|
.Where(t => activeTelemetriesUids.Contains(t.RemoteUid));
|
||||||
telemetryDtos = telemetries.Adapt<TelemetryDto>().ToList();
|
telemetryDtos = telemetries.Adapt<IEnumerable<TelemetryDto>>().ToList();
|
||||||
|
|
||||||
return telemetryDtos;
|
return telemetryDtos;
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,15 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
{
|
{
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
|
|
||||||
public ScheduleService(IAsbCloudDbContext context, IWellService wellService) : base(context)
|
public ScheduleService(IAsbCloudDbContext context, IWellService wellService)
|
||||||
|
: base(context, dbSet => dbSet.Include(s => s.Driller))
|
||||||
{
|
{
|
||||||
Includes.Add(nameof(Schedule.Driller));
|
|
||||||
this.wellService = wellService;
|
this.wellService = wellService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<ScheduleDto>> GetByIdWellAsync(int idWell, CancellationToken token = default)
|
public async Task<IEnumerable<ScheduleDto>> GetByIdWellAsync(int idWell, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var entities = await GetQueryWithIncludes()
|
var entities = await GetQuery()
|
||||||
.Where(s => s.IdWell == idWell)
|
.Where(s => s.IdWell == idWell)
|
||||||
.ToListAsync(token);
|
.ToListAsync(token);
|
||||||
var dtos = entities.Select(Convert);
|
var dtos = entities.Select(Convert);
|
||||||
@ -36,7 +36,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
var hoursOffset = wellService.GetTimezone(idWell).Hours;
|
var hoursOffset = wellService.GetTimezone(idWell).Hours;
|
||||||
var date = workTime.ToUtcDateTimeOffset(hoursOffset);
|
var date = workTime.ToUtcDateTimeOffset(hoursOffset);
|
||||||
|
|
||||||
var entities = await GetQueryWithIncludes()
|
var entities = await GetQuery()
|
||||||
.Where(s => s.IdWell==idWell
|
.Where(s => s.IdWell==idWell
|
||||||
&& s.DrillStart <= date
|
&& s.DrillStart <= date
|
||||||
&& s.DrillEnd >= date)
|
&& s.DrillEnd >= date)
|
||||||
@ -56,7 +56,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
return entity?.Driller.Adapt<DrillerDto>();
|
return entity?.Driller.Adapt<DrillerDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Schedule Convert(ScheduleDto dto)
|
protected override Schedule Convert(ScheduleDto dto)
|
||||||
{
|
{
|
||||||
var hoursOffset = wellService.GetTimezone(dto.IdWell).Hours;
|
var hoursOffset = wellService.GetTimezone(dto.IdWell).Hours;
|
||||||
var entity = base.Convert(dto);
|
var entity = base.Convert(dto);
|
||||||
@ -65,7 +65,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ScheduleDto Convert(Schedule entity)
|
protected override ScheduleDto Convert(Schedule entity)
|
||||||
{
|
{
|
||||||
var hoursOffset = wellService.GetTimezone(entity.IdWell).Hours;
|
var hoursOffset = wellService.GetTimezone(entity.IdWell).Hours;
|
||||||
var dto = base.Convert(entity);
|
var dto = base.Convert(entity);
|
||||||
|
@ -56,6 +56,14 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
var dtos = entities?.Select(Convert);
|
var dtos = entities?.Select(Convert);
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
public UserRoleDto Get(int id)
|
||||||
|
{
|
||||||
|
var entity = cacheUserRoles.FirstOrDefault(r => r.Id == id);
|
||||||
|
if (entity is null)
|
||||||
|
return null;
|
||||||
|
var dto = Convert(entity);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<UserRoleDto> GetAsync(int id, CancellationToken token = default)
|
public async Task<UserRoleDto> GetAsync(int id, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
@ -97,7 +105,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (exist)
|
if (exist)
|
||||||
return -1;
|
return ICrudService<UserRoleDto>.ErrorIdNotFound;
|
||||||
|
|
||||||
await cacheUserRoles.RemoveAsync(i => i.Id == id, token)
|
await cacheUserRoles.RemoveAsync(i => i.Id == id, token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@ -107,10 +115,9 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
await UpdatePermissionsAsync(dto, token);
|
await UpdatePermissionsAsync(dto, token);
|
||||||
await UpdateIncludedRolesAsync(dto, token);
|
await UpdateIncludedRolesAsync(dto, token);
|
||||||
|
|
||||||
await cacheUserRoles.UpsertAsync(entity, token)
|
var result = await cacheUserRoles.UpsertAsync(entity, token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
return result;
|
||||||
return dto.Id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<UserRoleDto> GetNestedById(int id, int recursionLevel = 7)
|
public IEnumerable<UserRoleDto> GetNestedById(int id, int recursionLevel = 7)
|
||||||
|
@ -81,6 +81,14 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserExtendedDto Get(int id)
|
||||||
|
{
|
||||||
|
var entity = cacheUsers.FirstOrDefault(u => u.Id == id);
|
||||||
|
var dto = Convert(entity);
|
||||||
|
dto.RoleNames = GetRolesNamesByIdUser(dto.Id);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<UserExtendedDto> GetAsync(int id, CancellationToken token = default)
|
public async Task<UserExtendedDto> GetAsync(int id, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var entity = await cacheUsers.FirstOrDefaultAsync(u => u.Id == id, token).ConfigureAwait(false);
|
var entity = await cacheUsers.FirstOrDefaultAsync(u => u.Id == id, token).ConfigureAwait(false);
|
||||||
|
@ -26,7 +26,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.ToListAsync(token)
|
.ToListAsync(token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
return entities.Adapt<WellCompositeDto>();
|
return entities.Select(Convert);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<int> SaveAsync(int idWell, IEnumerable<WellCompositeDto> wellComposites, CancellationToken token)
|
public Task<int> SaveAsync(int idWell, IEnumerable<WellCompositeDto> wellComposites, CancellationToken token)
|
||||||
@ -35,10 +35,22 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
.Where(c => c.IdWell == idWell));
|
.Where(c => c.IdWell == idWell));
|
||||||
|
|
||||||
var entities = wellComposites
|
var entities = wellComposites
|
||||||
.Adapt<WellComposite, WellCompositeDto>((s, _) => { s.IdWell = idWell; });
|
.Select(w => Convert(idWell, w));
|
||||||
|
|
||||||
context.WellComposites.AddRange(entities);
|
context.WellComposites.AddRange(entities);
|
||||||
return context.SaveChangesAsync(token);
|
return context.SaveChangesAsync(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WellComposite Convert(int idWell, WellCompositeDto dto)
|
||||||
|
{
|
||||||
|
var entity = dto.Adapt<WellComposite>();
|
||||||
|
entity.IdWell = idWell;
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
private WellCompositeDto Convert(WellComposite entity)
|
||||||
|
{
|
||||||
|
var dto = entity.Adapt<WellCompositeDto>();
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
|
|||||||
{
|
{
|
||||||
var operationTypes = cachedOperationCategories
|
var operationTypes = cachedOperationCategories
|
||||||
.Distinct().OrderBy(o => o.Name);
|
.Distinct().OrderBy(o => o.Name);
|
||||||
var result = operationTypes.Adapt<WellOperationCategoryDto>();
|
var result = operationTypes.Adapt<IEnumerable<WellOperationCategoryDto>>();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@ using AsbCloudApp.Exceptions;
|
|||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudInfrastructure.Services.Cache;
|
using AsbCloudInfrastructure.Services.Cache;
|
||||||
|
using AsbCloudInfrastructure.EfCache;
|
||||||
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;
|
||||||
@ -25,31 +27,53 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
dst => dst.WellType)
|
dst => dst.WellType)
|
||||||
.Config;
|
.Config;
|
||||||
|
|
||||||
|
private const string relationCompaniesWellsCacheTag = "RelationCompaniesWells";
|
||||||
|
private static readonly TimeSpan relationCompaniesWellsCacheObsolence = TimeSpan.FromMinutes(15);
|
||||||
|
|
||||||
private readonly ITelemetryService telemetryService;
|
private readonly ITelemetryService telemetryService;
|
||||||
private readonly CacheTable<RelationCompanyWell> cacheRelationCompaniesWells;
|
private readonly ICrudService<CompanyTypeDto> companyTypesService;
|
||||||
private readonly CacheTable<CompanyType> cacheCompanyWellTypes;
|
|
||||||
private readonly ITimezoneService timezoneService;
|
private readonly ITimezoneService timezoneService;
|
||||||
private readonly Lazy<IWellOperationService> wellOperationService;
|
private readonly IWellOperationService wellOperationService;
|
||||||
|
|
||||||
public ITelemetryService TelemetryService => telemetryService;
|
public ITelemetryService TelemetryService => telemetryService;
|
||||||
|
|
||||||
|
private static IQueryable<Well> MakeQueryWell(DbSet<Well> dbSet)
|
||||||
|
=> dbSet
|
||||||
|
.Include(w => w.Cluster)
|
||||||
|
.ThenInclude(c => c.Deposit)
|
||||||
|
.Include(w => w.Telemetry)
|
||||||
|
.Include(w => w.WellType)
|
||||||
|
.Include(w => w.RelationCompaniesWells)
|
||||||
|
.ThenInclude(r => r.Company);
|
||||||
|
|
||||||
public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService, ITimezoneService timezoneService)
|
public WellService(IAsbCloudDbContext db, CacheDb cacheDb, ITelemetryService telemetryService, ITimezoneService timezoneService)
|
||||||
: base(db, cacheDb)
|
: base(db, MakeQueryWell)
|
||||||
{
|
{
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
this.timezoneService = timezoneService;
|
this.timezoneService = timezoneService;
|
||||||
this.wellOperationService = new Lazy<IWellOperationService>(() => new WellOperationService.WellOperationService(db, cacheDb, this));
|
|
||||||
cacheRelationCompaniesWells = cacheDb.GetCachedTable<RelationCompanyWell>((AsbCloudDbContext)db, nameof(RelationCompanyWell.Company), nameof(RelationCompanyWell.Well));
|
this.wellOperationService = new WellOperationService.WellOperationService(db, cacheDb, this);
|
||||||
cacheCompanyWellTypes = cacheDb.GetCachedTable<CompanyType>((AsbCloudDbContext)db);
|
companyTypesService = new CrudCacheServiceBase<CompanyTypeDto, CompanyType>(dbContext);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<RelationCompanyWell> GetCacheRelationCompanyWell()
|
||||||
|
=> dbContext.RelationCompaniesWells
|
||||||
|
.Include(r => r.Company)
|
||||||
|
.Include(r => r.Well)
|
||||||
|
.FromCache(relationCompaniesWellsCacheTag, relationCompaniesWellsCacheObsolence);
|
||||||
|
|
||||||
|
private Task<IEnumerable<RelationCompanyWell>> GetCacheRelationCompanyWellAsync(CancellationToken token)
|
||||||
|
=> dbContext.RelationCompaniesWells
|
||||||
|
.Include(r => r.Company)
|
||||||
|
.Include(r => r.Well)
|
||||||
|
.FromCacheAsync(relationCompaniesWellsCacheTag, relationCompaniesWellsCacheObsolence, token);
|
||||||
|
|
||||||
|
private void DropCacheRelationCompanyWell()
|
||||||
|
=> dbContext.RelationCompaniesWells.DropCache(relationCompaniesWellsCacheTag);
|
||||||
|
|
||||||
public DateTimeOffset GetLastTelemetryDate(int idWell)
|
public DateTimeOffset GetLastTelemetryDate(int idWell)
|
||||||
{
|
{
|
||||||
var well = Cache.FirstOrDefault(w => w.Id == idWell);
|
var well = Get(idWell);
|
||||||
|
|
||||||
if (well?.IdTelemetry is null)
|
if (well?.IdTelemetry is null)
|
||||||
return DateTimeOffset.MinValue;
|
return DateTimeOffset.MinValue;
|
||||||
@ -60,14 +84,17 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
|
|
||||||
public async Task<IEnumerable<WellDto>> GetWellsByCompanyAsync(int idCompany, CancellationToken token)
|
public async Task<IEnumerable<WellDto>> GetWellsByCompanyAsync(int idCompany, CancellationToken token)
|
||||||
{
|
{
|
||||||
var relations = await cacheRelationCompaniesWells
|
var relationsCache = await GetCacheRelationCompanyWellAsync(token);
|
||||||
.WhereAsync(r => r.IdCompany == idCompany, token);
|
|
||||||
|
|
||||||
var wellsIds = relations.Select(r => r.IdWell);
|
var wellsIds = relationsCache
|
||||||
var wells = await Cache.WhereAsync(w => wellsIds.Contains(w.Id), token);
|
.Where(r => r.IdCompany == idCompany)
|
||||||
|
.Select(r => r.IdWell);
|
||||||
|
|
||||||
|
var wellsDtos = (await GetCacheAsync(token))
|
||||||
|
.Where(kv => wellsIds.Contains(kv.Key))
|
||||||
|
.Select(kv =>kv.Value);
|
||||||
|
|
||||||
var dtos = wells.Select(Convert);
|
return wellsDtos.ToList();
|
||||||
return dtos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<int> InsertAsync(WellDto dto, CancellationToken token = default)
|
public override async Task<int> InsertAsync(WellDto dto, CancellationToken token = default)
|
||||||
@ -78,20 +105,22 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
if (dto.IdState is < 0 or > 2)
|
if (dto.IdState is < 0 or > 2)
|
||||||
throw new ArgumentInvalidException("Текущее состояние работы скважины указано неправильно.", nameof(dto));
|
throw new ArgumentInvalidException("Текущее состояние работы скважины указано неправильно.", nameof(dto));
|
||||||
|
|
||||||
if (dto.Id != 0 && await Cache.ContainsAsync(w => w.Id == dto.Id, token))
|
if (dto.Id != 0 && (await GetCacheAsync(token)).ContainsKey(dto.Id))
|
||||||
throw new ArgumentInvalidException($"Нельзя повторно добавить скважину с id: {dto.Id}", nameof(dto));
|
throw new ArgumentInvalidException($"Нельзя повторно добавить скважину с id: {dto.Id}", nameof(dto));
|
||||||
|
|
||||||
var entity = Convert(dto);
|
var entity = Convert(dto);
|
||||||
|
|
||||||
var result = await Cache.InsertAsync(entity, token);
|
var result = await base.InsertAsync(dto, token);
|
||||||
|
|
||||||
if (dto.Companies.Any())
|
if (dto.Companies.Any())
|
||||||
{
|
{
|
||||||
var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = result.Id, IdCompany = c.Id });
|
var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = result, IdCompany = c.Id });
|
||||||
await cacheRelationCompaniesWells.InsertAsync(newRelations, token);
|
dbContext.RelationCompaniesWells.AddRange(newRelations);
|
||||||
|
await dbContext.SaveChangesAsync(token);
|
||||||
|
DropCacheRelationCompanyWell();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.Id;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<int> InsertRangeAsync(IEnumerable<WellDto> dtos, CancellationToken token)
|
public override Task<int> InsertRangeAsync(IEnumerable<WellDto> dtos, CancellationToken token)
|
||||||
@ -111,47 +140,50 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
if (dto.Id != idWell)
|
if (dto.Id != idWell)
|
||||||
throw new ArgumentInvalidException($"Нельзя поменять id для скважины: {idWell} => {dto.Id}.", nameof(dto));
|
throw new ArgumentInvalidException($"Нельзя поменять id для скважины: {idWell} => {dto.Id}.", nameof(dto));
|
||||||
|
|
||||||
var entity = Convert(dto);
|
var oldRelations = (await GetCacheRelationCompanyWellAsync(token))
|
||||||
|
.Where(r => r.IdWell == idWell);
|
||||||
var oldRelations = await cacheRelationCompaniesWells
|
|
||||||
.WhereAsync(r => r.IdWell == idWell, token);
|
|
||||||
|
|
||||||
if (dto.Companies.Count() != oldRelations.Count() ||
|
if (dto.Companies.Count() != oldRelations.Count() ||
|
||||||
dto.Companies.Any(c => !oldRelations.Any(oldC => oldC.IdCompany == c.Id)))
|
dto.Companies.Any(c => !oldRelations.Any(oldC => oldC.IdCompany == c.Id)))
|
||||||
{
|
{
|
||||||
await cacheRelationCompaniesWells.RemoveAsync(r => r.IdWell == idWell, token);
|
dbContext.RelationCompaniesWells
|
||||||
|
.RemoveRange(dbContext.RelationCompaniesWells
|
||||||
|
.Where(r => r.IdWell == idWell));
|
||||||
|
|
||||||
var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = idWell, IdCompany = c.Id });
|
var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = idWell, IdCompany = c.Id });
|
||||||
await cacheRelationCompaniesWells.InsertAsync(newRelations, token);
|
dbContext.RelationCompaniesWells.AddRange(newRelations);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await Cache.UpsertAsync(entity, token);
|
var result = await base.UpdateAsync(idWell, dto, token);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCompanyInvolvedInWell(int idCompany, int idWell)
|
public bool IsCompanyInvolvedInWell(int idCompany, int idWell)
|
||||||
=> cacheRelationCompaniesWells.Contains(r => r.IdWell == idWell && r.IdCompany == idCompany);
|
=> GetCacheRelationCompanyWell()
|
||||||
|
.Any(r => r.IdWell == idWell && r.IdCompany == idCompany);
|
||||||
|
|
||||||
public async Task<bool> IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token)
|
public async Task<bool> IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token)
|
||||||
=> await cacheRelationCompaniesWells.ContainsAsync(r => r.IdWell == idWell &&
|
=> (await GetCacheRelationCompanyWellAsync(token))
|
||||||
r.IdCompany == idCompany, token).ConfigureAwait(false);
|
.Any(r => r.IdWell == idWell && r.IdCompany == idCompany);
|
||||||
|
|
||||||
public async Task<string> GetWellCaptionByIdAsync(int idWell, CancellationToken token)
|
public async Task<string> GetWellCaptionByIdAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var entity = await Cache.FirstOrDefaultAsync(w => w.Id == idWell, token).ConfigureAwait(false);
|
var entity = await GetAsync(idWell, token).ConfigureAwait(false);
|
||||||
var dto = Convert(entity);
|
var dto = Convert(entity);
|
||||||
return dto.Caption;
|
return dto.Caption;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<CompanyDto>> GetCompaniesAsync(int idWell, CancellationToken token)
|
public async Task<IEnumerable<CompanyDto>> GetCompaniesAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var relations = await cacheRelationCompaniesWells.WhereAsync(r => r.IdWell == idWell, token);
|
var relations = (await GetCacheRelationCompanyWellAsync(token))
|
||||||
|
.Where(r => r.IdWell == idWell);
|
||||||
var dtos = relations.Select(r => Convert(r.Company));
|
var dtos = relations.Select(r => Convert(r.Company));
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<CompanyDto> GetCompanies(int idWell)
|
private IEnumerable<CompanyDto> GetCompanies(int idWell)
|
||||||
{
|
{
|
||||||
var relations = cacheRelationCompaniesWells.Where(r => r.IdWell == idWell);
|
var relations = GetCacheRelationCompanyWell().Where(r => r.IdWell == idWell);
|
||||||
var dtos = relations.Select(r => Convert(r.Company));
|
var dtos = relations.Select(r => Convert(r.Company));
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
@ -168,16 +200,18 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
|
|
||||||
public async Task<IEnumerable<int>> GetClusterWellsIdsAsync(int idWell, CancellationToken token)
|
public async Task<IEnumerable<int>> GetClusterWellsIdsAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var well = await Cache.FirstOrDefaultAsync(w => w.Id == idWell, token)
|
var well = await GetAsync(idWell, token);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (well is null)
|
if (well is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var clusterWells = await Cache.WhereAsync(w => w.IdCluster == well.IdCluster, token)
|
var cache = await GetCacheAsync(token);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return clusterWells.Select(w => w.Id);
|
var clusterWellsIds = cache.Values
|
||||||
|
.Where((w) => w.IdCluster == well.IdCluster)
|
||||||
|
.Select(w => w.Id);
|
||||||
|
|
||||||
|
return clusterWellsIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Well Convert(WellDto dto)
|
protected override Well Convert(WellDto dto)
|
||||||
@ -187,8 +221,8 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
entity.IdTelemetry = entity.IdTelemetry ?? dto.IdTelemetry ?? dto.Telemetry?.Id;
|
entity.IdTelemetry = entity.IdTelemetry ?? dto.IdTelemetry ?? dto.Telemetry?.Id;
|
||||||
|
|
||||||
if (dto.Timezone is null)
|
if (dto.Timezone is null)
|
||||||
if (TryGetTimezone(dto.Id, out var timezoneDto))
|
entity.Timezone = GetTimezone(dto.Id)
|
||||||
entity.Timezone = timezoneDto.Adapt<SimpleTimezone>();
|
.Adapt<SimpleTimezone>();
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
@ -201,15 +235,17 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
var dto = base.Convert(entity);
|
var dto = base.Convert(entity);
|
||||||
|
|
||||||
if (entity.Timezone is null)
|
if (entity.Timezone is null)
|
||||||
if (TryGetTimezone(entity, out var timezone))
|
dto.Timezone = GetTimezone(entity.Id);
|
||||||
dto.Timezone = timezone;
|
|
||||||
|
|
||||||
dto.StartDate = wellOperationService.Value.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours);
|
dto.StartDate = wellOperationService.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours);
|
||||||
dto.WellType = entity.WellType?.Caption;
|
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).DateTime;
|
if(entity.IdTelemetry is not null)
|
||||||
dto.Companies = GetCompanies(entity.Id);
|
dto.LastTelemetryDate = telemetryService.GetLastTelemetryDate((int)entity.IdTelemetry);
|
||||||
|
dto.Companies = entity.RelationCompaniesWells
|
||||||
|
.Select(r => Convert(r.Company))
|
||||||
|
.ToList();
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,94 +253,56 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
{
|
{
|
||||||
var dto = entity.Adapt<CompanyDto>();
|
var dto = entity.Adapt<CompanyDto>();
|
||||||
dto.CompanyTypeCaption = entity.CompanyType?.Caption
|
dto.CompanyTypeCaption = entity.CompanyType?.Caption
|
||||||
?? cacheCompanyWellTypes.FirstOrDefault(c => c.Id == entity.IdCompanyType).Caption;
|
?? companyTypesService.Get(entity.IdCompanyType).Caption;
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnshureTimezonesIsSet()
|
public async Task EnshureTimezonesIsSetAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
var wells = Cache.Where(w => w.Timezone is null).ToList();
|
var cache = await GetCacheAsync(token);
|
||||||
foreach (var well in wells)
|
if (!cache.Values.Any(w => w.Timezone is null))
|
||||||
{
|
return;
|
||||||
if (TryGetTimezone(well, out var timezone))
|
|
||||||
well.Timezone = timezone.Adapt<SimpleTimezone>();
|
|
||||||
else
|
|
||||||
well.Timezone = new SimpleTimezone
|
|
||||||
{
|
|
||||||
Hours = 5,
|
|
||||||
IsOverride = false,
|
|
||||||
TimeZoneId = "Assumed",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var wellsWithTz = wells.Where(w => w.Timezone is not null);
|
var defaultTimeZone = new SimpleTimezone
|
||||||
if (wellsWithTz.Any())
|
|
||||||
{
|
{
|
||||||
var adaptedWells = wellsWithTz.Adapt<WellDto>().Select(Convert);
|
Hours = 5,
|
||||||
Cache.Upsert(adaptedWells);
|
IsOverride = false,
|
||||||
}
|
TimeZoneId = "Assumed",
|
||||||
}
|
};
|
||||||
|
|
||||||
private bool TryGetTimezone(int idWell, out SimpleTimezoneDto timezone)
|
await dbSet.Where(w => w.Timezone == null)
|
||||||
{
|
.ForEachAsync(w => w.Timezone = defaultTimeZone, token);
|
||||||
timezone = null;
|
|
||||||
try
|
await dbContext.SaveChangesAsync(token);
|
||||||
{
|
DropCache();
|
||||||
timezone = GetTimezone(idWell);
|
|
||||||
return timezone is not null;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleTimezoneDto GetTimezone(int idWell)
|
public SimpleTimezoneDto GetTimezone(int idWell)
|
||||||
{
|
{
|
||||||
var well = Cache.FirstOrDefault(c => c.Id == idWell);
|
var well = Get(idWell);
|
||||||
if (well == null)
|
if (well == null)
|
||||||
throw new ArgumentInvalidException($"idWell: {idWell} does not exist.", nameof(idWell));
|
throw new ArgumentInvalidException($"idWell: {idWell} does not exist.", nameof(idWell));
|
||||||
return GetTimezone(well);
|
return GetTimezone(well);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetTimezone(Well well, out SimpleTimezoneDto timezone)
|
private SimpleTimezoneDto GetTimezone(WellDto wellDto)
|
||||||
{
|
{
|
||||||
timezone = null;
|
if (wellDto.Timezone is not null)
|
||||||
try
|
return wellDto.Timezone;
|
||||||
{
|
|
||||||
timezone = GetTimezone(well);
|
|
||||||
return timezone is not null;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SimpleTimezoneDto GetTimezone(Well well)
|
if (wellDto.Telemetry is not null)
|
||||||
{
|
|
||||||
if (well == null)
|
|
||||||
throw new ArgumentNullException(nameof(well));
|
|
||||||
|
|
||||||
if (well.Timezone is not null)
|
|
||||||
return well.Timezone.Adapt<SimpleTimezoneDto>();
|
|
||||||
|
|
||||||
if (well.Telemetry is not null)
|
|
||||||
{
|
{
|
||||||
var timezone = telemetryService.GetTimezone(well.Telemetry.Id);
|
var timezone = telemetryService.GetTimezone(wellDto.Telemetry.Id);
|
||||||
if (timezone is not null)
|
if (timezone is not null)
|
||||||
{
|
|
||||||
well.Timezone = timezone.Adapt<SimpleTimezone>();
|
|
||||||
return timezone;
|
return timezone;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var well = GetQuery().FirstOrDefault(w => w.Id == wellDto.Id);
|
||||||
var point = GetCoordinates(well);
|
var point = GetCoordinates(well);
|
||||||
if (point is not null)
|
if (point is not null)
|
||||||
{
|
{
|
||||||
if (point.Timezone is not null)
|
if (point.Timezone is not null)
|
||||||
{
|
{
|
||||||
well.Timezone = point.Timezone;
|
|
||||||
return point.Timezone.Adapt<SimpleTimezoneDto>();
|
return point.Timezone.Adapt<SimpleTimezoneDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,13 +311,12 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
var timezone = timezoneService.GetByCoordinates((double)point.Latitude, (double)point.Longitude);
|
var timezone = timezoneService.GetByCoordinates((double)point.Latitude, (double)point.Longitude);
|
||||||
if (timezone is not null)
|
if (timezone is not null)
|
||||||
{
|
{
|
||||||
well.Timezone = timezone.Adapt<SimpleTimezone>();
|
|
||||||
return timezone;
|
return timezone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception($"Can't find timezone for well {well.Caption} id: {well.Id}");
|
throw new Exception($"Can't find timezone for well {wellDto.Caption} id: {wellDto.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AsbCloudDb.Model.IMapPoint GetCoordinates(Well well)
|
private static AsbCloudDb.Model.IMapPoint GetCoordinates(Well well)
|
||||||
@ -330,9 +327,9 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
if (well.Latitude is not null & well.Longitude is not null)
|
if (well.Latitude is not null & well.Longitude is not null)
|
||||||
return well;
|
return well;
|
||||||
|
|
||||||
if (well.Cluster is null)
|
if (well.IdCluster is null)
|
||||||
throw new Exception($"Can't find coordinates of well {well.Caption} id: {well.Id}");
|
throw new Exception($"Can't find coordinates of well {well.Caption} id: {well.Id}");
|
||||||
|
|
||||||
var cluster = well.Cluster;
|
var cluster = well.Cluster;
|
||||||
|
|
||||||
if (cluster.Latitude is not null & cluster.Longitude is not null)
|
if (cluster.Latitude is not null & cluster.Longitude is not null)
|
||||||
@ -351,7 +348,7 @@ namespace AsbCloudInfrastructure.Services
|
|||||||
|
|
||||||
public DatesRangeDto GetDatesRange(int idWell)
|
public DatesRangeDto GetDatesRange(int idWell)
|
||||||
{
|
{
|
||||||
var well = Cache.FirstOrDefault(w => w.Id == idWell);
|
var well = Get(idWell);
|
||||||
if (well is null)
|
if (well is null)
|
||||||
throw new Exception($"Well id: {idWell} does not exist.");
|
throw new Exception($"Well id: {idWell} does not exist.");
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace AsbCloudInfrastructure
|
|||||||
context.Database.Migrate();
|
context.Database.Migrate();
|
||||||
|
|
||||||
var wellService = scope.ServiceProvider.GetService<IWellService>();
|
var wellService = scope.ServiceProvider.GetService<IWellService>();
|
||||||
wellService.EnshureTimezonesIsSet();
|
wellService.EnshureTimezonesIsSetAsync(System.Threading.CancellationToken.None).Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<ServerGarbageCollection>true</ServerGarbageCollection>
|
||||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||||
<UserSecretsId>80899ceb-210f-4f19-ac56-aa90a5d666d4</UserSecretsId>
|
<UserSecretsId>80899ceb-210f-4f19-ac56-aa90a5d666d4</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -12,9 +12,6 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
{
|
{
|
||||||
public AdminClusterController(ICrudService<ClusterDto> service)
|
public AdminClusterController(ICrudService<ClusterDto> service)
|
||||||
: base(service)
|
: base(service)
|
||||||
{
|
{}
|
||||||
service.Includes.Add(nameof(ClusterDto.Wells));
|
|
||||||
service.Includes.Add(nameof(ClusterDto.Deposit));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
public AdminCompanyController(ICrudService<CompanyDto> service)
|
public AdminCompanyController(ICrudService<CompanyDto> service)
|
||||||
: base(service)
|
: base(service)
|
||||||
{
|
{
|
||||||
service.Includes.Add("CompanyType");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
public AdminDepositController(ICrudService<DepositDto> service)
|
public AdminDepositController(ICrudService<DepositDto> service)
|
||||||
: base(service)
|
: base(service)
|
||||||
{
|
{
|
||||||
service.Includes.Add("Clusters");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
ITelemetryService telemetryService)
|
ITelemetryService telemetryService)
|
||||||
: base(service)
|
: base(service)
|
||||||
{
|
{
|
||||||
service.Includes.Add("Well");
|
|
||||||
this.telemetryService = telemetryService;
|
this.telemetryService = telemetryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers
|
namespace AsbCloudWebApi.Controllers
|
||||||
{
|
{
|
||||||
@ -12,15 +14,13 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
{
|
{
|
||||||
public AdminWellController(IWellService service)
|
public AdminWellController(IWellService service)
|
||||||
: base(service)
|
: base(service)
|
||||||
{
|
{}
|
||||||
service.Includes.Add("Telemetry");
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("EnshureTimezonesIsSet")]
|
[HttpPost("EnshureTimezonesIsSet")]
|
||||||
[Permission]
|
[Permission]
|
||||||
public IActionResult EnsureTimestamps()
|
public async Task<IActionResult> EnsureTimestamps(CancellationToken token)
|
||||||
{
|
{
|
||||||
((IWellService)service).EnshureTimezonesIsSet();
|
await ((IWellService)service).EnshureTimezonesIsSetAsync(token);
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
Forbid();
|
Forbid();
|
||||||
|
|
||||||
var result = await service.UpdateAsync(id, value, token).ConfigureAwait(false);
|
var result = await service.UpdateAsync(id, value, token).ConfigureAwait(false);
|
||||||
if (result == 0)
|
if (result == ICrudService<T>.ErrorIdNotFound)
|
||||||
return BadRequest($"id:{id} does not exist in the db");
|
return BadRequest($"id:{id} does not exist in the db");
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,50 @@
|
|||||||
{
|
{
|
||||||
"files": {
|
"files": {
|
||||||
"main.css": "/static/css/main.c2a82e71.chunk.css",
|
"main.css": "/static/css/main.a0664ea6.chunk.css",
|
||||||
"main.js": "/static/js/main.1a56c0e0.chunk.js",
|
"main.js": "/static/js/main.02d15bac.chunk.js",
|
||||||
"main.js.map": "/static/js/main.1a56c0e0.chunk.js.map",
|
"main.js.map": "/static/js/main.02d15bac.chunk.js.map",
|
||||||
"runtime-main.js": "/static/js/runtime-main.8da12c69.js",
|
"runtime-main.js": "/static/js/runtime-main.83ebcb38.js",
|
||||||
"runtime-main.js.map": "/static/js/runtime-main.8da12c69.js.map",
|
"runtime-main.js.map": "/static/js/runtime-main.83ebcb38.js.map",
|
||||||
"static/js/2.f196b75b.chunk.js": "/static/js/2.f196b75b.chunk.js",
|
"static/js/2.ebe1f792.chunk.js": "/static/js/2.ebe1f792.chunk.js",
|
||||||
"static/js/2.f196b75b.chunk.js.map": "/static/js/2.f196b75b.chunk.js.map",
|
"static/js/2.ebe1f792.chunk.js.map": "/static/js/2.ebe1f792.chunk.js.map",
|
||||||
"static/css/3.f8ac3883.chunk.css": "/static/css/3.f8ac3883.chunk.css",
|
"static/css/3.f8ac3883.chunk.css": "/static/css/3.f8ac3883.chunk.css",
|
||||||
"static/js/3.31b66021.chunk.js": "/static/js/3.31b66021.chunk.js",
|
"static/js/3.a763380a.chunk.js": "/static/js/3.a763380a.chunk.js",
|
||||||
"static/js/3.31b66021.chunk.js.map": "/static/js/3.31b66021.chunk.js.map",
|
"static/js/3.a763380a.chunk.js.map": "/static/js/3.a763380a.chunk.js.map",
|
||||||
"static/css/4.f8ac3883.chunk.css": "/static/css/4.f8ac3883.chunk.css",
|
"static/css/4.f8ac3883.chunk.css": "/static/css/4.f8ac3883.chunk.css",
|
||||||
"static/js/4.1f09e89e.chunk.js": "/static/js/4.1f09e89e.chunk.js",
|
"static/js/4.14deb3a9.chunk.js": "/static/js/4.14deb3a9.chunk.js",
|
||||||
"static/js/4.1f09e89e.chunk.js.map": "/static/js/4.1f09e89e.chunk.js.map",
|
"static/js/4.14deb3a9.chunk.js.map": "/static/js/4.14deb3a9.chunk.js.map",
|
||||||
"static/js/5.ef929bfe.chunk.js": "/static/js/5.ef929bfe.chunk.js",
|
"static/js/5.54daf1dd.chunk.js": "/static/js/5.54daf1dd.chunk.js",
|
||||||
"static/js/5.ef929bfe.chunk.js.map": "/static/js/5.ef929bfe.chunk.js.map",
|
"static/js/5.54daf1dd.chunk.js.map": "/static/js/5.54daf1dd.chunk.js.map",
|
||||||
"static/js/6.88051835.chunk.js": "/static/js/6.88051835.chunk.js",
|
"static/js/6.2f64a277.chunk.js": "/static/js/6.2f64a277.chunk.js",
|
||||||
"static/js/6.88051835.chunk.js.map": "/static/js/6.88051835.chunk.js.map",
|
"static/js/6.2f64a277.chunk.js.map": "/static/js/6.2f64a277.chunk.js.map",
|
||||||
"static/js/7.4f3c315a.chunk.js": "/static/js/7.4f3c315a.chunk.js",
|
"static/js/7.8c90cea1.chunk.js": "/static/js/7.8c90cea1.chunk.js",
|
||||||
"static/js/7.4f3c315a.chunk.js.map": "/static/js/7.4f3c315a.chunk.js.map",
|
"static/js/7.8c90cea1.chunk.js.map": "/static/js/7.8c90cea1.chunk.js.map",
|
||||||
"static/js/8.8e9a1dc7.chunk.js": "/static/js/8.8e9a1dc7.chunk.js",
|
"static/js/8.6e937634.chunk.js": "/static/js/8.6e937634.chunk.js",
|
||||||
"static/js/8.8e9a1dc7.chunk.js.map": "/static/js/8.8e9a1dc7.chunk.js.map",
|
"static/js/8.6e937634.chunk.js.map": "/static/js/8.6e937634.chunk.js.map",
|
||||||
"static/js/9.71667cac.chunk.js": "/static/js/9.71667cac.chunk.js",
|
"static/js/9.3b35991a.chunk.js": "/static/js/9.3b35991a.chunk.js",
|
||||||
"static/js/9.71667cac.chunk.js.map": "/static/js/9.71667cac.chunk.js.map",
|
"static/js/9.3b35991a.chunk.js.map": "/static/js/9.3b35991a.chunk.js.map",
|
||||||
"static/js/10.e5247b1b.chunk.js": "/static/js/10.e5247b1b.chunk.js",
|
"static/js/10.69527c71.chunk.js": "/static/js/10.69527c71.chunk.js",
|
||||||
"static/js/10.e5247b1b.chunk.js.map": "/static/js/10.e5247b1b.chunk.js.map",
|
"static/js/10.69527c71.chunk.js.map": "/static/js/10.69527c71.chunk.js.map",
|
||||||
"static/js/11.70112c8f.chunk.js": "/static/js/11.70112c8f.chunk.js",
|
"static/js/11.f8320c6a.chunk.js": "/static/js/11.f8320c6a.chunk.js",
|
||||||
"static/js/11.70112c8f.chunk.js.map": "/static/js/11.70112c8f.chunk.js.map",
|
"static/js/11.f8320c6a.chunk.js.map": "/static/js/11.f8320c6a.chunk.js.map",
|
||||||
"static/js/12.2265b74f.chunk.js": "/static/js/12.2265b74f.chunk.js",
|
"static/js/12.7a9654fd.chunk.js": "/static/js/12.7a9654fd.chunk.js",
|
||||||
"static/js/12.2265b74f.chunk.js.map": "/static/js/12.2265b74f.chunk.js.map",
|
"static/js/12.7a9654fd.chunk.js.map": "/static/js/12.7a9654fd.chunk.js.map",
|
||||||
"static/js/13.063a16c9.chunk.js": "/static/js/13.063a16c9.chunk.js",
|
"static/js/13.35247644.chunk.js": "/static/js/13.35247644.chunk.js",
|
||||||
"static/js/13.063a16c9.chunk.js.map": "/static/js/13.063a16c9.chunk.js.map",
|
"static/js/13.35247644.chunk.js.map": "/static/js/13.35247644.chunk.js.map",
|
||||||
"static/js/14.50a284b1.chunk.js": "/static/js/14.50a284b1.chunk.js",
|
"static/js/14.0f147158.chunk.js": "/static/js/14.0f147158.chunk.js",
|
||||||
"static/js/14.50a284b1.chunk.js.map": "/static/js/14.50a284b1.chunk.js.map",
|
"static/js/14.0f147158.chunk.js.map": "/static/js/14.0f147158.chunk.js.map",
|
||||||
"index.html": "/index.html",
|
"index.html": "/index.html",
|
||||||
"static/css/3.f8ac3883.chunk.css.map": "/static/css/3.f8ac3883.chunk.css.map",
|
"static/css/3.f8ac3883.chunk.css.map": "/static/css/3.f8ac3883.chunk.css.map",
|
||||||
"static/css/4.f8ac3883.chunk.css.map": "/static/css/4.f8ac3883.chunk.css.map",
|
"static/css/4.f8ac3883.chunk.css.map": "/static/css/4.f8ac3883.chunk.css.map",
|
||||||
"static/css/main.c2a82e71.chunk.css.map": "/static/css/main.c2a82e71.chunk.css.map",
|
"static/css/main.a0664ea6.chunk.css.map": "/static/css/main.a0664ea6.chunk.css.map",
|
||||||
"static/js/2.f196b75b.chunk.js.LICENSE.txt": "/static/js/2.f196b75b.chunk.js.LICENSE.txt",
|
"static/js/2.ebe1f792.chunk.js.LICENSE.txt": "/static/js/2.ebe1f792.chunk.js.LICENSE.txt",
|
||||||
"static/media/ClusterIcon.f85713df.svg": "/static/media/ClusterIcon.f85713df.svg",
|
"static/media/ClusterIcon.f85713df.svg": "/static/media/ClusterIcon.f85713df.svg",
|
||||||
"static/media/DepositIcon.9688e406.svg": "/static/media/DepositIcon.9688e406.svg"
|
"static/media/DepositIcon.9688e406.svg": "/static/media/DepositIcon.9688e406.svg"
|
||||||
},
|
},
|
||||||
"entrypoints": [
|
"entrypoints": [
|
||||||
"static/js/runtime-main.8da12c69.js",
|
"static/js/runtime-main.83ebcb38.js",
|
||||||
"static/js/2.f196b75b.chunk.js",
|
"static/js/2.ebe1f792.chunk.js",
|
||||||
"static/css/main.c2a82e71.chunk.css",
|
"static/css/main.a0664ea6.chunk.css",
|
||||||
"static/js/main.1a56c0e0.chunk.js"
|
"static/js/main.02d15bac.chunk.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1 +1 @@
|
|||||||
<!doctype html><html lang="ru"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="white"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="white"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/><meta name="description" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><link rel="manifest" href="/manifest.json"/><title>АСБ Vision</title><link href="/static/css/main.c2a82e71.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function t(t){for(var n,o,u=t[0],f=t[1],i=t[2],l=0,d=[];l<u.length;l++)o=u[l],Object.prototype.hasOwnProperty.call(a,o)&&a[o]&&d.push(a[o][0]),a[o]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(s&&s(t);d.length;)d.shift()();return c.push.apply(c,i||[]),r()}function r(){for(var e,t=0;t<c.length;t++){for(var r=c[t],n=!0,o=1;o<r.length;o++){var f=r[o];0!==a[f]&&(n=!1)}n&&(c.splice(t--,1),e=u(u.s=r[0]))}return e}var n={},o={1:0},a={1:0},c=[];function u(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,u),r.l=!0,r.exports}u.e=function(e){var t=[];o[e]?t.push(o[e]):0!==o[e]&&{3:1,4:1}[e]&&t.push(o[e]=new Promise((function(t,r){for(var n="static/css/"+({}[e]||e)+"."+{3:"f8ac3883",4:"f8ac3883",5:"31d6cfe0",6:"31d6cfe0",7:"31d6cfe0",8:"31d6cfe0",9:"31d6cfe0",10:"31d6cfe0",11:"31d6cfe0",12:"31d6cfe0",13:"31d6cfe0",14:"31d6cfe0"}[e]+".chunk.css",a=u.p+n,c=document.getElementsByTagName("link"),f=0;f<c.length;f++){var i=(s=c[f]).getAttribute("data-href")||s.getAttribute("href");if("stylesheet"===s.rel&&(i===n||i===a))return t()}var l=document.getElementsByTagName("style");for(f=0;f<l.length;f++){var s;if((i=(s=l[f]).getAttribute("data-href"))===n||i===a)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var n=t&&t.target&&t.target.src||a,c=new Error("Loading CSS chunk "+e+" failed.\n("+n+")");c.code="CSS_CHUNK_LOAD_FAILED",c.request=n,delete o[e],d.parentNode.removeChild(d),r(c)},d.href=a,document.getElementsByTagName("head")[0].appendChild(d)})).then((function(){o[e]=0})));var r=a[e];if(0!==r)if(r)t.push(r[2]);else{var n=new Promise((function(t,n){r=a[e]=[t,n]}));t.push(r[2]=n);var c,f=document.createElement("script");f.charset="utf-8",f.timeout=120,u.nc&&f.setAttribute("nonce",u.nc),f.src=function(e){return u.p+"static/js/"+({}[e]||e)+"."+{3:"31b66021",4:"1f09e89e",5:"ef929bfe",6:"88051835",7:"4f3c315a",8:"8e9a1dc7",9:"71667cac",10:"e5247b1b",11:"70112c8f",12:"2265b74f",13:"063a16c9",14:"50a284b1"}[e]+".chunk.js"}(e);var i=new Error;c=function(t){f.onerror=f.onload=null,clearTimeout(l);var r=a[e];if(0!==r){if(r){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+e+" failed.\n("+n+": "+o+")",i.name="ChunkLoadError",i.type=n,i.request=o,r[1](i)}a[e]=void 0}};var l=setTimeout((function(){c({type:"timeout",target:f})}),12e4);f.onerror=f.onload=c,document.head.appendChild(f)}return Promise.all(t)},u.m=e,u.c=n,u.d=function(e,t,r){u.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,t){if(1&t&&(e=u(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(u.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)u.d(r,n,function(t){return e[t]}.bind(null,n));return r},u.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(t,"a",t),t},u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.p="/",u.oe=function(e){throw console.error(e),e};var f=this.webpackJsonpasb_cloud_front_react=this.webpackJsonpasb_cloud_front_react||[],i=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var s=i;r()}([])</script><script src="/static/js/2.f196b75b.chunk.js"></script><script src="/static/js/main.1a56c0e0.chunk.js"></script></body></html>
|
<!doctype html><html lang="ru"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="white"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="white"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="black"/><meta name="description" content="Онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"/><link rel="manifest" href="/manifest.json"/><title>АСБ Vision</title><link href="/static/css/main.a0664ea6.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function t(t){for(var n,o,u=t[0],f=t[1],i=t[2],l=0,d=[];l<u.length;l++)o=u[l],Object.prototype.hasOwnProperty.call(a,o)&&a[o]&&d.push(a[o][0]),a[o]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(s&&s(t);d.length;)d.shift()();return c.push.apply(c,i||[]),r()}function r(){for(var e,t=0;t<c.length;t++){for(var r=c[t],n=!0,o=1;o<r.length;o++){var f=r[o];0!==a[f]&&(n=!1)}n&&(c.splice(t--,1),e=u(u.s=r[0]))}return e}var n={},o={1:0},a={1:0},c=[];function u(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,u),r.l=!0,r.exports}u.e=function(e){var t=[];o[e]?t.push(o[e]):0!==o[e]&&{3:1,4:1}[e]&&t.push(o[e]=new Promise((function(t,r){for(var n="static/css/"+({}[e]||e)+"."+{3:"f8ac3883",4:"f8ac3883",5:"31d6cfe0",6:"31d6cfe0",7:"31d6cfe0",8:"31d6cfe0",9:"31d6cfe0",10:"31d6cfe0",11:"31d6cfe0",12:"31d6cfe0",13:"31d6cfe0",14:"31d6cfe0"}[e]+".chunk.css",a=u.p+n,c=document.getElementsByTagName("link"),f=0;f<c.length;f++){var i=(s=c[f]).getAttribute("data-href")||s.getAttribute("href");if("stylesheet"===s.rel&&(i===n||i===a))return t()}var l=document.getElementsByTagName("style");for(f=0;f<l.length;f++){var s;if((i=(s=l[f]).getAttribute("data-href"))===n||i===a)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var n=t&&t.target&&t.target.src||a,c=new Error("Loading CSS chunk "+e+" failed.\n("+n+")");c.code="CSS_CHUNK_LOAD_FAILED",c.request=n,delete o[e],d.parentNode.removeChild(d),r(c)},d.href=a,document.getElementsByTagName("head")[0].appendChild(d)})).then((function(){o[e]=0})));var r=a[e];if(0!==r)if(r)t.push(r[2]);else{var n=new Promise((function(t,n){r=a[e]=[t,n]}));t.push(r[2]=n);var c,f=document.createElement("script");f.charset="utf-8",f.timeout=120,u.nc&&f.setAttribute("nonce",u.nc),f.src=function(e){return u.p+"static/js/"+({}[e]||e)+"."+{3:"a763380a",4:"14deb3a9",5:"54daf1dd",6:"2f64a277",7:"8c90cea1",8:"6e937634",9:"3b35991a",10:"69527c71",11:"f8320c6a",12:"7a9654fd",13:"35247644",14:"0f147158"}[e]+".chunk.js"}(e);var i=new Error;c=function(t){f.onerror=f.onload=null,clearTimeout(l);var r=a[e];if(0!==r){if(r){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+e+" failed.\n("+n+": "+o+")",i.name="ChunkLoadError",i.type=n,i.request=o,r[1](i)}a[e]=void 0}};var l=setTimeout((function(){c({type:"timeout",target:f})}),12e4);f.onerror=f.onload=c,document.head.appendChild(f)}return Promise.all(t)},u.m=e,u.c=n,u.d=function(e,t,r){u.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,t){if(1&t&&(e=u(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(u.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)u.d(r,n,function(t){return e[t]}.bind(null,n));return r},u.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(t,"a",t),t},u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.p="/",u.oe=function(e){throw console.error(e),e};var f=this.webpackJsonpasb_cloud_front_react=this.webpackJsonpasb_cloud_front_react||[],i=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var s=i;r()}([])</script><script src="/static/js/2.ebe1f792.chunk.js"></script><script src="/static/js/main.02d15bac.chunk.js"></script></body></html>
|
Loading…
Reference in New Issue
Block a user