Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
32a41fcd80 |
68
Persistence.API/Controllers/ChangeLogController.cs
Normal file
68
Persistence.API/Controllers/ChangeLogController.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Persistence.Models;
|
||||||
|
using Persistence.Repositories;
|
||||||
|
|
||||||
|
namespace Persistence.API.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class ChangeLogController<TDto, TChangeLogDto> : ControllerBase, IChangeLogApi<TDto, TChangeLogDto>
|
||||||
|
where TDto : class, IChangeLogAbstract, new()
|
||||||
|
where TChangeLogDto : ChangeLogDto<TDto>
|
||||||
|
{
|
||||||
|
private IChangeLogRepository<TDto, TChangeLogDto> changeLogRepository;
|
||||||
|
|
||||||
|
public ChangeLogController(IChangeLogRepository<TDto, TChangeLogDto> changeLogRepository)
|
||||||
|
{
|
||||||
|
this.changeLogRepository = changeLogRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public Task<ActionResult<IEnumerable<TDto>>> GetChangeLogCurrent(CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("forDate")]
|
||||||
|
public Task<ActionResult<IEnumerable<TChangeLogDto>>> GetChangeLogForDate(DateTimeOffset historyMoment, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<ActionResult<int>> AddAsync(TDto dto, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<ActionResult<int>> AddRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<ActionResult<int>> DeleteAsync(int id, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public Task<ActionResult<int>> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("update")]
|
||||||
|
public Task<ActionResult<int>> UpdateAsync(TDto dto, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("update")]
|
||||||
|
public Task<ActionResult<int>> UpdateRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Persistence.API;
|
||||||
using Persistence.Repositories;
|
using Persistence.Repositories;
|
||||||
using Persistence.Repository.Data;
|
using Persistence.Repository.Data;
|
||||||
|
|
||||||
namespace Persistence.API.Controllers;
|
namespace Persistence.API.Controllers;
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class DataSaubController : TimeSeriesController<DataSaubDto>
|
public class DataSaubController : TimeSeriesController<DataSaubDto>
|
||||||
{
|
{
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Persistence.Models;
|
|
||||||
using Persistence.Repositories;
|
|
||||||
|
|
||||||
namespace Persistence.API.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[Authorize]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
public class SetpointController : ControllerBase, ISetpointApi
|
|
||||||
{
|
|
||||||
private readonly ISetpointRepository setpointRepository;
|
|
||||||
|
|
||||||
public SetpointController(ISetpointRepository setpointRepository)
|
|
||||||
{
|
|
||||||
this.setpointRepository = setpointRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("current")]
|
|
||||||
public async Task<ActionResult<IEnumerable<SetpointValueDto>>> GetCurrent([FromQuery] IEnumerable<Guid> setpointKeys, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await setpointRepository.GetCurrent(setpointKeys, token);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("history")]
|
|
||||||
public async Task<ActionResult<IEnumerable<SetpointValueDto>>> GetHistory([FromQuery] IEnumerable<Guid> setpointKeys, [FromQuery] DateTimeOffset historyMoment, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await setpointRepository.GetHistory(setpointKeys, historyMoment, token);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("log")]
|
|
||||||
public async Task<ActionResult<Dictionary<Guid, IEnumerable<SetpointLogDto>>>> GetLog([FromQuery] IEnumerable<Guid> setpointKeys, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await setpointRepository.GetLog(setpointKeys, token);
|
|
||||||
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<ActionResult<int>> Save(Guid setpointKey, object newValue, CancellationToken token)
|
|
||||||
{
|
|
||||||
// ToDo: вычитка idUser
|
|
||||||
await setpointRepository.Save(setpointKey, newValue, 0, token);
|
|
||||||
|
|
||||||
return Ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,9 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Persistence.Models;
|
using Persistence.Models;
|
||||||
using Persistence.Repositories;
|
using Persistence.Repositories;
|
||||||
|
|
||||||
namespace Persistence.API.Controllers;
|
namespace Persistence.API.Controllers;
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDto>
|
public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDto>
|
||||||
where TDto : class, ITimeSeriesAbstractDto, new()
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
@ -19,32 +17,22 @@ public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDt
|
|||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public async Task<IActionResult> Get(DateTimeOffset dateBegin, CancellationToken token)
|
public async Task<IActionResult> GetAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await this.timeSeriesDataRepository.GetGtDate(dateBegin, token);
|
var result = await this.timeSeriesDataRepository.GetAsync(dateBegin, dateEnd, token);
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("datesRange")]
|
[HttpGet("datesRange")]
|
||||||
public async Task<IActionResult> GetDatesRange(CancellationToken token)
|
public Task<IActionResult> GetDatesRangeAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await this.timeSeriesDataRepository.GetDatesRange(token);
|
throw new NotImplementedException();
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("resampled")]
|
|
||||||
public async Task<IActionResult> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024, CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var result = await this.timeSeriesDataRepository.GetResampledData(dateBegin, intervalSec, approxPointsCount, token);
|
|
||||||
return Ok(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> InsertRange(IEnumerable<TDto> dtos, CancellationToken token)
|
public async Task<IActionResult> InsertRangeAsync(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var result = await this.timeSeriesDataRepository.InsertRange(dtos, token);
|
var result = await this.timeSeriesDataRepository.InsertRange(dtos, token);
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,195 +0,0 @@
|
|||||||
using System.Text.Json.Nodes;
|
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using Microsoft.OpenApi.Any;
|
|
||||||
using Microsoft.OpenApi.Models;
|
|
||||||
using Persistence.Models.Configurations;
|
|
||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
|
||||||
|
|
||||||
namespace Persistence.API;
|
|
||||||
|
|
||||||
public static class DependencyInjection
|
|
||||||
{
|
|
||||||
public static void AddSwagger(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.AddSwaggerGen(c =>
|
|
||||||
{
|
|
||||||
c.MapType<TimeSpan>(() => new OpenApiSchema { Type = "string", Example = new OpenApiString("0.00:00:00") });
|
|
||||||
c.MapType<DateOnly>(() => new OpenApiSchema { Type = "string", Format = "date" });
|
|
||||||
c.MapType<JsonValue>(() => new OpenApiSchema
|
|
||||||
{
|
|
||||||
AnyOf = new OpenApiSchema[]
|
|
||||||
{
|
|
||||||
new OpenApiSchema {Type = "string", Format = "string" },
|
|
||||||
new OpenApiSchema {Type = "number", Format = "int32" },
|
|
||||||
new OpenApiSchema {Type = "number", Format = "float" },
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
c.CustomOperationIds(e =>
|
|
||||||
{
|
|
||||||
return $"{e.ActionDescriptor.RouteValues["action"]}";
|
|
||||||
});
|
|
||||||
|
|
||||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Persistence web api", Version = "v1" });
|
|
||||||
|
|
||||||
var needUseKeyCloak = configuration.GetSection("NeedUseKeyCloak").Get<bool>();
|
|
||||||
if (needUseKeyCloak)
|
|
||||||
c.AddKeycloackSecurity(configuration);
|
|
||||||
else c.AddDefaultSecurity(configuration);
|
|
||||||
|
|
||||||
//var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
|
||||||
//var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
|
||||||
//var includeControllerXmlComment = true;
|
|
||||||
//options.IncludeXmlComments(xmlPath, includeControllerXmlComment);
|
|
||||||
//options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Authentication
|
|
||||||
public static void AddJWTAuthentication(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
var needUseKeyCloak = configuration
|
|
||||||
.GetSection("NeedUseKeyCloak")
|
|
||||||
.Get<bool>();
|
|
||||||
if (needUseKeyCloak)
|
|
||||||
services.AddKeyCloakAuthentication(configuration);
|
|
||||||
else services.AddDefaultAuthentication(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddKeyCloakAuthentication(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
||||||
.AddJwtBearer(options =>
|
|
||||||
{
|
|
||||||
options.RequireHttpsMetadata = false;
|
|
||||||
options.Audience = configuration["Authentication:Audience"];
|
|
||||||
options.MetadataAddress = configuration["Authentication:MetadataAddress"]!;
|
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
|
||||||
ValidIssuer = configuration["Authentication:ValidIssuer"],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddDefaultAuthentication(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
||||||
.AddJwtBearer(options =>
|
|
||||||
{
|
|
||||||
options.RequireHttpsMetadata = false;
|
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidIssuer = JwtParams.Issuer,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidAudience = JwtParams.Audience,
|
|
||||||
ValidateLifetime = true,
|
|
||||||
IssuerSigningKey = JwtParams.SecurityKey,
|
|
||||||
ValidateIssuerSigningKey = false
|
|
||||||
};
|
|
||||||
options.Events = new JwtBearerEvents
|
|
||||||
{
|
|
||||||
OnMessageReceived = context =>
|
|
||||||
{
|
|
||||||
var accessToken = context.Request.Headers["Authorization"]
|
|
||||||
.ToString()
|
|
||||||
.Replace(JwtBearerDefaults.AuthenticationScheme, string.Empty)
|
|
||||||
.Trim();
|
|
||||||
|
|
||||||
context.Token = accessToken;
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
},
|
|
||||||
OnTokenValidated = context =>
|
|
||||||
{
|
|
||||||
var username = context.Principal?.Claims
|
|
||||||
.FirstOrDefault(e => e.Type == "username")?.Value;
|
|
||||||
|
|
||||||
var password = context.Principal?.Claims
|
|
||||||
.FirstOrDefault(e => e.Type == "password")?.Value;
|
|
||||||
|
|
||||||
var keyCloakUser = configuration
|
|
||||||
.GetSection(nameof(AuthUser))
|
|
||||||
.Get<AuthUser>()!;
|
|
||||||
|
|
||||||
if (username != keyCloakUser.Username || password != keyCloakUser.Password)
|
|
||||||
{
|
|
||||||
context.Fail("username or password did not match");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Security (Swagger)
|
|
||||||
private static void AddKeycloackSecurity(this SwaggerGenOptions options, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
options.AddSecurityDefinition("Keycloack", new OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'",
|
|
||||||
Name = "Authorization",
|
|
||||||
In = ParameterLocation.Header,
|
|
||||||
Type = SecuritySchemeType.OAuth2,
|
|
||||||
Flows = new OpenApiOAuthFlows
|
|
||||||
{
|
|
||||||
Implicit = new OpenApiOAuthFlow
|
|
||||||
{
|
|
||||||
AuthorizationUrl = new Uri(configuration["Authentication:AuthorizationUrl"]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
new OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
Reference = new OpenApiReference
|
|
||||||
{
|
|
||||||
Type = ReferenceType.SecurityScheme,
|
|
||||||
Id = "Keycloack"
|
|
||||||
},
|
|
||||||
Scheme = "Bearer",
|
|
||||||
Name = "Bearer",
|
|
||||||
In = ParameterLocation.Header,
|
|
||||||
},
|
|
||||||
new List<string>()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddDefaultSecurity(this SwaggerGenOptions options, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'",
|
|
||||||
Name = "Authorization",
|
|
||||||
In = ParameterLocation.Header,
|
|
||||||
Type = SecuritySchemeType.ApiKey,
|
|
||||||
Scheme = "Bearer",
|
|
||||||
});
|
|
||||||
|
|
||||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
new OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
Reference = new OpenApiReference
|
|
||||||
{
|
|
||||||
Type = ReferenceType.SecurityScheme,
|
|
||||||
Id = "Bearer"
|
|
||||||
},
|
|
||||||
Scheme = "oauth2",
|
|
||||||
Name = "Bearer",
|
|
||||||
In = ParameterLocation.Header,
|
|
||||||
},
|
|
||||||
new List<string>()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using System.Security.Claims;
|
|
||||||
|
|
||||||
namespace Persistence.API;
|
|
||||||
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
public static T GetUserId<T>(this ClaimsPrincipal principal)
|
|
||||||
{
|
|
||||||
if (principal == null)
|
|
||||||
throw new ArgumentNullException(nameof(principal));
|
|
||||||
|
|
||||||
var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier);
|
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(loggedInUserId))
|
|
||||||
throw new ArgumentNullException(nameof(loggedInUserId));
|
|
||||||
|
|
||||||
var result = TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(loggedInUserId);
|
|
||||||
|
|
||||||
if (result is null)
|
|
||||||
throw new ArgumentNullException(nameof(result));
|
|
||||||
|
|
||||||
return (T)result;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,13 +8,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Persistence.Database.Postgres\Persistence.Database.Postgres.csproj" />
|
|
||||||
<ProjectReference Include="..\Persistence.Repository\Persistence.Repository.csproj" />
|
<ProjectReference Include="..\Persistence.Repository\Persistence.Repository.csproj" />
|
||||||
<ProjectReference Include="..\Persistence\Persistence.csproj" />
|
<ProjectReference Include="..\Persistence\Persistence.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
|
|
||||||
using Persistence.Models;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Persistence.Repositories;
|
||||||
|
using Persistence.Repository;
|
||||||
|
using Persistence.Repository.Data;
|
||||||
|
using Persistence.Repository.Repositories;
|
||||||
|
|
||||||
namespace Persistence.API;
|
namespace Persistence.API;
|
||||||
|
|
||||||
@ -7,9 +12,8 @@ public class Program
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
|
||||||
var host = CreateHostBuilder(args).Build();
|
var host = CreateHostBuilder(args).Build();
|
||||||
Startup.BeforeRunHandler(host);
|
Persistence.Repository.Startup.BeforeRunHandler(host);
|
||||||
host.Run();
|
host.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
},
|
},
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"applicationUrl": "http://localhost:13616"
|
"applicationUrl": "http://localhost:5032"
|
||||||
},
|
},
|
||||||
"IIS Express": {
|
"IIS Express": {
|
||||||
"commandName": "IISExpress",
|
"commandName": "IISExpress",
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using Persistence.Repository;
|
using Persistence.Repository;
|
||||||
using Persistence.Database.Model;
|
|
||||||
using Persistence.Database.Postgres;
|
|
||||||
|
|
||||||
namespace Persistence.API;
|
namespace Persistence.API;
|
||||||
|
|
||||||
@ -19,10 +17,9 @@ public class Startup
|
|||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
services.AddEndpointsApiExplorer();
|
services.AddEndpointsApiExplorer();
|
||||||
services.AddSwagger(Configuration);
|
services.AddSwaggerGen();
|
||||||
services.AddInfrastructure();
|
|
||||||
services.AddPersistenceDbContext(Configuration);
|
services.AddInfrastructure(Configuration);
|
||||||
services.AddJWTAuthentication(Configuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
@ -33,28 +30,11 @@ public class Startup
|
|||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
//app.UseAuthorization();
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseAuthentication();
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BeforeRunHandler(IHost host)
|
|
||||||
{
|
|
||||||
using var scope = host.Services.CreateScope();
|
|
||||||
var provider = scope.ServiceProvider;
|
|
||||||
|
|
||||||
var context = provider.GetRequiredService<PersistenceDbContext>();
|
|
||||||
context.Database.EnsureCreatedAndMigrated();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
12
Persistence.API/WeatherForecast.cs
Normal file
12
Persistence.API/WeatherForecast.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Persistence.API;
|
||||||
|
|
||||||
|
public class WeatherForecast
|
||||||
|
{
|
||||||
|
public DateOnly Date { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureC { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
}
|
@ -4,6 +4,5 @@
|
|||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"NeedUseKeyCloak": false
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
{
|
{
|
||||||
"DbConnection": {
|
"DbConnection": {
|
||||||
"Host": "localhost",
|
"Host": "localhost",
|
||||||
"Port": 5432,
|
"Port": 5432,
|
||||||
"Username": "postgres",
|
"Username": "postgres",
|
||||||
"Password": "q"
|
"Password": "q"
|
||||||
},
|
}
|
||||||
"NeedUseKeyCloak": false,
|
|
||||||
"AuthUser": {
|
|
||||||
"username": "myuser",
|
|
||||||
"password": 12345,
|
|
||||||
"clientId": "webapi",
|
|
||||||
"grantType": "password"
|
|
||||||
},
|
|
||||||
"KeycloakGetTokenUrl": "http://192.168.0.10:8321/realms/Persistence/protocol/openid-connect/token"
|
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=q;Persist Security Info=True"
|
"DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=q;Persist Security Info=True",
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*"
|
||||||
"Authentication": {
|
|
||||||
"MetadataAddress": "http://192.168.0.10:8321/realms/Persistence/.well-known/openid-configuration",
|
|
||||||
"Audience": "account",
|
|
||||||
"ValidIssuer": "http://192.168.0.10:8321/realms/Persistence",
|
|
||||||
"AuthorizationUrl": "http://192.168.0.10:8321/realms/Persistence/protocol/openid-connect/auth"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
using Persistence.Models;
|
|
||||||
using Refit;
|
|
||||||
|
|
||||||
namespace Persistence.Client.Clients;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Интерфейс для тестирования API, предназначенного для работы с уставками
|
|
||||||
/// </summary>
|
|
||||||
public interface ISetpointClient
|
|
||||||
{
|
|
||||||
private const string BaseRoute = "/api/setpoint";
|
|
||||||
|
|
||||||
[Get($"{BaseRoute}/current")]
|
|
||||||
Task<IApiResponse<IEnumerable<SetpointValueDto>>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys);
|
|
||||||
|
|
||||||
[Get($"{BaseRoute}/history")]
|
|
||||||
Task<IApiResponse<IEnumerable<SetpointValueDto>>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys, [Query] DateTimeOffset historyMoment);
|
|
||||||
|
|
||||||
[Get($"{BaseRoute}/log")]
|
|
||||||
Task<IApiResponse<Dictionary<Guid, IEnumerable<SetpointLogDto>>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable<Guid> setpointKeys);
|
|
||||||
|
|
||||||
[Post($"{BaseRoute}/")]
|
|
||||||
Task<IApiResponse> Save(Guid setpointKey, object newValue);
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Persistence.Models;
|
|
||||||
using Refit;
|
|
||||||
|
|
||||||
namespace Persistence.Client.Clients;
|
|
||||||
public interface ITimeSeriesClient<TDto>
|
|
||||||
where TDto : class, new()
|
|
||||||
{
|
|
||||||
private const string BaseRoute = "/api/dataSaub";
|
|
||||||
|
|
||||||
[Post($"{BaseRoute}")]
|
|
||||||
Task<IApiResponse<int>> InsertRange(IEnumerable<TDto> dtos);
|
|
||||||
|
|
||||||
[Get($"{BaseRoute}")]
|
|
||||||
Task<IApiResponse<IEnumerable<TDto>>> Get(DateTimeOffset dateBegin, DateTimeOffset dateEnd);
|
|
||||||
|
|
||||||
[Get($"{BaseRoute}/resampled")]
|
|
||||||
Task<IApiResponse<IEnumerable<TDto>>> GetResampledData(DateTimeOffset dateBegin, double intervalSec = 600d, int approxPointsCount = 1024);
|
|
||||||
|
|
||||||
[Get($"{BaseRoute}/datesRange")]
|
|
||||||
Task<IApiResponse<DatesRangeDto?>> GetDatesRange();
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Text.Json;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using Persistence.Models.Configurations;
|
|
||||||
using RestSharp;
|
|
||||||
|
|
||||||
namespace Persistence.Client.Helpers;
|
|
||||||
public static class ApiTokenHelper
|
|
||||||
{
|
|
||||||
public static void Authorize(this HttpClient httpClient, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
var authUser = configuration
|
|
||||||
.GetSection(nameof(AuthUser))
|
|
||||||
.Get<AuthUser>()!;
|
|
||||||
var needUseKeyCloak = configuration
|
|
||||||
.GetSection("NeedUseKeyCloak")
|
|
||||||
.Get<bool>()!;
|
|
||||||
var keycloakGetTokenUrl = configuration.GetSection("KeycloakGetTokenUrl").Get<string>() ?? string.Empty;
|
|
||||||
|
|
||||||
var jwtToken = needUseKeyCloak
|
|
||||||
? authUser.CreateKeyCloakJwtToken(keycloakGetTokenUrl)
|
|
||||||
: authUser.CreateDefaultJwtToken();
|
|
||||||
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string CreateDefaultJwtToken(this AuthUser authUser)
|
|
||||||
{
|
|
||||||
var claims = new List<Claim>()
|
|
||||||
{
|
|
||||||
new("client_id", authUser.ClientId),
|
|
||||||
new("username", authUser.Username),
|
|
||||||
new("password", authUser.Password),
|
|
||||||
new("grant_type", authUser.GrantType)
|
|
||||||
};
|
|
||||||
|
|
||||||
var tokenDescriptor = new SecurityTokenDescriptor
|
|
||||||
{
|
|
||||||
Issuer = JwtParams.Issuer,
|
|
||||||
Audience = JwtParams.Audience,
|
|
||||||
Subject = new ClaimsIdentity(claims),
|
|
||||||
Expires = DateTime.UtcNow.AddHours(1),
|
|
||||||
SigningCredentials = new SigningCredentials(JwtParams.SecurityKey, SecurityAlgorithms.HmacSha256Signature)
|
|
||||||
};
|
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
|
||||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
|
||||||
return tokenHandler.WriteToken(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string CreateKeyCloakJwtToken(this AuthUser authUser, string keycloakGetTokenUrl)
|
|
||||||
{
|
|
||||||
var restClient = new RestClient();
|
|
||||||
|
|
||||||
var request = new RestRequest(keycloakGetTokenUrl, Method.Post);
|
|
||||||
request.AddParameter("username", authUser.Username);
|
|
||||||
request.AddParameter("password", authUser.Password);
|
|
||||||
request.AddParameter("client_id", authUser.ClientId);
|
|
||||||
request.AddParameter("grant_type", authUser.GrantType);
|
|
||||||
|
|
||||||
var keyCloackResponse = restClient.Post(request);
|
|
||||||
if (keyCloackResponse.IsSuccessful && !String.IsNullOrEmpty(keyCloackResponse.Content))
|
|
||||||
{
|
|
||||||
var token = JsonSerializer.Deserialize<JwtToken>(keyCloackResponse.Content)!;
|
|
||||||
return token.AccessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.2.1" />
|
|
||||||
<PackageReference Include="Refit" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Refit.HttpClientFactory" Version="8.0.0" />
|
|
||||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Persistence\Persistence.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Models\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,32 +0,0 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Persistence.Client.Helpers;
|
|
||||||
using Refit;
|
|
||||||
|
|
||||||
namespace Persistence.Client
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Фабрика клиентов для доступа к Persistence - сервису
|
|
||||||
/// </summary>
|
|
||||||
public class PersistenceClientFactory
|
|
||||||
{
|
|
||||||
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
|
|
||||||
{
|
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
};
|
|
||||||
private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions));
|
|
||||||
private HttpClient httpClient;
|
|
||||||
public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
this.httpClient = httpClientFactory.CreateClient();
|
|
||||||
|
|
||||||
httpClient.Authorize(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetClient<T>()
|
|
||||||
{
|
|
||||||
return RestService.For<T>(httpClient, RefitSettings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Persistence.Database.Model;
|
|
||||||
|
|
||||||
public static class DependencyInjection
|
|
||||||
{
|
|
||||||
public static IServiceCollection AddPersistenceDbContext(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
string connectionStringName = "DefaultConnection";
|
|
||||||
|
|
||||||
services.AddDbContext<PersistenceDbContext>(options =>
|
|
||||||
options.UseNpgsql(configuration.GetConnectionString(connectionStringName)));
|
|
||||||
|
|
||||||
services.AddScoped<DbContext>(provider => provider.GetRequiredService<PersistenceDbContext>());
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Persistence.Database.Postgres.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PersistenceDbContext))]
|
|
||||||
[Migration("20241118052225_SetpointMigration")]
|
|
||||||
partial class SetpointMigration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.UseCollation("Russian_Russia.1251")
|
|
||||||
.HasAnnotation("ProductVersion", "8.0.10")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("id");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<double?>("AxialLoad")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("axialLoad");
|
|
||||||
|
|
||||||
b.Property<double?>("BitDepth")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("bitDepth");
|
|
||||||
|
|
||||||
b.Property<double?>("BlockPosition")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("blockPosition");
|
|
||||||
|
|
||||||
b.Property<double?>("BlockSpeed")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("blockSpeed");
|
|
||||||
|
|
||||||
b.Property<double?>("Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("flow");
|
|
||||||
|
|
||||||
b.Property<double?>("HookWeight")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("hookWeight");
|
|
||||||
|
|
||||||
b.Property<int>("IdFeedRegulator")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("idFeedRegulator");
|
|
||||||
|
|
||||||
b.Property<int?>("Mode")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("mode");
|
|
||||||
|
|
||||||
b.Property<double?>("Mse")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("mse");
|
|
||||||
|
|
||||||
b.Property<short>("MseState")
|
|
||||||
.HasColumnType("smallint")
|
|
||||||
.HasColumnName("mseState");
|
|
||||||
|
|
||||||
b.Property<double?>("Pressure")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pressure");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump0Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump0Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump1Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump1Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump2Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump2Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("RotorSpeed")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("rotorSpeed");
|
|
||||||
|
|
||||||
b.Property<double?>("RotorTorque")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("rotorTorque");
|
|
||||||
|
|
||||||
b.Property<int>("TimeStamp")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("timestamp");
|
|
||||||
|
|
||||||
b.Property<string>("User")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("user");
|
|
||||||
|
|
||||||
b.Property<double?>("WellDepth")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("wellDepth");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("DataSaub");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Persistence.Database.Model.Setpoint", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Key")
|
|
||||||
.HasColumnType("uuid")
|
|
||||||
.HasComment("Ключ");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Created")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasComment("Дата изменения уставки");
|
|
||||||
|
|
||||||
b.Property<int>("IdUser")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasComment("Id автора последнего изменения");
|
|
||||||
|
|
||||||
b.Property<object>("Value")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasComment("Значение уставки");
|
|
||||||
|
|
||||||
b.HasKey("Key", "Created");
|
|
||||||
|
|
||||||
b.ToTable("Setpoint");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Persistence.Database.Postgres.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class SetpointMigration : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Setpoint",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Key = table.Column<Guid>(type: "uuid", nullable: false, comment: "Ключ"),
|
|
||||||
Created = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, comment: "Дата изменения уставки"),
|
|
||||||
Value = table.Column<object>(type: "jsonb", nullable: false, comment: "Значение уставки"),
|
|
||||||
IdUser = table.Column<int>(type: "integer", nullable: false, comment: "Id автора последнего изменения")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Setpoint", x => new { x.Key, x.Created });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Setpoint");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Persistence.Database.Postgres.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PersistenceDbContext))]
|
|
||||||
[Migration("20241122074646_InitialCreate")]
|
|
||||||
partial class InitialCreate
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.UseCollation("Russian_Russia.1251")
|
|
||||||
.HasAnnotation("ProductVersion", "8.0.10")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
|
|
||||||
{
|
|
||||||
b.Property<DateTimeOffset>("Date")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("date");
|
|
||||||
|
|
||||||
b.Property<double?>("AxialLoad")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("axialLoad");
|
|
||||||
|
|
||||||
b.Property<double?>("BitDepth")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("bitDepth");
|
|
||||||
|
|
||||||
b.Property<double?>("BlockPosition")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("blockPosition");
|
|
||||||
|
|
||||||
b.Property<double?>("BlockSpeed")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("blockSpeed");
|
|
||||||
|
|
||||||
b.Property<double?>("Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("flow");
|
|
||||||
|
|
||||||
b.Property<double?>("HookWeight")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("hookWeight");
|
|
||||||
|
|
||||||
b.Property<int>("IdFeedRegulator")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("idFeedRegulator");
|
|
||||||
|
|
||||||
b.Property<int?>("Mode")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("mode");
|
|
||||||
|
|
||||||
b.Property<double?>("Mse")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("mse");
|
|
||||||
|
|
||||||
b.Property<short>("MseState")
|
|
||||||
.HasColumnType("smallint")
|
|
||||||
.HasColumnName("mseState");
|
|
||||||
|
|
||||||
b.Property<double?>("Pressure")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pressure");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump0Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump0Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump1Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump1Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump2Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump2Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("RotorSpeed")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("rotorSpeed");
|
|
||||||
|
|
||||||
b.Property<double?>("RotorTorque")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("rotorTorque");
|
|
||||||
|
|
||||||
b.Property<string>("User")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("user");
|
|
||||||
|
|
||||||
b.Property<double?>("WellDepth")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("wellDepth");
|
|
||||||
|
|
||||||
b.HasKey("Date");
|
|
||||||
|
|
||||||
b.ToTable("DataSaub");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Persistence.Database.Postgres.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class InitialCreate : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AlterDatabase()
|
|
||||||
.Annotation("Npgsql:PostgresExtension:adminpack", ",,");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "DataSaub",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
|
||||||
mode = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
user = table.Column<string>(type: "text", nullable: true),
|
|
||||||
wellDepth = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
bitDepth = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
blockPosition = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
blockSpeed = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
pressure = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
axialLoad = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
hookWeight = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
rotorTorque = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
rotorSpeed = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
flow = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
mseState = table.Column<short>(type: "smallint", nullable: false),
|
|
||||||
idFeedRegulator = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
mse = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
pump0Flow = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
pump1Flow = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
pump2Flow = table.Column<double>(type: "double precision", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_DataSaub", x => x.date);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "DataSaub");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,136 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Persistence.Database.Postgres.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(PersistenceDbContext))]
|
|
||||||
partial class PersistenceDbContextModelSnapshot : ModelSnapshot
|
|
||||||
{
|
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.UseCollation("Russian_Russia.1251")
|
|
||||||
.HasAnnotation("ProductVersion", "8.0.10")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
|
|
||||||
{
|
|
||||||
b.Property<DateTimeOffset>("Date")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasColumnName("date");
|
|
||||||
|
|
||||||
b.Property<double?>("AxialLoad")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("axialLoad");
|
|
||||||
|
|
||||||
b.Property<double?>("BitDepth")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("bitDepth");
|
|
||||||
|
|
||||||
b.Property<double?>("BlockPosition")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("blockPosition");
|
|
||||||
|
|
||||||
b.Property<double?>("BlockSpeed")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("blockSpeed");
|
|
||||||
|
|
||||||
b.Property<double?>("Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("flow");
|
|
||||||
|
|
||||||
b.Property<double?>("HookWeight")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("hookWeight");
|
|
||||||
|
|
||||||
b.Property<int>("IdFeedRegulator")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("idFeedRegulator");
|
|
||||||
|
|
||||||
b.Property<int?>("Mode")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("mode");
|
|
||||||
|
|
||||||
b.Property<double?>("Mse")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("mse");
|
|
||||||
|
|
||||||
b.Property<short>("MseState")
|
|
||||||
.HasColumnType("smallint")
|
|
||||||
.HasColumnName("mseState");
|
|
||||||
|
|
||||||
b.Property<double?>("Pressure")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pressure");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump0Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump0Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump1Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump1Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("Pump2Flow")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("pump2Flow");
|
|
||||||
|
|
||||||
b.Property<double?>("RotorSpeed")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("rotorSpeed");
|
|
||||||
|
|
||||||
b.Property<double?>("RotorTorque")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("rotorTorque");
|
|
||||||
|
|
||||||
b.Property<string>("User")
|
|
||||||
.HasColumnType("text")
|
|
||||||
.HasColumnName("user");
|
|
||||||
|
|
||||||
b.Property<double?>("WellDepth")
|
|
||||||
.HasColumnType("double precision")
|
|
||||||
.HasColumnName("wellDepth");
|
|
||||||
|
|
||||||
b.HasKey("Date");
|
|
||||||
|
|
||||||
b.ToTable("DataSaub");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Persistence.Database.Model.Setpoint", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Key")
|
|
||||||
.HasColumnType("uuid")
|
|
||||||
.HasComment("Ключ");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("Created")
|
|
||||||
.HasColumnType("timestamp with time zone")
|
|
||||||
.HasComment("Дата изменения уставки");
|
|
||||||
|
|
||||||
b.Property<int>("IdUser")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasComment("Id автора последнего изменения");
|
|
||||||
|
|
||||||
b.Property<object>("Value")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasComment("Значение уставки");
|
|
||||||
|
|
||||||
b.HasKey("Key", "Created");
|
|
||||||
|
|
||||||
b.ToTable("Setpoint");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Persistence.Database\Persistence.Database.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Migrations\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,5 +0,0 @@
|
|||||||
## Создать миграцию
|
|
||||||
```
|
|
||||||
dotnet ef migrations add <MigrationName> --project Persistence.Database.Postgres
|
|
||||||
|
|
||||||
```
|
|
@ -7,7 +7,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Persistence.Database.Postgres;
|
namespace Persistence.Database;
|
||||||
public static class EFExtensionsInitialization
|
public static class EFExtensionsInitialization
|
||||||
{
|
{
|
||||||
public static void EnsureCreatedAndMigrated(this DatabaseFacade db)
|
public static void EnsureCreatedAndMigrated(this DatabaseFacade db)
|
@ -1,21 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Persistence.Database.Model
|
|
||||||
{
|
|
||||||
[PrimaryKey(nameof(Key), nameof(Created))]
|
|
||||||
public class Setpoint
|
|
||||||
{
|
|
||||||
[Comment("Ключ")]
|
|
||||||
public Guid Key { get; set; }
|
|
||||||
|
|
||||||
[Column(TypeName = "jsonb"), Comment("Значение уставки")]
|
|
||||||
public required object Value { get; set; }
|
|
||||||
|
|
||||||
[Comment("Дата создания уставки")]
|
|
||||||
public DateTimeOffset Created { get; set; }
|
|
||||||
|
|
||||||
[Comment("Id автора последнего изменения")]
|
|
||||||
public int IdUser { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
|
|
||||||
namespace Persistence.Database;
|
|
||||||
public interface IPersistenceDbContext : IDisposable
|
|
||||||
{
|
|
||||||
DbSet<DataSaub> DataSaub { get; }
|
|
||||||
}
|
|
22
Persistence.Database/Model/ChangeLog.cs
Normal file
22
Persistence.Database/Model/ChangeLog.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Persistence.Database.Model
|
||||||
|
{
|
||||||
|
public class ChangeLog : IChangeLogData
|
||||||
|
{
|
||||||
|
[Column("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Column("idnext")]
|
||||||
|
public int? IdNext { get; set; }
|
||||||
|
|
||||||
|
[Column("idprevious")]
|
||||||
|
public int? IdPrevious { get; set; }
|
||||||
|
|
||||||
|
[Column("creation")]
|
||||||
|
public DateTimeOffset Creation { get; set; }
|
||||||
|
|
||||||
|
[Column("obsolete")]
|
||||||
|
public DateTimeOffset? Obsolete { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Persistence.Database.Model;
|
namespace Persistence.Database.Model;
|
||||||
public class DataSaub : ITimestampedData
|
public class DataSaub : ITimestampedData
|
||||||
{
|
{
|
||||||
[Key, Column("date")]
|
[Column("id")]
|
||||||
public DateTimeOffset Date { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Column("timestamp")]
|
||||||
|
public int TimeStamp { get; set; }
|
||||||
|
|
||||||
[Column("mode")]
|
[Column("mode")]
|
||||||
public int? Mode { get; set; }
|
public int? Mode { get; set; }
|
11
Persistence.Database/Model/IChangeLogData.cs
Normal file
11
Persistence.Database/Model/IChangeLogData.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Persistence.Database.Model
|
||||||
|
{
|
||||||
|
internal interface IChangeLogData
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int? IdNext { get; set; }
|
||||||
|
public int? IdPrevious { get; set; }
|
||||||
|
public DateTimeOffset Creation { get; set; }
|
||||||
|
public DateTimeOffset? Obsolete { get; set; }
|
||||||
|
}
|
||||||
|
}
|
21
Persistence.Database/Model/IDbContextManager.cs
Normal file
21
Persistence.Database/Model/IDbContextManager.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Persistence.Database.Model;
|
||||||
|
public interface IDbContextManager
|
||||||
|
{
|
||||||
|
//IConnectionManager ConnectionManager { get; }
|
||||||
|
|
||||||
|
DbContext GetReadonlyDbContext();
|
||||||
|
|
||||||
|
DbContext GetDbContext();
|
||||||
|
|
||||||
|
DbContext CreateAndInitializeNewContext();
|
||||||
|
|
||||||
|
DbContext CreateAndInitializeNewContext(DbConnection connection);
|
||||||
|
}
|
@ -11,7 +11,7 @@ namespace Persistence.Database.Model;
|
|||||||
public interface IPersistenceDbContext : IDisposable
|
public interface IPersistenceDbContext : IDisposable
|
||||||
{
|
{
|
||||||
DbSet<DataSaub> DataSaub { get; }
|
DbSet<DataSaub> DataSaub { get; }
|
||||||
DbSet<Setpoint> Setpoint { get; }
|
DbSet<ChangeLog> ChangeLog { get; }
|
||||||
DatabaseFacade Database { get; }
|
DatabaseFacade Database { get; }
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,5 @@ using System.Threading.Tasks;
|
|||||||
namespace Persistence.Database.Model;
|
namespace Persistence.Database.Model;
|
||||||
public interface ITimestampedData
|
public interface ITimestampedData
|
||||||
{
|
{
|
||||||
/// <summary>
|
int TimeStamp { get; set; }
|
||||||
/// Дата (должна быть обязательно в UTC)
|
|
||||||
/// </summary>
|
|
||||||
DateTimeOffset Date { get; set; }
|
|
||||||
}
|
}
|
@ -1,23 +1,22 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Data.Common;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Metrics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
|
||||||
|
|
||||||
namespace Persistence.Database.Model;
|
namespace Persistence.Database.Model;
|
||||||
public partial class PersistenceDbContext : DbContext, IPersistenceDbContext
|
public partial class PersistenceDbContext : DbContext, IPersistenceDbContext
|
||||||
{
|
{
|
||||||
public DbSet<DataSaub> DataSaub => Set<DataSaub>();
|
public DbSet<DataSaub> DataSaub => Set<DataSaub>();
|
||||||
|
public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>();
|
||||||
|
|
||||||
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
|
public PersistenceDbContext() { } // Áåç ïóñòîãî êîíñòðóêòîðà ìèãðàöèÿ ïàäààåò
|
||||||
|
|
||||||
public PersistenceDbContext()
|
|
||||||
: base()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public PersistenceDbContext(DbContextOptions<PersistenceDbContext> options)
|
public PersistenceDbContext(DbContextOptions<PersistenceDbContext> options)
|
||||||
: base(options)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
@ -7,11 +7,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
43
Persistence.IntegrationTests/ApiTokenHelper.cs
Normal file
43
Persistence.IntegrationTests/ApiTokenHelper.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
namespace Persistence.IntegrationTests;
|
||||||
|
public static class ApiTokenHelper
|
||||||
|
{
|
||||||
|
//public static string GetAdminUserToken()
|
||||||
|
//{
|
||||||
|
// var user = new User()
|
||||||
|
// {
|
||||||
|
// Id = 1,
|
||||||
|
// IdCompany = 1,
|
||||||
|
// Login = "test_user"
|
||||||
|
// };
|
||||||
|
// var roles = new[] { "root" };
|
||||||
|
|
||||||
|
// return CreateToken(user, roles);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private static string CreateToken(User user, IEnumerable<string> roles)
|
||||||
|
//{
|
||||||
|
// var claims = new List<Claim>
|
||||||
|
// {
|
||||||
|
// new("id", user.Id.ToString()),
|
||||||
|
// new(ClaimsIdentity.DefaultNameClaimType, user.Login),
|
||||||
|
// new("idCompany", user.IdCompany.ToString()),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
|
||||||
|
|
||||||
|
// const string secret = "супер секретный ключ для шифрования";
|
||||||
|
|
||||||
|
// var key = Encoding.ASCII.GetBytes(secret);
|
||||||
|
// var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
|
// {
|
||||||
|
// Issuer = "a",
|
||||||
|
// Audience = "a",
|
||||||
|
// Subject = new ClaimsIdentity(claims),
|
||||||
|
// Expires = DateTime.UtcNow.AddHours(1),
|
||||||
|
// SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||||
|
// };
|
||||||
|
// var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
// var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
|
// return tokenHandler.WriteToken(token);
|
||||||
|
//}
|
||||||
|
}
|
@ -17,9 +17,9 @@ public abstract class BaseIntegrationTest : IClassFixture<WebAppFactoryFixture>,
|
|||||||
|
|
||||||
protected BaseIntegrationTest(WebAppFactoryFixture factory)
|
protected BaseIntegrationTest(WebAppFactoryFixture factory)
|
||||||
{
|
{
|
||||||
scope = factory.Services.CreateScope();
|
//scope = factory.Services.CreateScope();
|
||||||
|
|
||||||
dbContext = scope.ServiceProvider.GetRequiredService<PersistenceDbContext>();
|
//dbContext = scope.ServiceProvider.GetRequiredService<PersistenceDbContext>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
16
Persistence.IntegrationTests/Clients/ITimeSeriesClient.cs
Normal file
16
Persistence.IntegrationTests/Clients/ITimeSeriesClient.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Persistence.Repository.Data;
|
||||||
|
using Refit;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Persistence.IntegrationTests.Clients;
|
||||||
|
public interface ITimeSeriesClient<TDto>
|
||||||
|
where TDto : class, new()
|
||||||
|
{
|
||||||
|
[Post("/api/dataSaub")]
|
||||||
|
Task<IApiResponse<int>> InsertRangeAsync(IEnumerable<TDto> dtos);
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
using Persistence.Client;
|
using Persistence.Repository.Data;
|
||||||
using Persistence.Database.Model;
|
using System;
|
||||||
using Persistence.Repository.Data;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Persistence.IntegrationTests.Controllers;
|
namespace Persistence.IntegrationTests.Controllers;
|
||||||
public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaub, DataSaubDto>
|
public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaubDto>
|
||||||
{
|
{
|
||||||
private readonly DataSaubDto dto = new DataSaubDto()
|
private readonly DataSaubDto dto = new DataSaubDto()
|
||||||
{
|
{
|
||||||
@ -12,32 +15,10 @@ public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaub, Dat
|
|||||||
BitDepth = 2,
|
BitDepth = 2,
|
||||||
BlockPosition = 3,
|
BlockPosition = 3,
|
||||||
BlockSpeed = 4,
|
BlockSpeed = 4,
|
||||||
Date = DateTimeOffset.UtcNow,
|
Date = DateTimeOffset.Now,
|
||||||
Flow = 5,
|
|
||||||
HookWeight = 6,
|
|
||||||
IdFeedRegulator = 8,
|
|
||||||
Mode = 9,
|
|
||||||
Mse = 10,
|
|
||||||
MseState = 11,
|
|
||||||
Pressure = 12,
|
|
||||||
Pump0Flow = 13,
|
|
||||||
Pump1Flow = 14,
|
|
||||||
Pump2Flow = 15,
|
|
||||||
RotorSpeed = 16,
|
|
||||||
RotorTorque = 17,
|
|
||||||
User = string.Empty,
|
|
||||||
WellDepth = 18,
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly DataSaub entity = new DataSaub()
|
|
||||||
{
|
|
||||||
AxialLoad = 1,
|
|
||||||
BitDepth = 2,
|
|
||||||
BlockPosition = 3,
|
|
||||||
BlockSpeed = 4,
|
|
||||||
Date = DateTimeOffset.UtcNow,
|
|
||||||
Flow = 5,
|
Flow = 5,
|
||||||
HookWeight = 6,
|
HookWeight = 6,
|
||||||
|
Id = 7,
|
||||||
IdFeedRegulator = 8,
|
IdFeedRegulator = 8,
|
||||||
Mode = 9,
|
Mode = 9,
|
||||||
Mse = 10,
|
Mse = 10,
|
||||||
@ -61,26 +42,4 @@ public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaub, Dat
|
|||||||
{
|
{
|
||||||
await InsertRangeSuccess(dto);
|
await InsertRangeSuccess(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Get_returns_success()
|
|
||||||
{
|
|
||||||
var beginDate = DateTimeOffset.UtcNow.AddDays(-1);
|
|
||||||
var endDate = DateTimeOffset.UtcNow;
|
|
||||||
await GetSuccess(beginDate, endDate, entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetDatesRange_returns_success()
|
|
||||||
{
|
|
||||||
await GetDatesRangeSuccess(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetResampledData_returns_success()
|
|
||||||
{
|
|
||||||
await GetResampledDataSuccess(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,159 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Persistence.Client;
|
|
||||||
using Persistence.Client.Clients;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Persistence.IntegrationTests.Controllers
|
|
||||||
{
|
|
||||||
public class SetpointControllerTest : BaseIntegrationTest
|
|
||||||
{
|
|
||||||
private ISetpointClient setpointClient;
|
|
||||||
private class TestObject
|
|
||||||
{
|
|
||||||
public string? value1 { get; set; }
|
|
||||||
public int? value2 { get; set; }
|
|
||||||
}
|
|
||||||
public SetpointControllerTest(WebAppFactoryFixture factory) : base(factory)
|
|
||||||
{
|
|
||||||
var scope = factory.Services.CreateScope();
|
|
||||||
var persistenceClientFactory = scope.ServiceProvider
|
|
||||||
.GetRequiredService<PersistenceClientFactory>();
|
|
||||||
|
|
||||||
setpointClient = persistenceClientFactory.GetClient<ISetpointClient>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetCurrent_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKeys = new List<Guid>()
|
|
||||||
{
|
|
||||||
Guid.NewGuid(),
|
|
||||||
Guid.NewGuid()
|
|
||||||
};
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.GetCurrent(setpointKeys);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.Empty(response.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetCurrent_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKey = await Save();
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.GetCurrent([setpointKey]);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.NotEmpty(response.Content);
|
|
||||||
Assert.Equal(setpointKey, response.Content.FirstOrDefault()?.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetHistory_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKeys = new List<Guid>()
|
|
||||||
{
|
|
||||||
Guid.NewGuid(),
|
|
||||||
Guid.NewGuid()
|
|
||||||
};
|
|
||||||
var historyMoment = DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.GetHistory(setpointKeys, historyMoment);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.Empty(response.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetHistory_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKey = await Save();
|
|
||||||
var historyMoment = DateTimeOffset.UtcNow;
|
|
||||||
historyMoment = historyMoment.AddDays(1);
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.GetHistory([setpointKey], historyMoment);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.NotEmpty(response.Content);
|
|
||||||
Assert.Equal(setpointKey, response.Content.FirstOrDefault()?.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetLog_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKeys = new List<Guid>()
|
|
||||||
{
|
|
||||||
Guid.NewGuid(),
|
|
||||||
Guid.NewGuid()
|
|
||||||
};
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.GetLog(setpointKeys);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.Empty(response.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task GetLog_AfterSave_returns_success()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKey = await Save();
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.GetLog([setpointKey]);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.NotEmpty(response.Content);
|
|
||||||
Assert.Equal(setpointKey, response.Content.FirstOrDefault().Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Save_returns_success()
|
|
||||||
{
|
|
||||||
await Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Guid> Save()
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var setpointKey = Guid.NewGuid();
|
|
||||||
var setpointValue = new TestObject()
|
|
||||||
{
|
|
||||||
value1 = "1",
|
|
||||||
value2 = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
//act
|
|
||||||
var response = await setpointClient.Save(setpointKey, setpointValue);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
|
|
||||||
return setpointKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +1,26 @@
|
|||||||
|
using Mapster;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Persistence.IntegrationTests.Clients;
|
||||||
|
using Persistence.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Mapster;
|
using System.Text;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using System.Threading.Tasks;
|
||||||
using Persistence.Client;
|
|
||||||
using Persistence.Client.Clients;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Persistence.IntegrationTests.Controllers;
|
namespace Persistence.IntegrationTests.Controllers;
|
||||||
public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrationTest
|
public abstract class TimeSeriesBaseControllerTest<TDto> : BaseIntegrationTest
|
||||||
where TEntity : class, ITimestampedData, new()
|
|
||||||
where TDto : class, new()
|
where TDto : class, new()
|
||||||
{
|
{
|
||||||
private ITimeSeriesClient<TDto> timeSeriesClient;
|
private ITimeSeriesClient<TDto> client;
|
||||||
|
|
||||||
public TimeSeriesBaseControllerTest(WebAppFactoryFixture factory) : base(factory)
|
public TimeSeriesBaseControllerTest(WebAppFactoryFixture factory) : base(factory)
|
||||||
{
|
{
|
||||||
dbContext.CleanupDbSet<TEntity>();
|
//dbContext.CleanupDbSet<TEntity>();
|
||||||
|
client = factory.GetHttpClient<ITimeSeriesClient<TDto>>(string.Empty);
|
||||||
var scope = factory.Services.CreateScope();
|
|
||||||
var persistenceClientFactory = scope.ServiceProvider
|
|
||||||
.GetRequiredService<PersistenceClientFactory>();
|
|
||||||
|
|
||||||
timeSeriesClient = persistenceClientFactory.GetClient<ITimeSeriesClient<TDto>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InsertRangeSuccess(TDto dto)
|
public async Task InsertRangeSuccess(TDto dto)
|
||||||
@ -30,96 +29,23 @@ public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrat
|
|||||||
var expected = dto.Adapt<TDto>();
|
var expected = dto.Adapt<TDto>();
|
||||||
|
|
||||||
//act
|
//act
|
||||||
var response = await timeSeriesClient.InsertRange(new TDto[] { expected });
|
var response = await client.InsertRangeAsync(new TDto[] { expected });
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
Assert.Equal(1, response.Content);
|
Assert.Equal(1, response.Content);
|
||||||
|
|
||||||
|
//var entity = GetByWellId();
|
||||||
|
|
||||||
|
//Assert.NotNull(entity);
|
||||||
|
|
||||||
|
//var actual = entity.Adapt<ChangeLogDto<TDto>>();
|
||||||
|
//Assert.Equal(ProcessMapPlanBase.IdStateActual, actual.IdState);
|
||||||
|
|
||||||
|
//var excludeProps = new[] {
|
||||||
|
// nameof(ProcessMapPlanBaseDto.Id),
|
||||||
|
// nameof(ProcessMapPlanBaseDto.Section)
|
||||||
|
//};
|
||||||
|
//MatchHelper.Match(expected, actual.Item, excludeProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetSuccess(DateTimeOffset beginDate, DateTimeOffset endDate, TEntity entity)
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var dbset = dbContext.Set<TEntity>();
|
|
||||||
|
|
||||||
dbset.Add(entity);
|
|
||||||
|
|
||||||
dbContext.SaveChanges();
|
|
||||||
|
|
||||||
var response = await timeSeriesClient.Get(beginDate, endDate);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
Assert.Single(response.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task GetDatesRangeSuccess(TEntity entity)
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var datesRangeExpected = 30;
|
|
||||||
|
|
||||||
var entity2 = entity.Adapt<TEntity>();
|
|
||||||
entity2.Date = entity.Date.AddDays(datesRangeExpected);
|
|
||||||
|
|
||||||
var dbset = dbContext.Set<TEntity>();
|
|
||||||
dbset.Add(entity);
|
|
||||||
dbset.Add(entity2);
|
|
||||||
|
|
||||||
dbContext.SaveChanges();
|
|
||||||
|
|
||||||
var response = await timeSeriesClient.GetDatesRange();
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
|
|
||||||
var datesRangeActual = (response.Content.To - response.Content.From).Days;
|
|
||||||
Assert.Equal(datesRangeExpected, datesRangeActual);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task GetResampledDataSuccess(TEntity entity)
|
|
||||||
{
|
|
||||||
//arrange
|
|
||||||
var approxPointsCount = 10;
|
|
||||||
var differenceBetweenStartAndEndDays = 50;
|
|
||||||
|
|
||||||
var entities = new List<TEntity>();
|
|
||||||
for (var i = 1; i <= differenceBetweenStartAndEndDays; i++)
|
|
||||||
{
|
|
||||||
var entity2 = entity.Adapt<TEntity>();
|
|
||||||
entity2.Date = entity.Date.AddDays(i - 1);
|
|
||||||
|
|
||||||
entities.Add(entity2);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dbset = dbContext.Set<TEntity>();
|
|
||||||
dbset.AddRange(entities);
|
|
||||||
|
|
||||||
dbContext.SaveChanges();
|
|
||||||
|
|
||||||
var response = await timeSeriesClient.GetResampledData(entity.Date.AddMinutes(-1), differenceBetweenStartAndEndDays * 24 * 60 * 60 + 60, approxPointsCount);
|
|
||||||
|
|
||||||
//assert
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
||||||
Assert.NotNull(response.Content);
|
|
||||||
|
|
||||||
var ratio = entities.Count() / approxPointsCount;
|
|
||||||
if (ratio > 1)
|
|
||||||
{
|
|
||||||
var expectedResampledCount = entities
|
|
||||||
.Where((_, index) => index % ratio == 0)
|
|
||||||
.Count();
|
|
||||||
|
|
||||||
Assert.Equal(expectedResampledCount, response.Content.Count());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert.Equal(entities.Count(), response.Content.Count());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
|
|
||||||
namespace Persistence.IntegrationTests;
|
|
||||||
public static class EFCoreExtensions
|
|
||||||
{
|
|
||||||
public static void CleanupDbSet<T>(this DbContext dbContext)
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
var dbset = dbContext.Set<T>();
|
|
||||||
dbset.RemoveRange(dbset);
|
|
||||||
dbContext.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,6 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
<PackageReference Include="Refit" Version="8.0.0" />
|
<PackageReference Include="Refit" Version="8.0.0" />
|
||||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
@ -25,8 +24,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Persistence.API\Persistence.API.csproj" />
|
<ProjectReference Include="..\Persistence.API\Persistence.API.csproj" />
|
||||||
<ProjectReference Include="..\Persistence.Client\Persistence.Client.csproj" />
|
|
||||||
<ProjectReference Include="..\Persistence.Database.Postgres\Persistence.Database.Postgres.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
namespace Persistence.IntegrationTests
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Фабрика HTTP клиентов для интеграционных тестов
|
|
||||||
/// </summary>
|
|
||||||
public class TestHttpClientFactory : IHttpClientFactory
|
|
||||||
{
|
|
||||||
private readonly WebAppFactoryFixture factory;
|
|
||||||
|
|
||||||
public TestHttpClientFactory(WebAppFactoryFixture factory)
|
|
||||||
{
|
|
||||||
this.factory = factory;
|
|
||||||
}
|
|
||||||
public HttpClient CreateClient(string name)
|
|
||||||
{
|
|
||||||
return factory.CreateClient();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +1,58 @@
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc.Testing;
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
||||||
using Persistence.API;
|
|
||||||
using Persistence.Client;
|
|
||||||
using Persistence.Database.Model;
|
using Persistence.Database.Model;
|
||||||
using Persistence.Database.Postgres;
|
using Persistence.API;
|
||||||
using RestSharp;
|
using Refit;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Persistence.IntegrationTests;
|
namespace Persistence.IntegrationTests;
|
||||||
public class WebAppFactoryFixture : WebApplicationFactory<Startup>
|
public class WebAppFactoryFixture : WebApplicationFactory<Startup>
|
||||||
{
|
{
|
||||||
private string connectionString = string.Empty;
|
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
PropertyNameCaseInsensitive = true,
|
||||||
|
//Converters = { new ValidationResultConverter() }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions));
|
||||||
|
|
||||||
|
private readonly string connectionString;
|
||||||
|
|
||||||
|
public WebAppFactoryFixture()
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.Tests.json")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var dbConnection = configuration.GetSection("DbConnection").Get<DbConnection>()!;
|
||||||
|
connectionString = dbConnection.GetConnectionString();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||||
{
|
{
|
||||||
builder.ConfigureAppConfiguration((hostingContext, config) =>
|
|
||||||
{
|
|
||||||
config.AddJsonFile("appsettings.Tests.json");
|
|
||||||
|
|
||||||
var dbConnection = config.Build().GetSection("DbConnection").Get<DbConnection>()!;
|
|
||||||
connectionString = dbConnection.GetConnectionString();
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.ConfigureServices(services =>
|
builder.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<PersistenceDbContext>));
|
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<PersistenceDbContext>));
|
||||||
|
|
||||||
if (descriptor != null)
|
if (descriptor != null)
|
||||||
services.Remove(descriptor);
|
services.Remove(descriptor);
|
||||||
|
|
||||||
services.AddDbContext<PersistenceDbContext>(options =>
|
services.AddDbContext<PersistenceDbContext>(options =>
|
||||||
options.UseNpgsql(connectionString));
|
options.UseNpgsql(connectionString));
|
||||||
|
|
||||||
services.RemoveAll<IHttpClientFactory>();
|
|
||||||
services.AddSingleton<IHttpClientFactory>(provider =>
|
|
||||||
{
|
|
||||||
return new TestHttpClientFactory(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddSingleton<PersistenceClientFactory>();
|
|
||||||
|
|
||||||
var serviceProvider = services.BuildServiceProvider();
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
|
||||||
using var scope = serviceProvider.CreateScope();
|
using var scope = serviceProvider.CreateScope();
|
||||||
var scopedServices = scope.ServiceProvider;
|
var scopedServices = scope.ServiceProvider;
|
||||||
|
|
||||||
var dbContext = scopedServices.GetRequiredService<PersistenceDbContext>();
|
var dbContext = scopedServices.GetRequiredService<PersistenceDbContext>();
|
||||||
dbContext.Database.EnsureCreatedAndMigrated();
|
|
||||||
|
//dbContext.Database.EnsureCreatedAndMigrated();
|
||||||
|
//dbContext.Deposits.AddRange(Data.Defaults.Deposits);
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -61,4 +66,36 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>
|
|||||||
|
|
||||||
await dbContext.Database.EnsureDeletedAsync();
|
await dbContext.Database.EnsureDeletedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T GetHttpClient<T>(string uriSuffix)
|
||||||
|
{
|
||||||
|
var httpClient = CreateClient();
|
||||||
|
if (string.IsNullOrEmpty(uriSuffix))
|
||||||
|
return RestService.For<T>(httpClient, RefitSettings);
|
||||||
|
|
||||||
|
if (httpClient.BaseAddress is not null)
|
||||||
|
httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix);
|
||||||
|
|
||||||
|
return RestService.For<T>(httpClient, RefitSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
//public T GetAuthorizedHttpClient<T>(string uriSuffix)
|
||||||
|
//{
|
||||||
|
// var httpClient = GetAuthorizedHttpClient();
|
||||||
|
// if (string.IsNullOrEmpty(uriSuffix))
|
||||||
|
// return RestService.For<T>(httpClient, RefitSettings);
|
||||||
|
|
||||||
|
// if (httpClient.BaseAddress is not null)
|
||||||
|
// httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix);
|
||||||
|
|
||||||
|
// return RestService.For<T>(httpClient, RefitSettings);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private HttpClient GetAuthorizedHttpClient()
|
||||||
|
//{
|
||||||
|
// var httpClient = CreateClient();
|
||||||
|
// var jwtToken = ApiTokenHelper.GetAdminUserToken();
|
||||||
|
// httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
|
||||||
|
// return httpClient;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
@ -1,199 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Persistence.Repository;
|
|
||||||
/// <summary>
|
|
||||||
/// Цикличный массив
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
public class CyclicArray<T> : IEnumerable<T>
|
|
||||||
{
|
|
||||||
readonly T[] array;
|
|
||||||
int used, current = -1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity"></param>
|
|
||||||
public CyclicArray(int capacity)
|
|
||||||
{
|
|
||||||
array = new T[capacity];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Количество элементов в массиве
|
|
||||||
/// </summary>
|
|
||||||
public int Count => used;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Добавить новый элемент<br/>
|
|
||||||
/// Если capacity достигнуто, то вытеснит самый первый элемент
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item"></param>
|
|
||||||
public void Add(T item)
|
|
||||||
{
|
|
||||||
current = (++current) % array.Length;
|
|
||||||
array[current] = item;
|
|
||||||
if (used < array.Length)
|
|
||||||
used++;
|
|
||||||
UpdatedInvoke(current, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Добавить новые элементы.<br/>
|
|
||||||
/// Если capacity достигнуто, то вытеснит самые первые элементы.<br/>
|
|
||||||
/// Не вызывает Updated!
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="items"></param>
|
|
||||||
public void AddRange(IEnumerable<T> items)
|
|
||||||
{
|
|
||||||
var capacity = array.Length;
|
|
||||||
var newItems = items.TakeLast(capacity).ToArray();
|
|
||||||
if (newItems.Length == capacity)
|
|
||||||
{
|
|
||||||
Array.Copy(newItems, array, capacity);
|
|
||||||
current = capacity - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current = (++current) % capacity;
|
|
||||||
var countToEndOfArray = capacity - current;
|
|
||||||
if (newItems.Length <= countToEndOfArray)
|
|
||||||
{
|
|
||||||
Array.Copy(newItems, 0, array, current, newItems.Length);
|
|
||||||
current += newItems.Length - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var firstStepLength = countToEndOfArray;
|
|
||||||
Array.Copy(newItems, 0, array, current, firstStepLength);
|
|
||||||
var secondStepCount = newItems.Length - firstStepLength;
|
|
||||||
Array.Copy(newItems, firstStepLength, array, 0, secondStepCount);
|
|
||||||
current = secondStepCount - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (used < capacity)
|
|
||||||
{
|
|
||||||
used += newItems.Length;
|
|
||||||
used = used > capacity ? capacity : used;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Индекс
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public T this[int index]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (used == 0)
|
|
||||||
throw new IndexOutOfRangeException();
|
|
||||||
|
|
||||||
var i = (current + 1 + index) % used;
|
|
||||||
return array[i];
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var devider = used > 0 ? used : array.Length;
|
|
||||||
var i = (current + 1 + index) % devider;
|
|
||||||
array[i] = value;
|
|
||||||
UpdatedInvoke(current, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// событие на изменение элемента в массиве
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<(int index, T value)>? Updated;
|
|
||||||
private void UpdatedInvoke(int index, T value)
|
|
||||||
{
|
|
||||||
Updated?.Invoke(this, (index, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Агрегирование значения по всему массиву
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="Tout"></typeparam>
|
|
||||||
/// <param name="func"></param>
|
|
||||||
/// <param name="startValue"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Tout Aggregate<Tout>(Func<T, Tout, Tout> func, Tout startValue)
|
|
||||||
{
|
|
||||||
Tout result = startValue;
|
|
||||||
for (int i = 0; i < used; i++)
|
|
||||||
result = func(this[i], result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
|
||||||
=> new CyclycListEnumerator<T>(array, current, used);
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
=> GetEnumerator();
|
|
||||||
|
|
||||||
class CyclycListEnumerator<Te> : IEnumerator<Te>
|
|
||||||
{
|
|
||||||
private readonly Te[] array;
|
|
||||||
private readonly int used;
|
|
||||||
private readonly int first;
|
|
||||||
private int current = -1;
|
|
||||||
|
|
||||||
public CyclycListEnumerator(Te[] array, int first, int used)
|
|
||||||
{
|
|
||||||
this.array = new Te[array.Length];
|
|
||||||
array.CopyTo(this.array, 0);
|
|
||||||
this.used = used;
|
|
||||||
this.first = first;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Te Current
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (IsCurrentOk())
|
|
||||||
{
|
|
||||||
var i = (current + first + 1) % used;
|
|
||||||
return array[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return default!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object? IEnumerator.Current => Current;
|
|
||||||
|
|
||||||
public void Dispose() {; }
|
|
||||||
|
|
||||||
private bool IsCurrentOk() => current >= 0 && current < used;
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
if (current < used)
|
|
||||||
current++;
|
|
||||||
return IsCurrentOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
current = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Очистить весь массив
|
|
||||||
/// </summary>
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
used = 0;
|
|
||||||
current = -1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,8 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace Persistence.Repository.Data;
|
namespace Persistence.Repository.Data;
|
||||||
public class DataSaubDto : ITimeSeriesAbstractDto
|
public class DataSaubDto : ITimeSeriesAbstractDto
|
||||||
{
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset Date { get; set; } = DateTimeOffset.UtcNow;
|
public DateTimeOffset Date { get; set; } = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
public int? Mode { get; set; }
|
public int? Mode { get; set; }
|
||||||
|
16
Persistence.Repository/Data/LogDto.cs
Normal file
16
Persistence.Repository/Data/LogDto.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Persistence.Models;
|
||||||
|
|
||||||
|
namespace Persistence.Repository.Data
|
||||||
|
{
|
||||||
|
internal class LogDto : IChangeLogAbstract
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int IdAuthor { get; set; }
|
||||||
|
public int? IdNext { get; set; }
|
||||||
|
public int? IdPrevious { get; set; }
|
||||||
|
public int? IdEditor { get; set; }
|
||||||
|
public int IdState { get; set; }
|
||||||
|
public DateTimeOffset Creation { get; set; }
|
||||||
|
public DateTimeOffset? Obsolete { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +0,0 @@
|
|||||||
namespace Persistence.Repository.Data
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Модель для работы с уставкой
|
|
||||||
/// </summary>
|
|
||||||
public class SetpointDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Идентификатор уставки
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Значение уставки
|
|
||||||
/// </summary>
|
|
||||||
public required object Value { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Дата сохранения уставки
|
|
||||||
/// </summary>
|
|
||||||
public DateTimeOffset Edit { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ключ пользователя
|
|
||||||
/// </summary>
|
|
||||||
public int IdUser { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,11 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Persistence.Database.Model;
|
|
||||||
using Persistence.Repositories;
|
using Persistence.Repositories;
|
||||||
|
using Persistence.Database.Model;
|
||||||
using Persistence.Repository.Data;
|
using Persistence.Repository.Data;
|
||||||
using Persistence.Repository.Repositories;
|
using Persistence.Repository.Repositories;
|
||||||
|
using Persistence.Models;
|
||||||
|
|
||||||
namespace Persistence.Repository;
|
namespace Persistence.Repository;
|
||||||
public static class DependencyInjection
|
public static class DependencyInjection
|
||||||
@ -10,13 +13,19 @@ public static class DependencyInjection
|
|||||||
public static void MapsterSetup()
|
public static void MapsterSetup()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||||
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
|
|
||||||
{
|
{
|
||||||
MapsterSetup();
|
MapsterSetup();
|
||||||
|
|
||||||
|
string connectionStringName = "DefaultConnection";
|
||||||
|
|
||||||
|
services.AddDbContext<PersistenceDbContext>(options =>
|
||||||
|
options.UseNpgsql(configuration.GetConnectionString(connectionStringName)));
|
||||||
|
|
||||||
|
services.AddScoped<IPersistenceDbContext>(provider => provider.GetRequiredService<PersistenceDbContext>());
|
||||||
|
|
||||||
services.AddTransient<ITimeSeriesDataRepository<DataSaubDto>, TimeSeriesDataRepository<DataSaub, DataSaubDto>>();
|
services.AddTransient<ITimeSeriesDataRepository<DataSaubDto>, TimeSeriesDataRepository<DataSaub, DataSaubDto>>();
|
||||||
services.AddTransient<ISetpointRepository, SetpointRepository>();
|
services.AddTransient<IChangeLogRepository<LogDto, ChangeLogDto<LogDto>>, ChangeLogRepository<ChangeLog, LogDto, ChangeLogDto<LogDto>>>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
71
Persistence.Repository/Repositories/ChangeLogRepository.cs
Normal file
71
Persistence.Repository/Repositories/ChangeLogRepository.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Persistence.Models;
|
||||||
|
using Persistence.Repositories;
|
||||||
|
|
||||||
|
namespace Persistence.Repository.Repositories
|
||||||
|
{
|
||||||
|
public abstract class ChangeLogRepository<TEntity, TDto, TChangeLogDto> : IChangeLogRepository<TDto, TChangeLogDto>
|
||||||
|
where TEntity : class
|
||||||
|
where TDto : class, IChangeLogAbstract, new()
|
||||||
|
where TChangeLogDto : ChangeLogDto<TDto>
|
||||||
|
{
|
||||||
|
private DbContext db;
|
||||||
|
|
||||||
|
public ChangeLogRepository(DbContext db)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual IQueryable<TEntity> GetQueryReadOnly() => db.Set<TEntity>();
|
||||||
|
|
||||||
|
public Task<int> Clear(int idUser, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> ClearAndInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<TChangeLogDto>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<TDto>> GetCurrent(DateTimeOffset moment, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<DateOnly>> GetDatesChange(CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> InsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> MarkAsDeleted(int idUser, IEnumerable<int> ids, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> UpdateOrInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> UpdateRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,73 +0,0 @@
|
|||||||
using Mapster;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
using Persistence.Models;
|
|
||||||
using Persistence.Repositories;
|
|
||||||
|
|
||||||
namespace Persistence.Repository.Repositories
|
|
||||||
{
|
|
||||||
public class SetpointRepository : ISetpointRepository
|
|
||||||
{
|
|
||||||
private DbContext db;
|
|
||||||
public SetpointRepository(DbContext db)
|
|
||||||
{
|
|
||||||
this.db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual IQueryable<Setpoint> GetQueryReadOnly() => db.Set<Setpoint>();
|
|
||||||
|
|
||||||
public async Task<IEnumerable<SetpointValueDto>> GetCurrent(IEnumerable<Guid> setpointKeys, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly();
|
|
||||||
var entities = await query
|
|
||||||
.Where(e => setpointKeys.Contains(e.Key))
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
var dtos = entities.Select(e => e.Adapt<SetpointValueDto>());
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<SetpointValueDto>> GetHistory(IEnumerable<Guid> setpointKeys, DateTimeOffset historyMoment, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly();
|
|
||||||
var entities = await query
|
|
||||||
.Where(e => setpointKeys.Contains(e.Key))
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
var filteredEntities = entities
|
|
||||||
.GroupBy(e => e.Key)
|
|
||||||
.Select(e => e.OrderBy(o => o.Created))
|
|
||||||
.Select(e => e.Where(e => e.Created <= historyMoment).Last());
|
|
||||||
var dtos = filteredEntities
|
|
||||||
.Select(e => e.Adapt<SetpointValueDto>());
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Dictionary<Guid, IEnumerable<SetpointLogDto>>> GetLog(IEnumerable<Guid> setpointKeys, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly();
|
|
||||||
var entities = await query
|
|
||||||
.Where(e => setpointKeys.Contains(e.Key))
|
|
||||||
.ToArrayAsync(token);
|
|
||||||
var dtos = entities
|
|
||||||
.GroupBy(e => e.Key)
|
|
||||||
.ToDictionary(e => e.Key, v => v.Select(z => z.Adapt<SetpointLogDto>()));
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Save(Guid setpointKey, object newValue, int idUser, CancellationToken token)
|
|
||||||
{
|
|
||||||
var entity = new Setpoint()
|
|
||||||
{
|
|
||||||
Key = setpointKey,
|
|
||||||
Value = newValue,
|
|
||||||
IdUser = idUser,
|
|
||||||
Created = DateTimeOffset.UtcNow
|
|
||||||
};
|
|
||||||
|
|
||||||
await db.Set<Setpoint>().AddAsync(entity, token);
|
|
||||||
await db.SaveChangesAsync(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
using Mapster;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Persistence.Database.Model;
|
|
||||||
using Persistence.Models;
|
|
||||||
|
|
||||||
namespace Persistence.Repository.Repositories;
|
|
||||||
|
|
||||||
public class TimeSeriesDataCachedRepository<TEntity, TDto> : TimeSeriesDataRepository<TEntity, TDto>
|
|
||||||
where TEntity : class, ITimestampedData, new()
|
|
||||||
where TDto : class, ITimeSeriesAbstractDto, new()
|
|
||||||
{
|
|
||||||
public static TDto? FirstByDate { get; private set; }
|
|
||||||
public static CyclicArray<TDto> LastData { get; } = new CyclicArray<TDto>(CacheItemsCount);
|
|
||||||
|
|
||||||
private const int CacheItemsCount = 3600;
|
|
||||||
|
|
||||||
public TimeSeriesDataCachedRepository(DbContext db) : base(db)
|
|
||||||
{
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var firstDateItem = await base.GetFirstAsync(CancellationToken.None);
|
|
||||||
if (firstDateItem == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FirstByDate = firstDateItem;
|
|
||||||
|
|
||||||
var dtos = await base.GetLastAsync(CacheItemsCount, CancellationToken.None);
|
|
||||||
dtos = dtos.OrderBy(d => d.Date);
|
|
||||||
LastData.AddRange(dtos);
|
|
||||||
}).Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset dateBegin, CancellationToken token)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (LastData.Count() == 0 || LastData[0].Date > dateBegin)
|
|
||||||
{
|
|
||||||
var dtos = await base.GetGtDate(dateBegin, token);
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
var items = LastData
|
|
||||||
.Where(i => i.Date >= dateBegin);
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<int> InsertRange(IEnumerable<TDto> dtos, CancellationToken token)
|
|
||||||
{
|
|
||||||
var result = await base.InsertRange(dtos, token);
|
|
||||||
if (result > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
dtos = dtos.OrderBy(x => x.Date);
|
|
||||||
|
|
||||||
FirstByDate = dtos.First();
|
|
||||||
LastData.AddRange(dtos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
|
|
||||||
{
|
|
||||||
if (FirstByDate == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return await Task.Run(() =>
|
|
||||||
{
|
|
||||||
return new DatesRangeDto
|
|
||||||
{
|
|
||||||
From = FirstByDate.Date,
|
|
||||||
To = LastData[^1].Date
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<IEnumerable<TDto>> GetResampledData(
|
|
||||||
DateTimeOffset dateBegin,
|
|
||||||
double intervalSec = 600d,
|
|
||||||
int approxPointsCount = 1024,
|
|
||||||
CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var dtos = LastData.Where(i => i.Date >= dateBegin);
|
|
||||||
if (LastData.Count == 0 || LastData[0].Date > dateBegin)
|
|
||||||
{
|
|
||||||
dtos = await base.GetGtDate(dateBegin, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
|
||||||
dtos = dtos
|
|
||||||
.Where(i => i.Date <= dateEnd);
|
|
||||||
|
|
||||||
var ratio = dtos.Count() / approxPointsCount;
|
|
||||||
if (ratio > 1)
|
|
||||||
dtos = dtos
|
|
||||||
.Where((_, index) => index % ratio == 0);
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
|||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Persistence.Database.Model;
|
|
||||||
using Persistence.Models;
|
using Persistence.Models;
|
||||||
using Persistence.Repositories;
|
using Persistence.Repositories;
|
||||||
|
using Persistence.Database.Model;
|
||||||
|
using Persistence.Repository.Data;
|
||||||
|
|
||||||
namespace Persistence.Repository.Repositories;
|
namespace Persistence.Repository.Repositories;
|
||||||
public class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository<TDto>
|
public abstract class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository<TDto>
|
||||||
where TEntity : class, ITimestampedData, new()
|
where TEntity : class
|
||||||
where TDto : class, ITimeSeriesAbstractDto, new()
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
{
|
{
|
||||||
private DbContext db;
|
private DbContext db;
|
||||||
@ -16,32 +17,28 @@ public class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IQueryable<TEntity> GetQueryReadOnly() => this.db.Set<TEntity>();
|
protected virtual IQueryable<TEntity> GetQueryReadOnly() => db.Set<TEntity>();
|
||||||
|
|
||||||
public virtual async Task<DatesRangeDto?> GetDatesRange(CancellationToken token)
|
public async Task<IEnumerable<TDto>> GetAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
|
||||||
{
|
{
|
||||||
var query = GetQueryReadOnly();
|
var query = GetQueryReadOnly();
|
||||||
var minDate = await query.MinAsync(o => o.Date, token);
|
|
||||||
var maxDate = await query.MaxAsync(o => o.Date, token);
|
|
||||||
|
|
||||||
return new DatesRangeDto
|
|
||||||
{
|
|
||||||
From = minDate,
|
|
||||||
To = maxDate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = this.db.Set<TEntity>().Where(e => e.Date > date);
|
|
||||||
var entities = await query.ToArrayAsync(token);
|
var entities = await query.ToArrayAsync(token);
|
||||||
|
|
||||||
var dtos = entities.Select(e => e.Adapt<TDto>());
|
var dtos = entities.Select(e => e.Adapt<TDto>());
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> InsertRange(IEnumerable<TDto> dtos, CancellationToken token)
|
public Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> InsertRange(IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var entities = dtos.Select(d => d.Adapt<TEntity>());
|
var entities = dtos.Select(d => d.Adapt<TEntity>());
|
||||||
|
|
||||||
@ -50,50 +47,4 @@ public class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<IEnumerable<TDto>> GetLastAsync(int takeCount, CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly()
|
|
||||||
.OrderByDescending(e => e.Date)
|
|
||||||
.Take(takeCount);
|
|
||||||
|
|
||||||
var entities = await query.ToArrayAsync(token);
|
|
||||||
var dtos = entities.Select(e => e.Adapt<TDto>());
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task<TDto?> GetFirstAsync(CancellationToken token)
|
|
||||||
{
|
|
||||||
var query = GetQueryReadOnly()
|
|
||||||
.OrderBy(e => e.Date);
|
|
||||||
|
|
||||||
var entity = await query.FirstOrDefaultAsync(token);
|
|
||||||
|
|
||||||
if (entity == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var dto = entity.Adapt<TDto>();
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async virtual Task<IEnumerable<TDto>> GetResampledData(
|
|
||||||
DateTimeOffset dateBegin,
|
|
||||||
double intervalSec = 600d,
|
|
||||||
int approxPointsCount = 1024,
|
|
||||||
CancellationToken token = default)
|
|
||||||
{
|
|
||||||
var dtos = await GetGtDate(dateBegin, token);
|
|
||||||
|
|
||||||
var dateEnd = dateBegin.AddSeconds(intervalSec);
|
|
||||||
dtos = dtos
|
|
||||||
.Where(i => i.Date <= dateEnd);
|
|
||||||
|
|
||||||
var ratio = dtos.Count() / approxPointsCount;
|
|
||||||
if (ratio > 1)
|
|
||||||
dtos = dtos
|
|
||||||
.Where((_, index) => index % ratio == 0);
|
|
||||||
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
19
Persistence.Repository/Startup.cs
Normal file
19
Persistence.Repository/Startup.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Persistence.Database;
|
||||||
|
using Persistence.Database.Model;
|
||||||
|
|
||||||
|
namespace Persistence.Repository;
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public static void BeforeRunHandler(IHost host)
|
||||||
|
{
|
||||||
|
using var scope = host.Services.CreateScope();
|
||||||
|
var provider = scope.ServiceProvider;
|
||||||
|
|
||||||
|
var context = provider.GetRequiredService<DbContext>();
|
||||||
|
context.Database.EnsureCreatedAndMigrated();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.Repository", "P
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.Database", "Persistence.Database\Persistence.Database.csproj", "{F77475D1-D074-407A-9D69-2FADDDAE2056}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.Database", "Persistence.Database\Persistence.Database.csproj", "{F77475D1-D074-407A-9D69-2FADDDAE2056}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.IntegrationTests", "Persistence.IntegrationTests\Persistence.IntegrationTests.csproj", "{10752C25-3773-4081-A1F2-215A1D950126}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Persistence.IntegrationTests", "Persistence.IntegrationTests\Persistence.IntegrationTests.csproj", "{10752C25-3773-4081-A1F2-215A1D950126}"
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.Database.Postgres", "Persistence.Database.Postgres\Persistence.Database.Postgres.csproj", "{CC284D27-162D-490C-B6CF-74D666B7C5F3}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Persistence.Client", "Persistence.Client\Persistence.Client.csproj", "{84B68660-48E6-4974-A4E5-517552D9DE23}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -43,14 +39,6 @@ Global
|
|||||||
{10752C25-3773-4081-A1F2-215A1D950126}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{10752C25-3773-4081-A1F2-215A1D950126}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{10752C25-3773-4081-A1F2-215A1D950126}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{10752C25-3773-4081-A1F2-215A1D950126}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{10752C25-3773-4081-A1F2-215A1D950126}.Release|Any CPU.Build.0 = Release|Any CPU
|
{10752C25-3773-4081-A1F2-215A1D950126}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{CC284D27-162D-490C-B6CF-74D666B7C5F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{CC284D27-162D-490C-B6CF-74D666B7C5F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{CC284D27-162D-490C-B6CF-74D666B7C5F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{CC284D27-162D-490C-B6CF-74D666B7C5F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{84B68660-48E6-4974-A4E5-517552D9DE23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{84B68660-48E6-4974-A4E5-517552D9DE23}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{84B68660-48E6-4974-A4E5-517552D9DE23}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{84B68660-48E6-4974-A4E5-517552D9DE23}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -31,7 +31,7 @@ public interface IChangeLogApi<TDto, TChangeLogDto>
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> Add(TDto dto, CancellationToken token);
|
Task<ActionResult<int>> AddAsync(TDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавить несколько записей
|
/// Добавить несколько записей
|
||||||
@ -39,7 +39,7 @@ public interface IChangeLogApi<TDto, TChangeLogDto>
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> AddRange(IEnumerable<TDto> dtos, CancellationToken token);
|
Task<ActionResult<int>> AddRangeAsync(IEnumerable<TDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновить одну запись
|
/// Обновить одну запись
|
||||||
@ -47,7 +47,7 @@ public interface IChangeLogApi<TDto, TChangeLogDto>
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> Update(TDto dto, CancellationToken token);
|
Task<ActionResult<int>> UpdateAsync(TDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновить несколько записей
|
/// Обновить несколько записей
|
||||||
@ -55,7 +55,7 @@ public interface IChangeLogApi<TDto, TChangeLogDto>
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> UpdateRange(IEnumerable<TDto> dtos, CancellationToken token);
|
Task<ActionResult<int>> UpdateRangeAsync(IEnumerable<TDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить одну запись
|
/// Удалить одну запись
|
||||||
@ -63,7 +63,7 @@ public interface IChangeLogApi<TDto, TChangeLogDto>
|
|||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> Delete(int id, CancellationToken token);
|
Task<ActionResult<int>> DeleteAsync(int id, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить несколько записей
|
/// Удалить несколько записей
|
||||||
@ -71,5 +71,5 @@ public interface IChangeLogApi<TDto, TChangeLogDto>
|
|||||||
/// <param name="ids"></param>
|
/// <param name="ids"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> DeleteRange(IEnumerable<int> ids, CancellationToken token);
|
Task<ActionResult<int>> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ public interface IDictionaryElementApi<TDto> where TDto : class, new()
|
|||||||
/// <param name="dictionaryKey">ключ справочника</param>
|
/// <param name="dictionaryKey">ключ справочника</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<IEnumerable<TDto>>> Get(Guid dictionaryKey, CancellationToken token);
|
Task<ActionResult<IEnumerable<TDto>>> GetAsync(Guid dictionaryKey, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавить элемент в справочник
|
/// Добавить элемент в справочник
|
||||||
@ -22,7 +22,7 @@ public interface IDictionaryElementApi<TDto> where TDto : class, new()
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<Guid>> Add(Guid dictionaryKey, TDto dto, CancellationToken token);
|
Task<ActionResult<Guid>> AddAsync(Guid dictionaryKey, TDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Изменить одну запись
|
/// Изменить одну запись
|
||||||
@ -32,7 +32,7 @@ public interface IDictionaryElementApi<TDto> where TDto : class, new()
|
|||||||
/// <param name="dto"></param>
|
/// <param name="dto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<Guid>> Update(Guid dictionaryKey, Guid dictionaryElementKey, TDto dto, CancellationToken token);
|
Task<ActionResult<Guid>> UpdateAsync(Guid dictionaryKey, Guid dictionaryElementKey, TDto dto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удалить одну запись
|
/// Удалить одну запись
|
||||||
@ -41,5 +41,5 @@ public interface IDictionaryElementApi<TDto> where TDto : class, new()
|
|||||||
/// <param name="dictionaryElementKey">ключ элемента в справочнике</param>
|
/// <param name="dictionaryElementKey">ключ элемента в справочнике</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> Delete(Guid dictionaryKey, Guid dictionaryElementKey, CancellationToken token);
|
Task<ActionResult<int>> DeleteAsync(Guid dictionaryKey, Guid dictionaryElementKey, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -4,27 +4,23 @@ using Persistence.Models;
|
|||||||
namespace Persistence.API;
|
namespace Persistence.API;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Базовый интерфейс для работы с временными рядами
|
/// Интерфейс для работы с API графиков
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITimeSeriesBaseDataApi<TDto>
|
public interface IGraphDataApi<TDto>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить список объектов с прореживанием, удовлетворяющий диапазону дат
|
/// Получить список объектов с прореживанием, удовлетворящий диапазону дат
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dateBegin">дата начала</param>
|
/// <param name="dateBegin">дата начала</param>
|
||||||
/// <param name="dateEnd">дата окончания</param>
|
/// <param name="dateEnd">дата окончания</param>
|
||||||
/// <param name="approxPointsCount"></param>
|
/// <param name="approxPointsCount"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> GetResampledData(
|
Task<ActionResult<IEnumerable<TDto>>> GetThinnedDataAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd, int approxPointsCount = 1024);
|
||||||
DateTimeOffset dateBegin,
|
|
||||||
double intervalSec = 600d,
|
|
||||||
int approxPointsCount = 1024,
|
|
||||||
CancellationToken token = default);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить диапазон дат, для которых есть данные в репозитории
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> GetDatesRange(CancellationToken token);
|
Task<ActionResult<DatesRangeDto>> GetDatesRangeAsync(CancellationToken token);
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ public interface ISetpointApi
|
|||||||
/// <param name="setpoitKeys">ключи уставок</param>
|
/// <param name="setpoitKeys">ключи уставок</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<IEnumerable<SetpointValueDto>>> GetCurrent(IEnumerable<Guid> setpoitKeys, CancellationToken token);
|
Task<ActionResult<IEnumerable<SetpointValueDto>>> GetCurrentAsync(IEnumerable<Guid> setpoitKeys, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить значения уставок за определенный момент времени
|
/// Получить значения уставок за определенный момент времени
|
||||||
@ -23,7 +23,7 @@ public interface ISetpointApi
|
|||||||
/// <param name="historyMoment">дата, на которую получаем данные</param>
|
/// <param name="historyMoment">дата, на которую получаем данные</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<IEnumerable<SetpointValueDto>>> GetHistory(IEnumerable<Guid> setpoitKeys, DateTimeOffset historyMoment, CancellationToken token);
|
Task<ActionResult<IEnumerable<SetpointValueDto>>> GetHistoryAsync(IEnumerable<Guid> setpoitKeys, DateTimeOffset historyMoment, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить историю изменений значений уставок
|
/// Получить историю изменений значений уставок
|
||||||
@ -31,7 +31,7 @@ public interface ISetpointApi
|
|||||||
/// <param name="setpoitKeys">ключи уставок</param>
|
/// <param name="setpoitKeys">ключи уставок</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<Dictionary<Guid, IEnumerable<SetpointLogDto>>>> GetLog(IEnumerable<Guid> setpoitKeys, CancellationToken token);
|
Task<ActionResult<Dictionary<Guid, IEnumerable<SetpointLogDto>>>> GetLogAsync(IEnumerable<Guid> setpoitKeys, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Метод сохранения уставки
|
/// Метод сохранения уставки
|
||||||
@ -40,5 +40,5 @@ public interface ISetpointApi
|
|||||||
/// <param name="newValue">значение</param>
|
/// <param name="newValue">значение</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<int>> Save(Guid setpointKey, object newValue, CancellationToken token);
|
Task<ActionResult<int>> SaveAsync(Guid setpointKey, object newValue, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ public interface ISyncApi<TDto> where TDto : class, new()
|
|||||||
/// <param name="take">количество записей</param>
|
/// <param name="take">количество записей</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<IEnumerable<TDto>>> GetPart(DateTimeOffset dateBegin, int take = 24 * 60 * 60, CancellationToken token = default);
|
Task<ActionResult<IEnumerable<TDto>>> GetPartAsync(DateTimeOffset dateBegin, int take = 24 * 60 * 60, CancellationToken token = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить диапазон дат, для которых есть данные в репозитории
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
|
@ -19,5 +19,5 @@ public interface ITableDataApi<TDto, TRequest>
|
|||||||
/// <param name="request">параметры фильтрации</param>
|
/// <param name="request">параметры фильтрации</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<ActionResult<PaginationContainer<TDto>>> GetPage(TRequest request, CancellationToken token);
|
Task<ActionResult<PaginationContainer<TDto>>> GetPageAsync(TRequest request, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -11,16 +11,24 @@ namespace Persistence.API;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Интерфейс для работы с API временных данных
|
/// Интерфейс для работы с API временных данных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITimeSeriesDataApi<TDto> : ITimeSeriesBaseDataApi<TDto>
|
public interface ITimeSeriesDataApi<TDto>
|
||||||
where TDto : class, ITimeSeriesAbstractDto, new()
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить список объектов, удовлетворяющий диапазон дат
|
/// Получить список объектов, удовлетворяющий диапазон дат
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dateBegin">дата начала</param>
|
/// <param name="dateBegin">дата начала</param>
|
||||||
|
/// <param name="dateEnd">дата окончания</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> Get(DateTimeOffset dateBegin, CancellationToken token);
|
Task<IActionResult> GetAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IActionResult> GetDatesRangeAsync(CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавление записей
|
/// Добавление записей
|
||||||
@ -28,7 +36,7 @@ public interface ITimeSeriesDataApi<TDto> : ITimeSeriesBaseDataApi<TDto>
|
|||||||
/// <param name="dtos"></param>
|
/// <param name="dtos"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IActionResult> InsertRange(IEnumerable<TDto> dtos, CancellationToken token);
|
Task<IActionResult> InsertRangeAsync(IEnumerable<TDto> dtos, CancellationToken token);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ public class ChangeLogDto<T> where T: class
|
|||||||
public DateTimeOffset Creation { get; set; }
|
public DateTimeOffset Creation { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дата устаревания (например, при удалении)
|
/// Дата устаревания (например при удалении)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTimeOffset? Obsolete { get; set; }
|
public DateTimeOffset? Obsolete { get; set; }
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
namespace Persistence.Models.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Настройки credentials для авторизации
|
|
||||||
/// </summary>
|
|
||||||
public class AuthUser
|
|
||||||
{
|
|
||||||
public required string Username { get; set; }
|
|
||||||
public required string Password { get; set; }
|
|
||||||
public required string ClientId { get; set; }
|
|
||||||
public required string GrantType { get; set; }
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
using System.Text;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
|
|
||||||
namespace Persistence.Models.Configurations
|
|
||||||
{
|
|
||||||
public static class JwtParams
|
|
||||||
{
|
|
||||||
private static readonly string KeyValue = "супер секретный ключ для шифрования";
|
|
||||||
public static SymmetricSecurityKey SecurityKey
|
|
||||||
{
|
|
||||||
get { return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(KeyValue)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly string Issuer = "a";
|
|
||||||
|
|
||||||
public static readonly string Audience = "a";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Persistence.Models.Configurations
|
|
||||||
{
|
|
||||||
public class JwtToken
|
|
||||||
{
|
|
||||||
[JsonPropertyName("access_token")]
|
|
||||||
public required string AccessToken { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,19 +5,9 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Persistence.Models;
|
namespace Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Диапазон дат
|
|
||||||
/// </summary>
|
|
||||||
public class DatesRangeDto
|
public class DatesRangeDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
public DateTimeOffset dateBegin { get; set; }
|
||||||
/// Дата начала диапазона
|
|
||||||
/// </summary>
|
|
||||||
public DateTimeOffset From { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public DateTimeOffset dateEnd { get; set; }
|
||||||
/// Дата окончания диапазона
|
|
||||||
/// </summary>
|
|
||||||
public DateTimeOffset To { get; set; }
|
|
||||||
}
|
}
|
||||||
|
@ -59,4 +59,9 @@ public interface IChangeLogAbstract
|
|||||||
/// Id заменяемой записи
|
/// Id заменяемой записи
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? IdPrevious { get; set; }
|
public int? IdPrevious { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Id последующей записи
|
||||||
|
/// </summary>
|
||||||
|
public int? IdNext { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
namespace Persistence.Models;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Интерфейс, описывающий временные данные
|
/// Интерфейс, описывающий временные данные
|
||||||
|
@ -1,23 +1,10 @@
|
|||||||
namespace Persistence.Models;
|
namespace Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Контейнер для поддержки постраничного просмотра таблиц
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
public class RequestDto
|
public class RequestDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Кол-во записей пропущенных с начала таблицы в запросе от api
|
|
||||||
/// </summary>
|
|
||||||
public int Skip { get; set; }
|
public int Skip { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Кол-во записей в запросе от api
|
|
||||||
/// </summary>
|
|
||||||
public int Take { get; set; }
|
public int Take { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Настройки сортировки
|
|
||||||
/// </summary>
|
|
||||||
public string SortSettings { get; set; } = string.Empty;
|
public string SortSettings { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
namespace Persistence.Models;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
/// <summary>
|
namespace Persistence.Models;
|
||||||
/// Модель для описания лога уставки
|
|
||||||
/// </summary>
|
|
||||||
public class SetpointLogDto : SetpointValueDto
|
public class SetpointLogDto : SetpointValueDto
|
||||||
{
|
{
|
||||||
/// <summary>
|
public DateTimeOffset Edit { get; set; }
|
||||||
/// Дата сохранения уставки
|
|
||||||
/// </summary>
|
|
||||||
public DateTimeOffset Created { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ключ пользователя
|
|
||||||
/// </summary>
|
|
||||||
public int IdUser { get; set; }
|
public int IdUser { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Persistence.Models;
|
namespace Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Модель для хранения значения уставки
|
|
||||||
/// </summary>
|
|
||||||
public class SetpointValueDto
|
public class SetpointValueDto
|
||||||
{
|
{
|
||||||
/// Идентификатор уставки
|
public int Id { get; set; }
|
||||||
/// <summary>
|
public object Value { get; set; }
|
||||||
/// </summary>
|
|
||||||
public Guid Key { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Значение уставки
|
|
||||||
/// </summary>
|
|
||||||
public required object Value { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
namespace Persistence.Models;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
/// <summary>
|
namespace Persistence.Models;
|
||||||
/// Модель, описывающая пользователя
|
|
||||||
/// </summary>
|
|
||||||
public class UserDto
|
public class UserDto
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.2.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -7,7 +7,7 @@ namespace Persistence.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TDto"></typeparam>
|
/// <typeparam name="TDto"></typeparam>
|
||||||
public interface IChangeLogRepository<TDto, TChangeLogDto> : ISyncRepository<TDto>
|
public interface IChangeLogRepository<TDto, TChangeLogDto> : ISyncRepository<TDto>
|
||||||
where TDto : class, ITimeSeriesAbstractDto, new()
|
where TDto : class, IChangeLogAbstract, new()
|
||||||
where TChangeLogDto : ChangeLogDto<TDto>
|
where TChangeLogDto : ChangeLogDto<TDto>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -5,25 +5,22 @@ namespace Persistence.Repositories;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Интерфейс по работе с прореженными данными
|
/// Интерфейс по работе с прореженными данными
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITimeSeriesBaseRepository<TDto>
|
public interface IGraphDataRepository<TDto>
|
||||||
where TDto : class, new()
|
where TDto : class, new()
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить список объектов с прореживанием
|
/// Получить список объектов с прореживанием
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dateBegin">дата начала</param>
|
/// <param name="dateBegin">дата начала</param>
|
||||||
|
/// <param name="dateEnd">дата окончания</param>
|
||||||
/// <param name="approxPointsCount"></param>
|
/// <param name="approxPointsCount"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<TDto>> GetResampledData(
|
Task<IEnumerable<TDto>> GetThinnedDataAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd, int approxPointsCount = 1024);
|
||||||
DateTimeOffset dateBegin,
|
|
||||||
double intervalSec = 600d,
|
|
||||||
int approxPointsCount = 1024,
|
|
||||||
CancellationToken token = default);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить диапазон дат, для которых есть данные в репозитории
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<DatesRangeDto?> GetDatesRange(CancellationToken token);
|
Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token);
|
||||||
}
|
}
|
@ -1,4 +1,10 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Persistence.Models;
|
using Persistence.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Persistence.Repositories;
|
namespace Persistence.Repositories;
|
||||||
|
|
||||||
@ -7,30 +13,23 @@ namespace Persistence.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISetpointRepository
|
public interface ISetpointRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Получить значения уставок по набору ключей
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="setpointKeys"></param>
|
|
||||||
/// <param name="token"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<IEnumerable<SetpointValueDto>> GetCurrent(IEnumerable<Guid> setpointKeys, CancellationToken token);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить значения уставок за определенный момент времени
|
/// Получить значения уставок за определенный момент времени
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="setpointKeys"></param>
|
/// <param name="setpoitKeys"></param>
|
||||||
/// <param name="historyMoment">дата, на которую получаем данные</param>
|
/// <param name="historyMoment">дата, на которую получаем данные</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<SetpointValueDto>> GetHistory(IEnumerable<Guid> setpointKeys, DateTimeOffset historyMoment, CancellationToken token);
|
Task<IEnumerable<SetpointValueDto>> GetHistoryAsync(IEnumerable<Guid> setpoitKeys, DateTimeOffset historyMoment, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получить историю изменений значений уставок
|
/// Получить историю изменений значений уставок
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="setpointKeys"></param>
|
/// <param name="setpoitKeys"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Dictionary<Guid, IEnumerable<SetpointLogDto>>> GetLog(IEnumerable<Guid> setpointKeys, CancellationToken token);
|
Task<Dictionary<Guid, IEnumerable<SetpointLogDto>>> GetLogAsync(IEnumerable<Guid> setpoitKeys, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Метод сохранения уставки
|
/// Метод сохранения уставки
|
||||||
@ -42,5 +41,5 @@ public interface ISetpointRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// to do
|
/// to do
|
||||||
/// id User учесть в соответствующем методе репозитория
|
/// id User учесть в соответствующем методе репозитория
|
||||||
Task Save(Guid setpointKey, object newValue, int idUser, CancellationToken token);
|
Task<int> SaveAsync(Guid setpointKey, int idUser, object newValue, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -15,5 +15,5 @@ public interface ITableDataRepository<TDto, TRequest>
|
|||||||
/// <param name="request">параметры фильтрации</param>
|
/// <param name="request">параметры фильтрации</param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<IEnumerable<TDto>> Get(TRequest request, CancellationToken token);
|
Task<IEnumerable<TDto>> GetAsync(TRequest request, CancellationToken token);
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,24 @@ namespace Persistence.Repositories;
|
|||||||
/// Интерфейс по работе с временными данными
|
/// Интерфейс по работе с временными данными
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TDto"></typeparam>
|
/// <typeparam name="TDto"></typeparam>
|
||||||
public interface ITimeSeriesDataRepository<TDto> : ISyncRepository<TDto>, ITimeSeriesBaseRepository<TDto>
|
public interface ITimeSeriesDataRepository<TDto> : ISyncRepository<TDto>
|
||||||
where TDto : class, ITimeSeriesAbstractDto, new()
|
where TDto : class, ITimeSeriesAbstractDto, new()
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Получить страницу списка объектов
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dateBegin">дата начала</param>
|
||||||
|
/// <param name="dateEnd">дата окончания</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<TDto>> GetAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить диапазон дат, для которых есть данные в репозитории
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавление записей
|
/// Добавление записей
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
namespace Persistence.Services;
|
namespace Persistence.Services;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сервис по работе с БД
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface IArchiveService
|
internal interface IArchiveService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Переименование БД
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connectionString"></param>
|
/// <param name="connectionString"></param>
|
||||||
/// <param name="databaseName"></param>
|
/// <param name="databaseName"></param>
|
||||||
@ -15,7 +15,7 @@ internal interface IArchiveService
|
|||||||
Task RenameDatabase(string connectionString, string databaseName, CancellationToken token);
|
Task RenameDatabase(string connectionString, string databaseName, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Создание БД
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connectionString"></param>
|
/// <param name="connectionString"></param>
|
||||||
/// <param name="databaseName"></param>
|
/// <param name="databaseName"></param>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
namespace Persistence.Services;
|
namespace Persistence.Services;
|
||||||
|
|
||||||
public interface ITimeSeriesDataObserverService
|
public interface ITimeSeriesDataObserverService
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user