From 1e7f5fe65487b730955c309fa24145c623b0e23b Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 1 Jun 2022 17:52:26 +0500 Subject: [PATCH] Doc --- .../Comparators/TelemetryUserDtoComparer.cs | 3 + AsbCloudApp/Data/ClusterDto.cs | 36 +- AsbCloudApp/Data/ClusterRopStatDto.cs | 10 + AsbCloudApp/Data/CompanyDto.cs | 17 +- AsbCloudApp/Data/CompanyTypeDto.cs | 8 + AsbCloudApp/Data/DatesRangeDto.cs | 10 + AsbCloudApp/Data/DepositDto.cs | 20 + AsbCloudApp/Data/DrillFlowChartDto.cs | 3 + AsbCloudApp/Data/DrillingProgramPartDto.cs | 30 ++ AsbCloudApp/Data/IId.cs | 6 + AsbCloudApp/Data/IMapPoint.cs | 14 + AsbCloudApp/Data/ITelemetryData.cs | 9 + AsbCloudApp/Data/TelemetryDto.cs | 22 + AsbCloudApp/Data/WITS/Record1Dto.cs | 16 +- AsbCloudApp/Data/WITS/Record7Dto.cs | 10 +- AsbCloudApp/Data/WITS/Record8Dto.cs | 18 +- AsbCloudApp/Data/WellDto.cs | 16 +- AsbCloudApp/Services/ICrudService.cs | 58 ++- ...ions.cs => EfCacheDictionaryExtensions.cs} | 0 .../Services/Cache/EfCacheL2.cs | 411 ------------------ .../Services/CrudServiceBase.cs | 9 - ConsoleApp1/Properties/launchSettings.json | 8 + 22 files changed, 272 insertions(+), 462 deletions(-) rename AsbCloudInfrastructure/EfCache/{EfCacheWithKeyExtensions.cs => EfCacheDictionaryExtensions.cs} (100%) delete mode 100644 AsbCloudInfrastructure/Services/Cache/EfCacheL2.cs create mode 100644 ConsoleApp1/Properties/launchSettings.json diff --git a/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs b/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs index ad8f3239..42ed1e86 100644 --- a/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs +++ b/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; namespace AsbCloudApp.Comparators { + /// public class TelemetryUserDtoComparer : IEqualityComparer { + /// public bool Equals(TelemetryUserDto prevUser, TelemetryUserDto nextUser) { if (prevUser is null || nextUser is null) @@ -15,6 +17,7 @@ namespace AsbCloudApp.Comparators return false; } + /// public int GetHashCode(TelemetryUserDto user) => user.Id.GetHashCode(); } } diff --git a/AsbCloudApp/Data/ClusterDto.cs b/AsbCloudApp/Data/ClusterDto.cs index 1f2eb2c7..8a9a95e6 100644 --- a/AsbCloudApp/Data/ClusterDto.cs +++ b/AsbCloudApp/Data/ClusterDto.cs @@ -2,15 +2,43 @@ namespace AsbCloudApp.Data { +#nullable enable + /// + /// DTO кустов + /// public class ClusterDto : IMapPoint, IId { + /// public int Id { get; set; } - public string Caption { get; set; } + + /// + /// Название + /// + public string Caption { get; set; } = null!; + + /// public double? Latitude { get; set; } + + /// public double? Longitude { get; set; } - public SimpleTimezoneDto Timezone { get; set; } + + /// + public SimpleTimezoneDto Timezone { get; set; } = null!; + + /// + /// ИД месторождения, необязательный + /// public int? IdDeposit { get; set; } - public DepositBaseDto Deposit { get; set; } - public IEnumerable Wells { get; set; } + + /// + /// DTO месторождения + /// + public DepositBaseDto? Deposit { get; set; } + + /// + /// Список скважин куста + /// + public IEnumerable Wells { get; set; } = null!; } +#nullable disable } diff --git a/AsbCloudApp/Data/ClusterRopStatDto.cs b/AsbCloudApp/Data/ClusterRopStatDto.cs index 92af0004..abc8de19 100644 --- a/AsbCloudApp/Data/ClusterRopStatDto.cs +++ b/AsbCloudApp/Data/ClusterRopStatDto.cs @@ -1,8 +1,18 @@ namespace AsbCloudApp.Data { + /// + /// () + /// public class ClusterRopStatDto { + /// + /// . + /// public double RopMax { get; set; } + + /// + /// + /// public double RopAverage { get; set; } } } \ No newline at end of file diff --git a/AsbCloudApp/Data/CompanyDto.cs b/AsbCloudApp/Data/CompanyDto.cs index 38b6f9fc..b7698e36 100644 --- a/AsbCloudApp/Data/CompanyDto.cs +++ b/AsbCloudApp/Data/CompanyDto.cs @@ -1,11 +1,26 @@ namespace AsbCloudApp.Data { - + /// + /// DTO компании + /// public class CompanyDto : IId { + /// public int Id { get; set; } + + /// + /// Название + /// public string Caption { get; set; } + + /// + /// ИД типа компании + /// public int IdCompanyType { get; set; } + + /// + /// Название типа компании + /// public string CompanyTypeCaption { get; set; } } } diff --git a/AsbCloudApp/Data/CompanyTypeDto.cs b/AsbCloudApp/Data/CompanyTypeDto.cs index 00926724..a2a83697 100644 --- a/AsbCloudApp/Data/CompanyTypeDto.cs +++ b/AsbCloudApp/Data/CompanyTypeDto.cs @@ -1,8 +1,16 @@ namespace AsbCloudApp.Data { + /// + /// DTO тип компании + /// public class CompanyTypeDto : IId { + /// public int Id { get; set; } + + /// + /// Название типа компании + /// public string Caption { get; set; } } diff --git a/AsbCloudApp/Data/DatesRangeDto.cs b/AsbCloudApp/Data/DatesRangeDto.cs index 8df4776b..64a01263 100644 --- a/AsbCloudApp/Data/DatesRangeDto.cs +++ b/AsbCloudApp/Data/DatesRangeDto.cs @@ -2,9 +2,19 @@ namespace AsbCloudApp.Data { + /// + /// Диапазон дат + /// public class DatesRangeDto { + /// + /// Дата начала диапазона + /// public DateTime From { get; set; } + + /// + /// Дата окончания диапазона + /// public DateTime To { get; set; } } } diff --git a/AsbCloudApp/Data/DepositDto.cs b/AsbCloudApp/Data/DepositDto.cs index be0200fd..d15c2048 100644 --- a/AsbCloudApp/Data/DepositDto.cs +++ b/AsbCloudApp/Data/DepositDto.cs @@ -2,17 +2,37 @@ namespace AsbCloudApp.Data { + /// + /// DTO Месторождения + /// public class DepositBaseDto : IMapPoint, IId { + /// public int Id { get; set; } + + /// + /// Название + /// public string Caption { get; set; } + + /// public double? Latitude { get; set; } + + /// public double? Longitude { get; set; } + + /// public SimpleTimezoneDto Timezone { get; set; } } + /// + /// DTO Месторождения с кустами + /// public class DepositDto : DepositBaseDto { + /// + /// Кусты месторождения + /// public IEnumerable Clusters { get; set; } } } diff --git a/AsbCloudApp/Data/DrillFlowChartDto.cs b/AsbCloudApp/Data/DrillFlowChartDto.cs index 55e14919..af6dfe8d 100644 --- a/AsbCloudApp/Data/DrillFlowChartDto.cs +++ b/AsbCloudApp/Data/DrillFlowChartDto.cs @@ -7,6 +7,9 @@ namespace AsbCloudApp.Data /// public class DrillFlowChartDto : IId { + /// + /// + /// public int Id { get; set; } /// diff --git a/AsbCloudApp/Data/DrillingProgramPartDto.cs b/AsbCloudApp/Data/DrillingProgramPartDto.cs index f2714de9..9800bad4 100644 --- a/AsbCloudApp/Data/DrillingProgramPartDto.cs +++ b/AsbCloudApp/Data/DrillingProgramPartDto.cs @@ -2,9 +2,19 @@ namespace AsbCloudApp.Data { + /// + /// Часть программы бурения + /// public class DrillingProgramPartDto { + /// + /// Название + /// public string Name { get; set; } + + /// + /// ИД категории файла + /// public int IdFileCategory { get; set; } /// @@ -13,10 +23,30 @@ namespace AsbCloudApp.Data /// 2 - completely approved /// public int IdState { get; set; } + + /// + /// Публикаторы. Могут загружать файл этой категории + /// public IEnumerable Publishers { get; set; } + + /// + /// Согласованты. Могут согласовывать загруженные файлы этой категории + /// public IEnumerable Approvers { get; set; } + + /// + /// Разрешение для текущего пользователя согласовывать документ + /// public bool PermissionToApprove { get; set; } + + /// + /// Разрешение для текущего пользователя загружать документ + /// public bool PermissionToUpload { get; set; } + + /// + /// Ссылка на документ. + /// public FileInfoDto File { get; set; } } } diff --git a/AsbCloudApp/Data/IId.cs b/AsbCloudApp/Data/IId.cs index 77e45a4d..e5ad455e 100644 --- a/AsbCloudApp/Data/IId.cs +++ b/AsbCloudApp/Data/IId.cs @@ -1,7 +1,13 @@ namespace AsbCloudApp.Data { + /// + /// Интерфейс данных с Id + /// public interface IId { + /// + /// Идентификатор БД + /// public int Id { get; set; } } } diff --git a/AsbCloudApp/Data/IMapPoint.cs b/AsbCloudApp/Data/IMapPoint.cs index 4ab08239..f71bd7fa 100644 --- a/AsbCloudApp/Data/IMapPoint.cs +++ b/AsbCloudApp/Data/IMapPoint.cs @@ -1,9 +1,23 @@ namespace AsbCloudApp.Data { + /// + /// точка на карте + /// public interface IMapPoint { + /// + /// Широта + /// double? Latitude { get; set; } + + /// + /// Широта + /// double? Longitude { get; set; } + + /// + /// Часовой пояс + /// SimpleTimezoneDto Timezone { get; set; } } } diff --git a/AsbCloudApp/Data/ITelemetryData.cs b/AsbCloudApp/Data/ITelemetryData.cs index 61d70da7..2838aef0 100644 --- a/AsbCloudApp/Data/ITelemetryData.cs +++ b/AsbCloudApp/Data/ITelemetryData.cs @@ -2,10 +2,19 @@ namespace AsbCloudApp.Data { + /// + /// Интерфейс записи данных телеметрии + /// public interface ITelemetryData { + /// + /// ИД телеметрии + /// int IdTelemetry { get; set; } + /// + /// Отметка времени для этой записи + /// DateTime DateTime { get; set; } } } diff --git a/AsbCloudApp/Data/TelemetryDto.cs b/AsbCloudApp/Data/TelemetryDto.cs index 804d7210..d71afdd4 100644 --- a/AsbCloudApp/Data/TelemetryDto.cs +++ b/AsbCloudApp/Data/TelemetryDto.cs @@ -2,16 +2,38 @@ namespace AsbCloudApp.Data { + /// + /// DTO телеметрии панели + /// public class TelemetryBaseDto : IId { + /// public int Id { get; set; } + + /// + /// уникальный идентификатор телеметрии по которому панель оператора присылает данные + /// public string RemoteUid { get; set; } + + /// + /// информация о бурении, панели оператора и контроллерах + /// public TelemetryInfoDto Info { get; set; } } + /// + /// DTO телеметрии панели с скважиной + /// public class TelemetryDto : TelemetryBaseDto { + /// + /// ИД скважины + /// public int? IdWell { get; set; } + + /// + /// DTO скважины + /// public WellInfoDto Well { get; set; } } } diff --git a/AsbCloudApp/Data/WITS/Record1Dto.cs b/AsbCloudApp/Data/WITS/Record1Dto.cs index ca79211d..28a0aaa2 100644 --- a/AsbCloudApp/Data/WITS/Record1Dto.cs +++ b/AsbCloudApp/Data/WITS/Record1Dto.cs @@ -14,7 +14,7 @@ namespace AsbCloudApp.Data.WITS /// LongMnemonic = "DEPTBITM", /// ShortMnemonic = "DBTM", /// Description = "Depth Bit (meas)", - /// Description2 = "Code indicating what activity is currently being performed on the rig. IT IS ESSENTIAL that this information be as accurate and current as possible. Acceptible codes are shownhere", + /// Description2 = "Code indicating what activity is currently being performed on the rig. IT IS ESSENTIAL that this information be as accurate and current as possible. Acceptable codes are shown here", /// FPSUnits = "F", /// MetricUnits = "M", /// Length = 4, @@ -103,7 +103,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 14, /// LongMnemonic = "HKLA", /// ShortMnemonic = "HKLA", - /// Description = "Hookload (avg)", + /// Description = "Hook-load (avg)", /// Description2 = "", /// FPSUnits = "KLB", /// MetricUnits = "KDN", @@ -118,7 +118,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 15, /// LongMnemonic = "HKLX", /// ShortMnemonic = "HKLX", - /// Description = "Hookload (max)", + /// Description = "Hook-load (max)", /// Description2 = "", /// FPSUnits = "KLB", /// MetricUnits = "KDN", @@ -508,7 +508,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 41, /// LongMnemonic = "SPARE1", /// ShortMnemonic = "SPR1", - /// Description = "< SPARE 1>", + /// Description = "SPARE 1", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -523,7 +523,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 42, /// LongMnemonic = "SPARE2", /// ShortMnemonic = "SPR2", - /// Description = "< SPARE 2>", + /// Description = "SPARE 2", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -538,7 +538,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 43, /// LongMnemonic = "SPARE3", /// ShortMnemonic = "SPR3", - /// Description = "< SPARE 3>", + /// Description = "SPARE 3", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -553,7 +553,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 44, /// LongMnemonic = "SPARE4", /// ShortMnemonic = "SPR4", - /// Description = "< SPARE 4>", + /// Description = "SPARE 4", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -568,7 +568,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 45, /// LongMnemonic = "SPARE5", /// ShortMnemonic = "SPR5", - /// Description = "< SPARE 5>", + /// Description = "SPARE 5", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", diff --git a/AsbCloudApp/Data/WITS/Record7Dto.cs b/AsbCloudApp/Data/WITS/Record7Dto.cs index 61c3f99d..43c370d1 100644 --- a/AsbCloudApp/Data/WITS/Record7Dto.cs +++ b/AsbCloudApp/Data/WITS/Record7Dto.cs @@ -224,7 +224,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 22, /// LongMnemonic = "SPARE1", /// ShortMnemonic = "SPR1", - /// Description = "< SPARE 1>", + /// Description = "SPARE 1", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -239,7 +239,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 23, /// LongMnemonic = "SPARE2", /// ShortMnemonic = "SPR2", - /// Description = "< SPARE 2>", + /// Description = "SPARE 2", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -254,7 +254,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 24, /// LongMnemonic = "SPARE3", /// ShortMnemonic = "SPR3", - /// Description = "< SPARE 3>", + /// Description = "SPARE 3", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -269,7 +269,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 25, /// LongMnemonic = "SPARE4", /// ShortMnemonic = "SPR4", - /// Description = "< SPARE 4>", + /// Description = "SPARE 4", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -284,7 +284,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 26, /// LongMnemonic = "SPARE5", /// ShortMnemonic = "SPR5", - /// Description = "< SPARE 5>", + /// Description = "SPARE 5", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "---", diff --git a/AsbCloudApp/Data/WITS/Record8Dto.cs b/AsbCloudApp/Data/WITS/Record8Dto.cs index 38a83aad..7a8d7331 100644 --- a/AsbCloudApp/Data/WITS/Record8Dto.cs +++ b/AsbCloudApp/Data/WITS/Record8Dto.cs @@ -599,7 +599,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 47, /// LongMnemonic = "SPARE1", /// ShortMnemonic = "SPR1", - /// Description = "< SPARE 1>", + /// Description = "SPARE 1", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -614,7 +614,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 48, /// LongMnemonic = "SPARE2", /// ShortMnemonic = "SPR2", - /// Description = "< SPARE 2>", + /// Description = "SPARE 2", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -629,7 +629,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 49, /// LongMnemonic = "SPARE3", /// ShortMnemonic = "SPR3", - /// Description = "< SPARE 3>", + /// Description = "SPARE 3", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -644,7 +644,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 50, /// LongMnemonic = "SPARE4", /// ShortMnemonic = "SPR4", - /// Description = "< SPARE 4>", + /// Description = "SPARE 4", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -659,7 +659,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 51, /// LongMnemonic = "SPARE5", /// ShortMnemonic = "SPR5", - /// Description = "< SPARE 5>", + /// Description = "SPARE 5", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "---", @@ -674,7 +674,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 52, /// LongMnemonic = "SPARE6", /// ShortMnemonic = "SPR6", - /// Description = "< SPARE 6>", + /// Description = "SPARE 6", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -689,7 +689,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 53, /// LongMnemonic = "SPARE7", /// ShortMnemonic = "SPR7", - /// Description = "< SPARE 7>", + /// Description = "SPARE 7", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -704,7 +704,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 54, /// LongMnemonic = "SPARE8", /// ShortMnemonic = "SPR8", - /// Description = "< SPARE 8>", + /// Description = "SPARE 8", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", @@ -719,7 +719,7 @@ namespace AsbCloudApp.Data.WITS /// ItemId = 55, /// LongMnemonic = "SPARE9", /// ShortMnemonic = "SPR9", - /// Description = "< SPARE 9>", + /// Description = "SPARE 9", /// Description2 = "", /// FPSUnits = "----", /// MetricUnits = "----", diff --git a/AsbCloudApp/Data/WellDto.cs b/AsbCloudApp/Data/WellDto.cs index c1b9a22b..695c14c3 100644 --- a/AsbCloudApp/Data/WellDto.cs +++ b/AsbCloudApp/Data/WellDto.cs @@ -8,24 +8,16 @@ namespace AsbCloudApp.Data /// public class WellDto : WellInfoDto, IMapPoint, IId { - /// - /// ID в БД - /// + /// public int Id { get; set; } - /// - /// Широта - /// + /// public double? Latitude { get; set; } - /// - /// долгота - /// + /// public double? Longitude { get; set; } - /// - /// Упрощенная временная зона - /// + /// public SimpleTimezoneDto Timezone { get; set; } /// diff --git a/AsbCloudApp/Services/ICrudService.cs b/AsbCloudApp/Services/ICrudService.cs index aa1f8b41..5e0919b7 100644 --- a/AsbCloudApp/Services/ICrudService.cs +++ b/AsbCloudApp/Services/ICrudService.cs @@ -1,19 +1,71 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace AsbCloudApp.Services { +#nullable enable + /// + /// Сервис получения, добавления, изменения, удаления данных + /// + /// public interface ICrudService where Tdto : Data.IId { + /// + /// Включение связных данных + /// ISet Includes { get; } + + /// + /// Добавление новой записи + /// + /// + /// + /// Id новой записи Task InsertAsync(Tdto newItem, CancellationToken token = default); + + /// + /// Добавление нескольких записей + /// + /// + /// + /// количество добавленных Task InsertRangeAsync(IEnumerable newItems, CancellationToken token = default); + + /// + /// Получение всех записей + /// + /// + /// + [Obsolete("Небезопасный метод, может выполняться бесконечно долго")] Task> GetAllAsync(CancellationToken token = default); - Task GetAsync(int id, CancellationToken token = default); + + /// + /// Получить запись по id + /// + /// + /// + /// + Task GetAsync(int id, CancellationToken token = default); + + /// + /// Отредактировать запись + /// + /// + /// + /// + /// Task UpdateAsync(int id, Tdto item, CancellationToken token = default); + + /// + /// Удалить запись + /// + /// + /// + /// Task DeleteAsync(int id, CancellationToken token = default); - Task DeleteAsync(IEnumerable ids, CancellationToken token = default); } +#nullable disable } \ No newline at end of file diff --git a/AsbCloudInfrastructure/EfCache/EfCacheWithKeyExtensions.cs b/AsbCloudInfrastructure/EfCache/EfCacheDictionaryExtensions.cs similarity index 100% rename from AsbCloudInfrastructure/EfCache/EfCacheWithKeyExtensions.cs rename to AsbCloudInfrastructure/EfCache/EfCacheDictionaryExtensions.cs diff --git a/AsbCloudInfrastructure/Services/Cache/EfCacheL2.cs b/AsbCloudInfrastructure/Services/Cache/EfCacheL2.cs deleted file mode 100644 index cd147d92..00000000 --- a/AsbCloudInfrastructure/Services/Cache/EfCacheL2.cs +++ /dev/null @@ -1,411 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudInfrastructure.Services.Cache -{ -#nullable enable - /// - /// Кеширование запросов EF. - /// - public static class EfCacheL2 - { - /// - /// Кол-во обращений к БД. - /// - public static int CountOfRequestsToDB = 0; - private static readonly Dictionary caches = new(16); - private static readonly TimeSpan semaphoreTimeout = TimeSpan.FromSeconds(25); - private static readonly SemaphoreSlim semaphore = new(1); - private static readonly TimeSpan minCacheTime = TimeSpan.FromSeconds(2); - - private class CacheItem - { - internal IEnumerable? Data; - internal DateTime DateObsolete; - internal DateTime DateObsoleteTotal; - internal readonly SemaphoreSlim semaphore = new(1); - } - - private static CacheItem GetOrAddCache(string tag, Func valueFactory, TimeSpan obsolete) - { - CacheItem cache; - while (!caches.ContainsKey(tag)) - { - if (semaphore.Wait(0)) - { - try { - cache = new CacheItem(); - - var dateObsolete = DateTime.Now + obsolete; - var dateQueryStart = DateTime.Now; - var data = valueFactory(); - var queryTime = DateTime.Now - dateQueryStart; - - if (dateObsolete - DateTime.Now < minCacheTime) - dateObsolete = DateTime.Now + minCacheTime; - - cache.Data = data; - cache.DateObsolete = dateObsolete; - cache.DateObsoleteTotal = dateObsolete + queryTime + minCacheTime; - caches.Add(tag, cache); - } - catch - { - throw; - } - finally - { - semaphore.Release(); - } - break; - } - else - { - if (semaphore.Wait(semaphoreTimeout)) - { - semaphore.Release(); - } - else - { - semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting cache"); - } - } - } - - cache = caches[tag]; - - if (cache.DateObsolete < DateTime.Now) - { - if (cache.semaphore.Wait(0)) - { - try - { - var dateObsolete = DateTime.Now + obsolete; - var dateQueryStart = DateTime.Now; - var data = valueFactory(); - var queryTime = DateTime.Now - dateQueryStart; - - if (dateObsolete - DateTime.Now < minCacheTime) - dateObsolete = DateTime.Now + minCacheTime; - - cache.Data = data; - cache.DateObsolete = dateObsolete; - cache.DateObsoleteTotal = dateObsolete + queryTime + minCacheTime; - } - catch - { - throw; - } - finally - { - cache.semaphore.Release(); - } - } - else if(cache.DateObsoleteTotal < DateTime.Now) - { - if (cache.semaphore.Wait(semaphoreTimeout)) - { - cache.semaphore.Release(); - } - else - { - cache.semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting cache"); - } - } - } - return cache; - } - - private static async Task GetOrAddCacheAsync(string tag, Func> valueFactoryAsync, TimeSpan obsolete, CancellationToken token) - { - CacheItem cache; - while (!caches.ContainsKey(tag)) - { - if (semaphore.Wait(0)) - { - try - { - cache = new CacheItem(); - - var dateObsolete = DateTime.Now + obsolete; - var dateQueryStart = DateTime.Now; - var data = await valueFactoryAsync(token); - var queryTime = DateTime.Now - dateQueryStart; - - if (dateObsolete - DateTime.Now < minCacheTime) - dateObsolete = DateTime.Now + minCacheTime; - - cache.Data = data; - cache.DateObsolete = dateObsolete; - cache.DateObsoleteTotal = dateObsolete + queryTime + minCacheTime; - caches.Add(tag, cache); - } - catch - { - throw; - } - finally - { - semaphore.Release(); - } - break; - } - else - { - if (await semaphore.WaitAsync(semaphoreTimeout, token)) - { - semaphore.Release(); - } - else - { - semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting cache"); - } - } - } - - cache = caches[tag]; - - if (cache.DateObsolete < DateTime.Now) - { - if (cache.semaphore.Wait(0)) - { - try - { - var dateObsolete = DateTime.Now + obsolete; - var dateQueryStart = DateTime.Now; - var data = await valueFactoryAsync(token); - var queryTime = DateTime.Now - dateQueryStart; - - if (dateObsolete - DateTime.Now < minCacheTime) - dateObsolete = DateTime.Now + minCacheTime; - - cache.Data = data; - cache.DateObsolete = dateObsolete; - cache.DateObsoleteTotal = dateObsolete + queryTime + minCacheTime; - } - catch - { - throw; - } - finally - { - cache.semaphore.Release(); - } - } - else if (cache.DateObsoleteTotal < DateTime.Now) - { - if (await cache.semaphore.WaitAsync(semaphoreTimeout, token)) - { - cache.semaphore.Release(); - } - else - { - cache.semaphore.Release(); - throw new TimeoutException("EfCacheL2.GetOrAddCache. Can't wait too long while getting updated cache"); - } - } - } - return cache; - } - - private static IEnumerable ConvertToIEnumerable(IEnumerable? data) - { - if (data is IEnumerable list) - return list; - else if (data is IDictionary dictionary) - { - System.Diagnostics.Trace.TraceWarning($"ConvertToIEnumerable. Use keyless method on keyed cache. Type: {typeof(T).Name};"); - return (IEnumerable)dictionary.Values; - } - else - throw new NotSupportedException("cache.Data has wrong type."); - } - - private static Dictionary ConvertToDictionary(IEnumerable? data, Func keySelector) - where TKey : notnull - { - if (data is Dictionary dictionary) - return dictionary; - else if (data is IEnumerable enumerable) - { - System.Diagnostics.Trace.TraceWarning($"ConvertToDictionary. Use keyed method on keyless cache. Type: {typeof(T).Name};"); - return enumerable.ToDictionary(keySelector); - } - else - throw new NotSupportedException("cache.Data has wrong type."); - } - - /// - /// Кешировать запрос в List\. - /// Выборки по PK будут работать медленнее, чем при кешировании в виде словаря. - /// - /// - /// - /// Метка кеша - /// Период устаревания данных - /// - public static IEnumerable FromCache(this IQueryable query, string tag, TimeSpan obsolescence) - { - IEnumerable factory () - { - CountOfRequestsToDB++; - return query.ToList(); - } - var cache = GetOrAddCache(tag, factory, obsolescence); - return ConvertToIEnumerable(cache.Data); - } - - /// - /// Асинхронно кешировать запрос в List\. - /// Выборки по PK будут работать медленнее, чем при кешировании в виде словаря. - /// - /// - /// - /// Метка кеша - /// Период устаревания данных - /// - /// - public static async Task> FromCacheAsync(this IQueryable query, string tag, TimeSpan obsolescence, CancellationToken token = default) - { - async Task factory(CancellationToken token) - { - CountOfRequestsToDB++; - return await query.ToListAsync(token); - } - var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token); - return ConvertToIEnumerable(cache.Data); - } - - /// - /// Кешировать запрос в Dictionary\. - /// - /// тип ключа - /// тип значения - /// - /// Метка кеша - /// Период устаревания данных - /// Делегат получения ключа из записи - /// - /// - /// - /// - public static Dictionary FromCache(this IQueryable query, string tag, TimeSpan obsolescence, Func keySelector) - where TKey: notnull - { - IEnumerable factory () - { - CountOfRequestsToDB++; - return query.ToDictionary(keySelector); - } - var cache = GetOrAddCache(tag, factory, obsolescence); - return ConvertToDictionary(cache.Data, keySelector); - } - - /// - /// Асинхронно кешировать запрос в Dictionary\. - /// - /// тип ключа - /// тип значения - /// - /// Метка кеша - /// Период устаревания данных - /// Делегат получения ключа из записи - /// - /// - public static async Task> FromCacheAsync(this IQueryable query, string tag, TimeSpan obsolescence, Func keySelector, CancellationToken token = default) - where TKey : notnull - { - async Task factory(CancellationToken token) - { - CountOfRequestsToDB++; - return await query.ToDictionaryAsync(keySelector, token); - } - var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token); - return ConvertToDictionary(cache.Data, keySelector); - } - - /// - /// Получить запись из кеша по ключу. - /// При отсутствии кеша создаст его для всех записей из query. - /// - /// тип ключа - /// тип значения - /// - /// Метка кеша - /// Период устаревания данных - /// Делегат получения ключа из записи - /// - /// - /// if cache contains trash - public static T? FromCacheGetValueOrDefault(this IQueryable query, string tag, TimeSpan obsolescence, Func keySelector, TKey key) - where TKey : notnull - { - IEnumerable factory() - { - CountOfRequestsToDB++; - return query.ToDictionary(keySelector); - } - var cache = GetOrAddCache(tag, factory, obsolescence); - var data = cache.Data; - if (data is Dictionary dictionary) - return dictionary.GetValueOrDefault(key); - else if (data is IEnumerable enumerable) - { - System.Diagnostics.Trace.TraceWarning($"Use keyed method on keyless cache. Tag: {tag}, type: {typeof(T).Name};"); - return enumerable.FirstOrDefault(v => keySelector(v).Equals(key)); - } - else - throw new NotSupportedException("cache.Data has wrong type."); - } - - /// - /// Асинхронно получить запись из кеша по ключу. - /// При отсутствии кеша создаст его для всех записей из query. - /// - /// тип ключа - /// тип значения - /// - /// Метка кеша - /// Период устаревания данных - /// Делегат получения ключа из записи - /// - /// - /// - /// if cache contains trash - public static async Task FromCacheGetValueOrDefaultAsync(this IQueryable query, string tag, TimeSpan obsolescence, Func keySelector, TKey key, CancellationToken token = default) - where TKey : notnull - { - async Task factory(CancellationToken token) - { - CountOfRequestsToDB++; - return await query.ToDictionaryAsync(keySelector, token); - } - var cache = await GetOrAddCacheAsync(tag, factory, obsolescence, token); - - var data = cache.Data; - if (data is Dictionary dictionary) - return dictionary.GetValueOrDefault(key); - else if (data is IEnumerable enumerable) - { - System.Diagnostics.Trace.TraceWarning($"Use keyed method on keyless cache. Tag: {tag}, type: {typeof(T).Name};"); - return enumerable.FirstOrDefault(v => keySelector(v).Equals(key)); - } - else - throw new NotSupportedException("cache.Data has wrong type."); - } - - public static void DropCache(this IQueryable query, string tag) - { - caches.Remove(tag, out var _); - } - } -#nullable disable -} diff --git a/AsbCloudInfrastructure/Services/CrudServiceBase.cs b/AsbCloudInfrastructure/Services/CrudServiceBase.cs index 7bb64c88..d64ba451 100644 --- a/AsbCloudInfrastructure/Services/CrudServiceBase.cs +++ b/AsbCloudInfrastructure/Services/CrudServiceBase.cs @@ -124,15 +124,6 @@ namespace AsbCloudInfrastructure.Services return context.SaveChangesAsync(token); } - public virtual Task DeleteAsync(IEnumerable ids, CancellationToken token = default) - { - var entities = dbSet.Where(e => ids.Contains(e.Id)).AsNoTracking(); - if (entities == default) - return Task.FromResult(0); - dbSet.RemoveRange(entities); - return context.SaveChangesAsync(token); - } - public virtual TDto Convert(TModel src) => src.Adapt(); public virtual TModel Convert(TDto src) => src.Adapt(); diff --git a/ConsoleApp1/Properties/launchSettings.json b/ConsoleApp1/Properties/launchSettings.json new file mode 100644 index 00000000..33504c94 --- /dev/null +++ b/ConsoleApp1/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WSL": { + "commandName": "WSL2", + "distributionName": "" + } + } +} \ No newline at end of file