diff --git a/DD.Persistence.App/appsettings.Tests.json b/DD.Persistence.App/appsettings.Tests.json
index 72c43d3..e8d3cc4 100644
--- a/DD.Persistence.App/appsettings.Tests.json
+++ b/DD.Persistence.App/appsettings.Tests.json
@@ -1,10 +1,10 @@
{
"DbConnection": {
- "Host": "postgres",
+ "Host": "localhost",
"Port": 5432,
"Database": "persistence",
"Username": "postgres",
- "Password": "postgres"
+ "Password": "q"
},
"NeedUseKeyCloak": false,
"AuthUser": {
diff --git a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs
index c193fc5..9c9f262 100644
--- a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs
+++ b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs
@@ -77,4 +77,28 @@ public interface ITimestampedValuesClient : IDisposable
/// Дискриминатор (идентификатор) набора
///
Task GetDatesRange(Guid discriminatorId, CancellationToken token);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetLast(Guid idDiscriminator, int take, CancellationToken token);
}
\ No newline at end of file
diff --git a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs
index 19fce3f..bafead6 100644
--- a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs
+++ b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs
@@ -4,6 +4,7 @@ using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using Microsoft.Extensions.Logging;
+using System.Collections.Concurrent;
namespace DD.Persistence.Client.Clients;
@@ -18,6 +19,9 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient
this.refitTimestampedSetClient = refitTimestampedSetClientFactory.Create();
}
+ ///
+ private readonly ConcurrentDictionary mapperCache = new();
+
///
public async Task AddRange(Guid discriminatorId, IEnumerable sets, CancellationToken token)
{
@@ -89,6 +93,30 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient
return result;
}
+ ///
+ public async Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token)
+ {
+ var data = await Get(idDiscriminator, geTimestamp, columnNames, skip, take, token);
+ var mapper = GetMapper(idDiscriminator);
+
+ return data.Select(mapper.DeserializeTimeStampedData);
+ }
+
+ ///
+ public async Task> GetLast(Guid idDiscriminator, int take, CancellationToken token)
+ {
+ var data = await GetLast(idDiscriminator, take, token);
+ var mapper = GetMapper(idDiscriminator);
+
+ return data.Select(mapper.DeserializeTimeStampedData);
+ }
+
+ ///
+ private TimestampedSetMapper GetMapper(Guid idDiscriminator)
+ {
+ return (TimestampedSetMapper)mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator));
+ }
+
///
public void Dispose()
{
diff --git a/DD.Persistence.Client/DD.Persistence.Client.csproj b/DD.Persistence.Client/DD.Persistence.Client.csproj
index 3491596..1e0bc4a 100644
--- a/DD.Persistence.Client/DD.Persistence.Client.csproj
+++ b/DD.Persistence.Client/DD.Persistence.Client.csproj
@@ -11,9 +11,9 @@
DD.Persistence.Client
- 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1
+ 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1
- 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1
+ 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1
DD.Persistence.Client
@@ -40,8 +40,8 @@
- 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
- 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
+ 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
+ 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
diff --git a/DD.Persistence.Client/TimestampedSetMapper.cs b/DD.Persistence.Client/TimestampedSetMapper.cs
new file mode 100644
index 0000000..cf7463a
--- /dev/null
+++ b/DD.Persistence.Client/TimestampedSetMapper.cs
@@ -0,0 +1,135 @@
+using DD.Persistence.Models;
+using System.Collections.Concurrent;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Text.Json;
+
+namespace DD.Persistence.Client;
+
+internal abstract class TimestampedSetMapperBase
+{
+ public abstract object Map(TimestampedValuesDto data);
+
+}
+internal class TimestampedSetMapper : TimestampedSetMapperBase
+{
+ private readonly Type entityType = typeof(T);
+ public Guid IdDiscriminator { get; }
+ private readonly ConcurrentDictionary PropertyCache = new();
+
+ public TimestampedSetMapper(Guid idDiscriminator)
+ {
+ IdDiscriminator = idDiscriminator;
+ }
+
+ public override object Map(TimestampedValuesDto data)
+ {
+ return DeserializeTimeStampedData(data)!;
+ }
+
+ public T DeserializeTimeStampedData(TimestampedValuesDto data)
+ {
+
+ if (entityType.IsValueType)
+ return MapStruct(data);
+ else
+ return MapClass(data);
+ }
+
+ private T MapClass(TimestampedValuesDto data)
+ {
+ var entity = (T)RuntimeHelpers.GetUninitializedObject(typeof(T));
+ foreach (var (propertyName, value) in data.Values)
+ {
+ if (value is JsonElement jsonElement)
+ SetPropertyValueFromJson(ref entity, propertyName, jsonElement);
+ }
+ SetPropertyValue(ref entity, "Timestamp", data.Timestamp);
+ return entity;
+ }
+
+ private T MapStruct(TimestampedValuesDto data)
+ {
+ var entity = Activator.CreateInstance();
+ object boxedEntity = entity!;
+ foreach (var (propertyName, value) in data.Values)
+ {
+ if (value is JsonElement jsonElement)
+ SetPropertyValueForStructFromJson(ref boxedEntity, propertyName, jsonElement);
+ }
+ SetPropertyValueForStruct(ref boxedEntity, "Timestamp", data.Timestamp);
+
+ return (T)boxedEntity;
+ }
+
+ private void SetPropertyValueForStructFromJson(ref object entity, string propertyName, JsonElement element)
+ {
+ var property = GetPropertyInfo(propertyName);
+ if (property is null)
+ return;
+
+ try
+ {
+ var value = element.Deserialize(property.PropertyType);
+ property.SetValue(entity, value);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ private void SetPropertyValueForStruct(ref object entity, string propertyName, object value)
+ {
+ var property = GetPropertyInfo(propertyName);
+ if (property is null)
+ return;
+
+ try
+ {
+ var convertedValue = Convert.ChangeType(value, property.PropertyType);
+ property.SetValue(entity, convertedValue);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+
+
+ private void SetPropertyValueFromJson(ref T entity, string propertyName, JsonElement jsonElement)
+ {
+ var property = GetPropertyInfo(propertyName);
+
+ if (property is null)
+ return;
+
+ try
+ {
+ var value = jsonElement.Deserialize(property.PropertyType);
+ property.SetValue(entity, value);
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+ private void SetPropertyValue(ref T entity, string propertyName, object value)
+ {
+ var property = GetPropertyInfo(propertyName);
+ if (property is null)
+ return;
+
+ try
+ {
+ var convertedValue = Convert.ChangeType(value, property.PropertyType);
+ property.SetValue(entity, convertedValue);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+
+ private PropertyInfo? GetPropertyInfo(string propertyName)
+ {
+ return PropertyCache.GetOrAdd(propertyName, name => entityType.GetProperty(name));
+ }
+}
diff --git a/DD.Persistence.Models/DD.Persistence.Models.csproj b/DD.Persistence.Models/DD.Persistence.Models.csproj
index 6bcae66..6facfdc 100644
--- a/DD.Persistence.Models/DD.Persistence.Models.csproj
+++ b/DD.Persistence.Models/DD.Persistence.Models.csproj
@@ -11,9 +11,9 @@
DD.Persistence.Models
- 1.2.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
+ 1.3.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
- 1.2.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
+ 1.3.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH))
DD.Persistence.Models