Compare commits
	
		
			4 Commits
		
	
	
		
			main
			...
			dev-sergio
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 169c6409dc | |||
|   | 10f2083590 | ||
|   | ca35645488 | ||
|   | f89dd755b1 | 
| @@ -12,26 +12,26 @@ namespace Core.Blueprint.DAL.API.Controllers | |||||||
|     [Produces("application/json")] |     [Produces("application/json")] | ||||||
|     [ApiController] |     [ApiController] | ||||||
|     [AllowAnonymous] |     [AllowAnonymous] | ||||||
|     public class MongoBlueprintController(IBlueprintService service) : ControllerBase |     public class MongoSampleController(IMongoSampleService service) : ControllerBase | ||||||
|     { |     { | ||||||
|         [HttpPost("Create")] |         [HttpPost("Create")] | ||||||
|         public async Task<IActionResult> CreateBlueprint([FromBody] BlueprintRequest entity, CancellationToken cancellationToken) |         public async Task<IActionResult> CreateSample([FromBody] SampleRequest entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.CreateBlueprint(entity, cancellationToken).ConfigureAwait(false); |             var result = await service.CreateSample(entity, cancellationToken).ConfigureAwait(false); | ||||||
|             return Created("CreatedWithIdAsync", result); |             return Created("CreatedWithIdAsync", result); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpGet("GetAll")] |         [HttpGet("GetAll")] | ||||||
|         public async Task<IActionResult> GetEntities(CancellationToken cancellationToken) |         public async Task<IActionResult> GetEntities(CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.GetAllBlueprints(cancellationToken).ConfigureAwait(false); |             var result = await service.GetAllSamples(cancellationToken).ConfigureAwait(false); | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpGet("{_id}/GetBy_Id")] |         [HttpGet("{_id}/GetBy_Id")] | ||||||
|         public async Task<IActionResult> GetBlueprint([FromRoute] string _id, CancellationToken cancellationToken) |         public async Task<IActionResult> GetSample([FromRoute] string _id, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.GetBlueprintById(_id, cancellationToken).ConfigureAwait(false); |             var result = await service.GetSampleById(_id, cancellationToken).ConfigureAwait(false); | ||||||
| 
 | 
 | ||||||
|             if (result == null) |             if (result == null) | ||||||
|             { |             { | ||||||
| @@ -42,22 +42,22 @@ namespace Core.Blueprint.DAL.API.Controllers | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpPut("{_id}/Update")] |         [HttpPut("{_id}/Update")] | ||||||
|         public async Task<IActionResult> UpdateBlueprint([FromRoute] string _id, [FromBody] BlueprintCollection entity, CancellationToken cancellationToken) |         public async Task<IActionResult> UpdateSample([FromRoute] string _id, [FromBody] SampleCollection entity, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             if (_id != entity._Id?.ToString()) |             if (_id != entity._Id?.ToString()) | ||||||
|             { |             { | ||||||
|                 return BadRequest("Blueprint ID mismatch"); |                 return BadRequest("Sample ID mismatch"); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var result = await service.UpdateBlueprint(_id, entity, cancellationToken).ConfigureAwait(false); |             var result = await service.UpdateSample(_id, entity, cancellationToken).ConfigureAwait(false); | ||||||
| 
 | 
 | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpDelete("{_id}/Delete")] |         [HttpDelete("{_id}/Delete")] | ||||||
|         public async Task<IActionResult> DeleteBlueprint([FromRoute] string _id, CancellationToken cancellationToken) |         public async Task<IActionResult> DeleteSample([FromRoute] string _id, CancellationToken cancellationToken) | ||||||
|         { |         { | ||||||
|             var result = await service.DeleteBlueprint(_id, cancellationToken).ConfigureAwait(false); |             var result = await service.DeleteSample(_id, cancellationToken).ConfigureAwait(false); | ||||||
| 
 | 
 | ||||||
|             if (result is null) return NotFound(); |             if (result is null) return NotFound(); | ||||||
| 
 | 
 | ||||||
| @@ -12,48 +12,48 @@ namespace Core.Blueprint.DAL.API.Controllers | |||||||
|     [Produces("application/json")] |     [Produces("application/json")] | ||||||
|     [ApiController] |     [ApiController] | ||||||
|     [AllowAnonymous] |     [AllowAnonymous] | ||||||
|     public class UserProjectController(IUserProjectService service) : ControllerBase |     public class SqlSampleController(ISqlSampleService service) : ControllerBase | ||||||
|     { |     { | ||||||
|         [HttpPost("Create")] |         [HttpPost("Create")] | ||||||
|         public async Task<ActionResult<UserProject>> CreateEntity([FromBody] UserProjectRequest request) |         public async Task<ActionResult<Sample>> CreateEntity([FromBody] SampleRequest request) | ||||||
|         { |         { | ||||||
|             var result = await service.AddUserProject(request).ConfigureAwait(false); |             var result = await service.AddSample(request).ConfigureAwait(false); | ||||||
|             return Created("CreatedWithIdAsync", result); |             return Created("CreatedWithIdAsync", result); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpGet("GetAll")] |         [HttpGet("GetAll")] | ||||||
|         public async Task<ActionResult<IEnumerable<UserProject>>> GetEntities() |         public async Task<ActionResult<IEnumerable<Sample>>> GetEntities() | ||||||
|         { |         { | ||||||
|             var result = await service.GetAllUserProjects().ConfigureAwait(false); |             var result = await service.GetAllSamples().ConfigureAwait(false); | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpGet("{id}/GetById")] |         [HttpGet("{id}/GetById")] | ||||||
|         public async Task<ActionResult<UserProject>> GetEntity(int id) |         public async Task<ActionResult<Sample>> GetEntity(int id) | ||||||
|         { |         { | ||||||
|             var result = await service.GetUserProjectById(id).ConfigureAwait(false); |             var result = await service.GetSampleById(id).ConfigureAwait(false); | ||||||
| 
 | 
 | ||||||
|             if (result is null) return NotFound("User Project not found"); |             if (result is null) return NotFound("sample not found"); | ||||||
| 
 | 
 | ||||||
|             return Ok(result); |             return Ok(result); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpPut("{id}/Update")] |         [HttpPut("{id}/Update")] | ||||||
|         public async Task<ActionResult<UserProject>> UpdateEntity(int id, UserProject entity) |         public async Task<ActionResult<Sample>> UpdateEntity(int id, Sample entity) | ||||||
|         { |         { | ||||||
|             if (id != entity.Id) |             if (id != entity.Id) | ||||||
|             { |             { | ||||||
|                 return BadRequest("ID mismatch"); |                 return BadRequest("ID mismatch"); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             var result = await service.UpdateUserProject(entity).ConfigureAwait(false); |             var result = await service.UpdateSample(entity).ConfigureAwait(false); | ||||||
|             return Ok(entity); |             return Ok(entity); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [HttpDelete("{id}/Delete")] |         [HttpDelete("{id}/Delete")] | ||||||
|         public async Task<IActionResult> DeleteEntity(int id) |         public async Task<IActionResult> DeleteEntity(int id) | ||||||
|         { |         { | ||||||
|             var result = await service.DeleteUserProject(id).ConfigureAwait(false); |             var result = await service.DeleteSample(id).ConfigureAwait(false); | ||||||
| 
 | 
 | ||||||
|             if (result is null) return NotFound(); |             if (result is null) return NotFound(); | ||||||
| 
 | 
 | ||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" /> |     <PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" /> | ||||||
|     <PackageReference Include="Core.Blueprint.Logging" Version="0.3.0-alpha0034" /> |     <PackageReference Include="Blueprint.Logging" Version="0.0.2" /> | ||||||
|     <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" /> |     <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" /> | ||||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0" /> |     <PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0" /> | ||||||
|     <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" /> |     <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" /> | ||||||
|   | |||||||
| @@ -17,12 +17,12 @@ namespace Core.Blueprint.DAL.API.Extensions | |||||||
|         public static IServiceCollection AddDALLayerServices(this IServiceCollection services, IConfiguration configuration) |         public static IServiceCollection AddDALLayerServices(this IServiceCollection services, IConfiguration configuration) | ||||||
|         { |         { | ||||||
|             //Mongo |             //Mongo | ||||||
|             services.AddScoped<IBlueprintService, BlueprintService>(); |             services.AddScoped<IMongoSampleService, MongoSampleService>(); | ||||||
|             services.AddScoped<CollectionRepository<BlueprintCollection>>(); |             services.AddScoped<CollectionRepository<SampleCollection>>(); | ||||||
|  |  | ||||||
|             //SQL |             //SQL | ||||||
|             services.AddDbContext<SqlServerContext>(options => options.UseSqlServer(configuration.GetConnectionString("SQLServer"))); |             services.AddDbContext<SqlServerContext>(options => options.UseSqlServer(configuration.GetConnectionString("SQLServer"))); | ||||||
|             services.AddScoped<IUserProjectService, UserProjectService>(); |             services.AddScoped<ISqlSampleService, SqlSampleService>(); | ||||||
|  |  | ||||||
|             //Storage |             //Storage | ||||||
|             services.AddScoped<IBlobStorageService, BlobStorageService>(); |             services.AddScoped<IBlobStorageService, BlobStorageService>(); | ||||||
|   | |||||||
| @@ -13,21 +13,21 @@ using System.Text.Json.Serialization; | |||||||
|  |  | ||||||
| var builder = WebApplication.CreateBuilder(args); | var builder = WebApplication.CreateBuilder(args); | ||||||
|  |  | ||||||
| builder.Configuration.AddAzureAppConfiguration(options => | //builder.Configuration.AddAzureAppConfiguration(options => | ||||||
| { | //{ | ||||||
|     var endpoint = builder.Configuration.GetSection("Endpoints:AppConfigurationURI").Value; | //    var endpoint = builder.Configuration.GetSection("Endpoints:AppConfigurationURI").Value; | ||||||
|  |  | ||||||
|     if (string.IsNullOrEmpty(endpoint)) | //    if (string.IsNullOrEmpty(endpoint)) | ||||||
|         throw new ArgumentException("The app configuration is missing"); | //        throw new ArgumentException("The app configuration is missing"); | ||||||
|  |  | ||||||
|     options.Connect(new Uri(endpoint), new DefaultAzureCredential()) | //    options.Connect(new Uri(endpoint), new DefaultAzureCredential()) | ||||||
|     .Select(KeyFilter.Any, "blueprint_dal"); | //    .Select(KeyFilter.Any, "blueprint_dal"); | ||||||
|  |  | ||||||
|     options.ConfigureKeyVault(keyVaultOptions => | //    options.ConfigureKeyVault(keyVaultOptions => | ||||||
|     { | //    { | ||||||
|         keyVaultOptions.SetCredential(new DefaultAzureCredential()); | //        keyVaultOptions.SetCredential(new DefaultAzureCredential()); | ||||||
|     }); | //    }); | ||||||
| }); | //}); | ||||||
|  |  | ||||||
| builder.Services.AddEndpointsApiExplorer(); | builder.Services.AddEndpointsApiExplorer(); | ||||||
| builder.Services.AddSwaggerGen(); | builder.Services.AddSwaggerGen(); | ||||||
| @@ -40,10 +40,10 @@ builder.Services.AddProblemDetails(); | |||||||
| builder.Services.AddMemoryCache(); | builder.Services.AddMemoryCache(); | ||||||
| builder.Services.AddLogs(builder); | builder.Services.AddLogs(builder); | ||||||
| builder.Services.AddKeyVault(builder.Configuration); | builder.Services.AddKeyVault(builder.Configuration); | ||||||
| builder.Services.AddBlobStorage(builder.Configuration); | //builder.Services.AddBlobStorage(builder.Configuration); | ||||||
| builder.Services.AddRedis(builder.Configuration); | //builder.Services.AddRedis(builder.Configuration); | ||||||
| builder.Services.AddMongoLayer(builder.Configuration); | //builder.Services.AddMongoLayer(builder.Configuration); | ||||||
| builder.Services.AddSQLServer(builder.Configuration); | //builder.Services.AddSQLServer(builder.Configuration); | ||||||
| builder.Services.AddDALLayerServices(builder.Configuration); | builder.Services.AddDALLayerServices(builder.Configuration); | ||||||
|  |  | ||||||
| builder.Host.ConfigureServices((context, services) => | builder.Host.ConfigureServices((context, services) => | ||||||
|   | |||||||
| @@ -7,5 +7,10 @@ | |||||||
|   }, |   }, | ||||||
|   "CacheSettings": { |   "CacheSettings": { | ||||||
|     "DefaultCacheDurationInMinutes": 3 |     "DefaultCacheDurationInMinutes": 3 | ||||||
|  |   }, | ||||||
|  |   "Vault": { | ||||||
|  |     "Address": "http://localhost:8200", | ||||||
|  |     "Token": "hvs.kDZnAfrvfcMNrom6RmlEhZ7I", | ||||||
|  |     "SecretMount": "secret" | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -7,11 +7,7 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Azure.Identity" Version="1.13.1" /> |     <PackageReference Include="Blueprint.KeyVault" Version="0.0.3" /> | ||||||
|     <PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" /> |  | ||||||
|     <PackageReference Include="Core.Blueprint.KeyVault" Version="0.3.0-alpha0037" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -1,50 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.Logs.Contracts; |  | ||||||
| using Serilog; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Logs |  | ||||||
| { |  | ||||||
|     public class BlueprintSerilogLogger : IBlueprintSerilogLogger |  | ||||||
|     { |  | ||||||
|         private readonly ILogger logger; |  | ||||||
|  |  | ||||||
|         public BlueprintSerilogLogger(ILogger logger) |  | ||||||
|         { |  | ||||||
|             this.logger = logger; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void LogInformation(string service, params object[] args) |  | ||||||
|         { |  | ||||||
|             logger.Information("Starting operation in {service} service", service, args); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void LogOperationStarted(string service, params object[] args) |  | ||||||
|         { |  | ||||||
|             logger.Information("Starting operation in {Service} service with parameters: {@Args}", service, args); |  | ||||||
|         } |  | ||||||
|         public void LogOperationFinished(string service, params object[] args) |  | ||||||
|         { |  | ||||||
|             logger.Information("Finishing operation in {Service} service with parameters: {@Args}", service, args); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void LogInformation(string message) |  | ||||||
|         { |  | ||||||
|             logger.Information(message); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void LogWarning(string message, params object[] args) |  | ||||||
|         { |  | ||||||
|             logger.Warning(message, args); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void LogError(string service, params object[] args) |  | ||||||
|         { |  | ||||||
|             logger.Error("An error occurred in `{service}` Exception: {@Args}", service, args); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void LogCritical(Exception exception, string message, params object[] args) |  | ||||||
|         { |  | ||||||
|             logger.Fatal(exception, message, args); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @@ -1,15 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.Logs.Contracts; |  | ||||||
| using Microsoft.Extensions.DependencyInjection; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Logs.Configuration |  | ||||||
| { |  | ||||||
|     public static class LogExtensionConfiguration |  | ||||||
|     { |  | ||||||
|         public static IServiceCollection AddLogLayer(this IServiceCollection services) |  | ||||||
|         { |  | ||||||
|             services.AddScoped<IBlueprintSerilogLogger, BlueprintSerilogLogger>(); |  | ||||||
|  |  | ||||||
|             return services; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,9 +0,0 @@ | |||||||
| namespace Core.Blueprint.DAL.Logs.Contracts |  | ||||||
| { |  | ||||||
|     public interface IBlueprintLogger<T> where T : class, new() |  | ||||||
|     { |  | ||||||
|         //logger |  | ||||||
|         //serilog... |  | ||||||
|         //patterns of structuie logging |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,12 +0,0 @@ | |||||||
| namespace Core.Blueprint.DAL.Logs.Contracts |  | ||||||
| { |  | ||||||
|     public interface IBlueprintSerilogLogger |  | ||||||
|     { |  | ||||||
|         public void LogInformation(string service, params object[] args); |  | ||||||
|         public void LogOperationStarted(string service, params object[] args); |  | ||||||
|         public void LogOperationFinished(string service, params object[] args); |  | ||||||
|         public void LogWarning(string message, params object[] args); |  | ||||||
|         public void LogError(string servicee, params object[] args); |  | ||||||
|         public void LogCritical(Exception exception, string message, params object[] args); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| namespace Core.Blueprint.DAL.Logs; |  | ||||||
| public static partial class Log |  | ||||||
| { |  | ||||||
|     //[LoggerMessage( |  | ||||||
|     //    EventId = 1, |  | ||||||
|     //    Level = LogLevel.Information, |  | ||||||
|     //    Message = "Starting operation in`{service}` service with parameters: {@Args}" |  | ||||||
|     //)] |  | ||||||
|     //static partial void OperationStarted(ILogger logger, string service, params object[] args); |  | ||||||
|  |  | ||||||
|     //[LoggerMessage( |  | ||||||
|     //    EventId = 1, |  | ||||||
|     //    Level = LogLevel.Information, |  | ||||||
|     //    Message = "Operation finished in`{service}` service with parameters: {@Args}" |  | ||||||
|     //)] |  | ||||||
|     //static partial void OperationFinished(ILogger logger, string service, params object[] args); |  | ||||||
|  |  | ||||||
|     //[LoggerMessage( |  | ||||||
|     //    EventId = 2, |  | ||||||
|     //    Level = LogLevel.Error, |  | ||||||
|     //    Message = "An error occurred in `{service}` service" |  | ||||||
|     //)] |  | ||||||
|     //static partial void OperationFailed(ILogger logger, string service, Exception exception); |  | ||||||
| } |  | ||||||
| @@ -1,18 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.Mongo.Entities.Collections; |  | ||||||
| using Core.Blueprint.DAL.Mongo.Entities.Requests; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Mongo.Contracts |  | ||||||
| { |  | ||||||
|     public interface IBlueprintService |  | ||||||
|     { |  | ||||||
|         ValueTask<BlueprintCollection> CreateBlueprint(BlueprintRequest newBlueprint, CancellationToken cancellationToken); |  | ||||||
|  |  | ||||||
|         ValueTask<BlueprintCollection> GetBlueprintById(string _id, CancellationToken cancellationToken); |  | ||||||
|  |  | ||||||
|         ValueTask<IEnumerable<BlueprintCollection>> GetAllBlueprints(CancellationToken cancellationToken); |  | ||||||
|  |  | ||||||
|         ValueTask<BlueprintCollection> UpdateBlueprint(string _id, BlueprintCollection entity, CancellationToken cancellationToken); |  | ||||||
|  |  | ||||||
|         ValueTask<BlueprintCollection> DeleteBlueprint(string _id, CancellationToken cancellationToken); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										18
									
								
								Core.Blueprint.DAL.Mongo/Contracts/IMongoSampleService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Core.Blueprint.DAL.Mongo/Contracts/IMongoSampleService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | using Core.Blueprint.DAL.Mongo.Entities.Collections; | ||||||
|  | using Core.Blueprint.DAL.Mongo.Entities.Requests; | ||||||
|  |  | ||||||
|  | namespace Core.Blueprint.DAL.Mongo.Contracts | ||||||
|  | { | ||||||
|  |     public interface IMongoSampleService | ||||||
|  |     { | ||||||
|  |         ValueTask<SampleCollection> CreateSample(SampleRequest newSample, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|  |         ValueTask<SampleCollection> GetSampleById(string _id, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|  |         ValueTask<IEnumerable<SampleCollection>> GetAllSamples(CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|  |         ValueTask<SampleCollection> UpdateSample(string _id, SampleCollection entity, CancellationToken cancellationToken); | ||||||
|  |  | ||||||
|  |         ValueTask<SampleCollection> DeleteSample(string _id, CancellationToken cancellationToken); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -7,16 +7,9 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Azure.Identity" Version="1.13.1" /> |     <PackageReference Include="Blueprint.Mongo" Version="0.0.3" /> | ||||||
|     <PackageReference Include="Core.Blueprint.Mongo" Version="0.3.0-alpha0047" /> |     <PackageReference Include="Blueprint.Redis" Version="0.0.1" /> | ||||||
|     <PackageReference Include="Core.Blueprint.Redis" Version="0.3.0-alpha0032" /> |     <PackageReference Include="Mapster" Version="7.4.0" /> | ||||||
|     <PackageReference Include="Mapster" Version="7.4.1-pre01" /> |  | ||||||
|     <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="MongoDB.Driver" Version="3.1.0" /> |  | ||||||
|     <PackageReference Include="Serilog" Version="4.2.0" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -2,8 +2,8 @@ | |||||||
| 
 | 
 | ||||||
| namespace Core.Blueprint.DAL.Mongo.Entities.Collections | namespace Core.Blueprint.DAL.Mongo.Entities.Collections | ||||||
| { | { | ||||||
|     [CollectionAttributeName("Blueprints")] |     [CollectionAttributeName("Samples")] | ||||||
|     public class BlueprintCollection : Document |     public class SampleCollection : Document | ||||||
|     { |     { | ||||||
|         public string Name { get; set; } = null!; |         public string Name { get; set; } = null!; | ||||||
|         public string? Description { get; set; } |         public string? Description { get; set; } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| namespace Core.Blueprint.DAL.Mongo.Entities.Requests | namespace Core.Blueprint.DAL.Mongo.Entities.Requests | ||||||
| { | { | ||||||
|     public class BlueprintRequest |     public class SampleRequest | ||||||
|     { |     { | ||||||
|         public string Name { get; set; } = null!; |         public string Name { get; set; } = null!; | ||||||
| 
 | 
 | ||||||
| @@ -1,80 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.Mongo.Contracts; |  | ||||||
| using Core.Blueprint.DAL.Mongo.Entities.Collections; |  | ||||||
| using Core.Blueprint.DAL.Mongo.Entities.Requests; |  | ||||||
| using Core.Blueprint.Mongo; |  | ||||||
| using Core.Blueprint.Redis; |  | ||||||
| using Core.Blueprint.Redis.Helpers; |  | ||||||
| using Mapster; |  | ||||||
| using Microsoft.Extensions.Options; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Mongo.Service |  | ||||||
| { |  | ||||||
|     public class BlueprintService : IBlueprintService |  | ||||||
|     { |  | ||||||
|         private readonly CollectionRepository<BlueprintCollection> repository; |  | ||||||
|         private readonly CacheSettings cacheSettings; |  | ||||||
|         private readonly IRedisCacheProvider cacheProvider; |  | ||||||
|  |  | ||||||
|         public BlueprintService(CollectionRepository<BlueprintCollection> repository, |  | ||||||
|         IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings) |  | ||||||
|         { |  | ||||||
|             this.repository = repository; |  | ||||||
|             this.repository.CollectionInitialization(); |  | ||||||
|             this.cacheSettings = cacheSettings.Value; |  | ||||||
|             this.cacheProvider = cacheProvider; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async ValueTask<BlueprintCollection> CreateBlueprint(BlueprintRequest newBlueprint, CancellationToken cancellationToken) |  | ||||||
|         { |  | ||||||
|             var blueprintCollection = newBlueprint.Adapt<BlueprintCollection>(); |  | ||||||
|  |  | ||||||
|             await this.repository.InsertOneAsync(blueprintCollection); |  | ||||||
|  |  | ||||||
|             return blueprintCollection; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async ValueTask<BlueprintCollection> GetBlueprintById(string _id, CancellationToken cancellationToken) |  | ||||||
|         { |  | ||||||
|  |  | ||||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetBlueprintById", _id); |  | ||||||
|             var cachedData = await cacheProvider.GetAsync<BlueprintCollection>(cacheKey); |  | ||||||
|  |  | ||||||
|             if (cachedData is not null) { return cachedData; } |  | ||||||
|  |  | ||||||
|             var blueprint = await this.repository.FindByIdAsync(_id); |  | ||||||
|  |  | ||||||
|             await cacheProvider.SetAsync(cacheKey, blueprint); |  | ||||||
|  |  | ||||||
|             return blueprint; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async ValueTask<IEnumerable<BlueprintCollection>> GetAllBlueprints(CancellationToken cancellationToken) |  | ||||||
|         { |  | ||||||
|  |  | ||||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllBlueprints"); |  | ||||||
|             var cachedData = await cacheProvider.GetAsync<IEnumerable<BlueprintCollection>>(cacheKey) ?? []; |  | ||||||
|  |  | ||||||
|             if (cachedData.Any()) return cachedData; |  | ||||||
|  |  | ||||||
|             var blueprints = await this.repository.AsQueryable(); |  | ||||||
|  |  | ||||||
|             await cacheProvider.SetAsync(cacheKey, blueprints); |  | ||||||
|  |  | ||||||
|             return blueprints; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async ValueTask<BlueprintCollection> UpdateBlueprint(string _id, BlueprintCollection entity, CancellationToken cancellationToken) |  | ||||||
|         { |  | ||||||
|             await this.repository.ReplaceOneAsync(entity); |  | ||||||
|  |  | ||||||
|             return entity; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async ValueTask<BlueprintCollection> DeleteBlueprint(string _id, CancellationToken cancellationToken) |  | ||||||
|         { |  | ||||||
|             var entity = await this.repository.DeleteOneAsync(doc => doc._Id == _id); |  | ||||||
|  |  | ||||||
|             return entity; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										80
									
								
								Core.Blueprint.DAL.Mongo/Service/MongoSampleService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Core.Blueprint.DAL.Mongo/Service/MongoSampleService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | |||||||
|  | using Core.Blueprint.DAL.Mongo.Contracts; | ||||||
|  | using Core.Blueprint.DAL.Mongo.Entities.Collections; | ||||||
|  | using Core.Blueprint.DAL.Mongo.Entities.Requests; | ||||||
|  | using Core.Blueprint.Mongo; | ||||||
|  | using Core.Blueprint.Redis; | ||||||
|  | using Core.Blueprint.Redis.Helpers; | ||||||
|  | using Mapster; | ||||||
|  | using Microsoft.Extensions.Options; | ||||||
|  |  | ||||||
|  | namespace Core.Blueprint.DAL.Mongo.Service | ||||||
|  | { | ||||||
|  |     public class MongoSampleService : IMongoSampleService | ||||||
|  |     { | ||||||
|  |         private readonly CollectionRepository<SampleCollection> repository; | ||||||
|  |         private readonly CacheSettings cacheSettings; | ||||||
|  |         private readonly IRedisCacheProvider cacheProvider; | ||||||
|  |  | ||||||
|  |         public MongoSampleService(CollectionRepository<SampleCollection> repository, | ||||||
|  |         IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings) | ||||||
|  |         { | ||||||
|  |             this.repository = repository; | ||||||
|  |             this.repository.CollectionInitialization(); | ||||||
|  |             this.cacheSettings = cacheSettings.Value; | ||||||
|  |             this.cacheProvider = cacheProvider; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async ValueTask<SampleCollection> CreateSample(SampleRequest newSample, CancellationToken cancellationToken) | ||||||
|  |         { | ||||||
|  |             var sampleCollection = newSample.Adapt<SampleCollection>(); | ||||||
|  |  | ||||||
|  |             await this.repository.InsertOneAsync(sampleCollection); | ||||||
|  |  | ||||||
|  |             return sampleCollection; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async ValueTask<SampleCollection> GetSampleById(string _id, CancellationToken cancellationToken) | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetSampleById", _id); | ||||||
|  |             var cachedData = await cacheProvider.GetAsync<SampleCollection>(cacheKey); | ||||||
|  |  | ||||||
|  |             if (cachedData is not null) { return cachedData; } | ||||||
|  |  | ||||||
|  |             var sample = await this.repository.FindByIdAsync(_id); | ||||||
|  |  | ||||||
|  |             await cacheProvider.SetAsync(cacheKey, sample); | ||||||
|  |  | ||||||
|  |             return sample; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async ValueTask<IEnumerable<SampleCollection>> GetAllSamples(CancellationToken cancellationToken) | ||||||
|  |         { | ||||||
|  |  | ||||||
|  |             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllSamples"); | ||||||
|  |             var cachedData = await cacheProvider.GetAsync<IEnumerable<SampleCollection>>(cacheKey) ?? []; | ||||||
|  |  | ||||||
|  |             if (cachedData.Any()) return cachedData; | ||||||
|  |  | ||||||
|  |             var samples = await this.repository.AsQueryable(); | ||||||
|  |  | ||||||
|  |             await cacheProvider.SetAsync(cacheKey, samples); | ||||||
|  |  | ||||||
|  |             return samples; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async ValueTask<SampleCollection> UpdateSample(string _id, SampleCollection entity, CancellationToken cancellationToken) | ||||||
|  |         { | ||||||
|  |             await this.repository.ReplaceOneAsync(entity); | ||||||
|  |  | ||||||
|  |             return entity; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async ValueTask<SampleCollection> DeleteSample(string _id, CancellationToken cancellationToken) | ||||||
|  |         { | ||||||
|  |             var entity = await this.repository.DeleteOneAsync(doc => doc._Id == _id); | ||||||
|  |  | ||||||
|  |             return entity; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,134 +0,0 @@ | |||||||
| using Azure.Identity; |  | ||||||
| using Core.Blueprint.DAL.Redis.Contracts; |  | ||||||
| using Microsoft.Extensions.Logging; |  | ||||||
| using StackExchange.Redis; |  | ||||||
| using System.Text.Json; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Redis |  | ||||||
| { |  | ||||||
|     public class CacheService : ICacheService |  | ||||||
|     { |  | ||||||
|         private IDatabase _cacheDatabase = null!; |  | ||||||
|         private readonly ILogger<CacheService> _logger; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         public CacheService(string connectionString, ILogger<CacheService> logger) |  | ||||||
|         { |  | ||||||
|             _logger = logger; |  | ||||||
|             Task.Run(async () => |  | ||||||
|             { |  | ||||||
|                 _cacheDatabase = await GetRedisDatabase(connectionString); |  | ||||||
|             }).Wait(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private async Task<IDatabase> GetRedisDatabase(string connectionString) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 var configurationOptions = await ConfigurationOptions.Parse($"{connectionString}") |  | ||||||
|                     .ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); |  | ||||||
|  |  | ||||||
|                 configurationOptions.AbortOnConnectFail = false; |  | ||||||
|                 var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions); |  | ||||||
|  |  | ||||||
|                 _logger.LogInformation("Successfully connected to Redis."); |  | ||||||
|  |  | ||||||
|                 return connectionMultiplexer.GetDatabase(); |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 _logger.LogError(ex, "Error establishing Redis connection."); |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         public async Task<T> GetAsync<T>(string key) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 var value = await _cacheDatabase.StringGetAsync(key); |  | ||||||
|                 if (value.IsNullOrEmpty) |  | ||||||
|                 { |  | ||||||
|                     _logger.LogInformation($"Cache miss for key: {key}"); |  | ||||||
|                     return default; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 _logger.LogInformation($"Cache hit for key: {key}"); |  | ||||||
|                 return JsonSerializer.Deserialize<T>(value); |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 _logger.LogError(ex, $"Error getting cache item with key {key}"); |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 var json = JsonSerializer.Serialize(value); |  | ||||||
|                 await _cacheDatabase.StringSetAsync(key, json, expiry); |  | ||||||
|                 _logger.LogInformation($"Cache item set with key: {key}"); |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 _logger.LogError(ex, $"Error setting cache item with key {key}"); |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async Task RemoveAsync(string key) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 await _cacheDatabase.KeyDeleteAsync(key); |  | ||||||
|                 _logger.LogInformation($"Cache item removed with key: {key}"); |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 _logger.LogError(ex, $"Error removing cache item with key {key}"); |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async Task<bool> ExistsAsync(string key) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 var exists = await _cacheDatabase.KeyExistsAsync(key); |  | ||||||
|                 _logger.LogInformation($"Cache item exists check for key: {key} - {exists}"); |  | ||||||
|                 return exists; |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 _logger.LogError(ex, $"Error checking existence of cache item with key {key}"); |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async Task RefreshAsync(string key, TimeSpan? expiry = null) |  | ||||||
|         { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                 var value = await _cacheDatabase.StringGetAsync(key); |  | ||||||
|                 if (!value.IsNullOrEmpty) |  | ||||||
|                 { |  | ||||||
|                     await _cacheDatabase.StringSetAsync(key, value, expiry); |  | ||||||
|                     _logger.LogInformation($"Cache item refreshed with key: {key}"); |  | ||||||
|                 } |  | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     _logger.LogWarning($"Cache item with key: {key} does not exist, cannot refresh"); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             catch (Exception ex) |  | ||||||
|             { |  | ||||||
|                 _logger.LogError(ex, $"Error refreshing cache item with key {key}"); |  | ||||||
|                 throw; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,7 +0,0 @@ | |||||||
| namespace Core.Blueprint.DAL.Redis.Configuration |  | ||||||
| { |  | ||||||
|     public class CacheSettings |  | ||||||
|     { |  | ||||||
|         public int DefaultCacheDurationInMinutes { get; set; } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,27 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.Redis.Contracts; |  | ||||||
| using Microsoft.Extensions.Configuration; |  | ||||||
| using Microsoft.Extensions.DependencyInjection; |  | ||||||
| using Microsoft.Extensions.Logging; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Redis.Configuration |  | ||||||
| { |  | ||||||
|     public static class RedisExtension |  | ||||||
|     { |  | ||||||
|         public static IServiceCollection AddRedisLayer(this IServiceCollection services, IConfiguration configuration) |  | ||||||
|         { |  | ||||||
|             var source = configuration.GetSection("ConnectionStrings"); |  | ||||||
|  |  | ||||||
|             var redisConnectionString = source["Redis"]?.ToString(); |  | ||||||
|  |  | ||||||
|             if (string.IsNullOrEmpty(redisConnectionString)) |  | ||||||
|             { |  | ||||||
|                 throw new InvalidOperationException("Redis connection string is not configured."); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             services.AddSingleton<ICacheService>(provider => |  | ||||||
|                 new CacheService(redisConnectionString, provider.GetRequiredService<ILogger<CacheService>>())); |  | ||||||
|  |  | ||||||
|             return services; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| namespace Core.Blueprint.DAL.Redis.Contracts |  | ||||||
| { |  | ||||||
|     public interface ICacheService |  | ||||||
|     { |  | ||||||
|         Task<T> GetAsync<T>(string key); |  | ||||||
|         Task SetAsync<T>(string key, T value, TimeSpan? expiry = null); |  | ||||||
|         Task RemoveAsync(string key); |  | ||||||
|         Task<bool> ExistsAsync(string key); |  | ||||||
|         Task RefreshAsync(string key, TimeSpan? expiry = null); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -7,11 +7,7 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Azure.Identity" Version="1.13.1" /> |     <PackageReference Include="Blueprint.Redis" Version="0.0.1" /> | ||||||
|     <PackageReference Include="Microsoft.Azure.StackExchangeRedis" Version="3.2.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="StackExchange.Redis" Version="2.8.24" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -1,30 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.Redis.Configuration; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Redis.Helpers |  | ||||||
| { |  | ||||||
|     public static class CacheHelper |  | ||||||
|     { |  | ||||||
|         /// <summary> |  | ||||||
|         /// Determines the cache duration based on specific duration, settings, or a default value. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="specificCacheDuration">Specific cache duration in minutes, if provided.</param> |  | ||||||
|         /// <param name="cacheSettings">General cache settings containing default duration values.</param> |  | ||||||
|         /// <returns>The cache duration as a TimeSpan.</returns> |  | ||||||
|         public static TimeSpan GetCacheDuration(CacheSettings cacheSettings, int? specificCacheDuration = 0) |  | ||||||
|         { |  | ||||||
|             var defaultCacheDuration = TimeSpan.FromMinutes(.5); |  | ||||||
|  |  | ||||||
|             if (specificCacheDuration.HasValue && specificCacheDuration.Value > 0) |  | ||||||
|             { |  | ||||||
|                 return TimeSpan.FromMinutes(specificCacheDuration.Value); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (cacheSettings.DefaultCacheDurationInMinutes > 0) |  | ||||||
|             { |  | ||||||
|                 return TimeSpan.FromMinutes(cacheSettings.DefaultCacheDurationInMinutes); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return defaultCacheDuration; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,46 +0,0 @@ | |||||||
| using System.Text; |  | ||||||
| using System.Text.RegularExpressions; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.Redis.Helpers |  | ||||||
| { |  | ||||||
|     public static class CacheKeyHelper |  | ||||||
|     { |  | ||||||
|         public static string GenerateCacheKey(object instance, string methodName, params object[] parameters) |  | ||||||
|         { |  | ||||||
|             var className = instance.GetType().Name; |  | ||||||
|             var keyBuilder = new StringBuilder($"{className}.{methodName}"); |  | ||||||
|  |  | ||||||
|             foreach (var param in parameters) |  | ||||||
|             { |  | ||||||
|                 string normalizedParam = NormalizeParameter(param); |  | ||||||
|                 keyBuilder.Append($".{normalizedParam}"); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return keyBuilder.ToString(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private static string NormalizeParameter(object param) |  | ||||||
|         { |  | ||||||
|             if (param == null) |  | ||||||
|             { |  | ||||||
|                 return "null"; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             string paramString; |  | ||||||
|  |  | ||||||
|             if (param is DateTime dateTime) |  | ||||||
|             { |  | ||||||
|                 paramString = dateTime.ToString("yyyyMMdd"); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 paramString = param.ToString(); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // Replace special characters with an underscore |  | ||||||
|             string normalizedParam = Regex.Replace(paramString, @"[^a-zA-Z0-9]", "_"); |  | ||||||
|  |  | ||||||
|             return normalizedParam; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -7,7 +7,7 @@ namespace Core.Blueprint.DAL.SQLServer.Context | |||||||
|     public sealed class SqlServerContext : DbContext |     public sealed class SqlServerContext : DbContext | ||||||
|     { |     { | ||||||
|         public SqlServerContext(DbContextOptions<SqlServerContext> options) : base(options) { } |         public SqlServerContext(DbContextOptions<SqlServerContext> options) : base(options) { } | ||||||
|         public DbSet<UserProject> UserProjects { get; set; } |         public DbSet<Sample> UserProjects { get; set; } | ||||||
|  |  | ||||||
|         protected override void OnModelCreating(ModelBuilder modelBuilder) |         protected override void OnModelCreating(ModelBuilder modelBuilder) | ||||||
|         { |         { | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								Core.Blueprint.DAL.SQLServer/Contracts/ISqlSampleService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Core.Blueprint.DAL.SQLServer/Contracts/ISqlSampleService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | using Core.Blueprint.DAL.SQLServer.Entities; | ||||||
|  | using Core.Blueprint.DAL.SQLServer.Entities.Request; | ||||||
|  |  | ||||||
|  | namespace Core.Blueprint.DAL.SQLServer.Contracts | ||||||
|  | { | ||||||
|  |     public interface ISqlSampleService | ||||||
|  |     { | ||||||
|  |         Task<IEnumerable<Sample>> GetAllSamples(); | ||||||
|  |  | ||||||
|  |         Task<Sample?> GetSampleById(int id); | ||||||
|  |  | ||||||
|  |         Task<Sample> AddSample(SampleRequest newSample); | ||||||
|  |  | ||||||
|  |         Task<Sample?> UpdateSample(Sample sample); | ||||||
|  |  | ||||||
|  |         Task<Sample?> DeleteSample(int id); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.SQLServer.Entities; |  | ||||||
| using Core.Blueprint.DAL.SQLServer.Entities.Request; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.SQLServer.Contracts |  | ||||||
| { |  | ||||||
|     public interface IUserProjectService |  | ||||||
|     { |  | ||||||
|         Task<IEnumerable<UserProject>> GetAllUserProjects(); |  | ||||||
|  |  | ||||||
|         Task<UserProject?> GetUserProjectById(int id); |  | ||||||
|  |  | ||||||
|         Task<UserProject> AddUserProject(UserProjectRequest newUserProject); |  | ||||||
|  |  | ||||||
|         Task<UserProject?> UpdateUserProject(UserProject userProject); |  | ||||||
|  |  | ||||||
|         Task<UserProject?> DeleteUserProject(int id); |  | ||||||
|  |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -7,13 +7,9 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Core.Blueprint.Redis" Version="0.3.0-alpha0032" /> |     <PackageReference Include="Blueprint.Redis" Version="0.0.1" /> | ||||||
|     <PackageReference Include="Core.Blueprint.SQLServer" Version="0.3.0-alpha0030" /> |     <PackageReference Include="Blueprint.SQLServer" Version="0.0.1" /> | ||||||
|     <PackageReference Include="Mapster" Version="7.4.1-pre01" /> |     <PackageReference Include="Mapster" Version="7.4.1-pre01" /> | ||||||
|     <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | namespace Core.Blueprint.DAL.SQLServer.Entities.Request | ||||||
|  | { | ||||||
|  |     public class SampleRequest | ||||||
|  |     { | ||||||
|  |         public string Name { get; set; } = null!; | ||||||
|  |         public string Description { get; set; } = null!; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,9 +0,0 @@ | |||||||
| namespace Core.Blueprint.DAL.SQLServer.Entities.Request |  | ||||||
| { |  | ||||||
|     public class UserProjectRequest |  | ||||||
|     { |  | ||||||
|         public string ProjectCode { get; set; } = null!; |  | ||||||
|         public string ProjectDescription { get; set; } = null!; |  | ||||||
|         public string UserId { get; set; } = null!; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										12
									
								
								Core.Blueprint.DAL.SQLServer/Entities/Sample.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Core.Blueprint.DAL.SQLServer/Entities/Sample.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | using Core.Blueprint.SQLServer.Entities; | ||||||
|  | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  |  | ||||||
|  | namespace Core.Blueprint.DAL.SQLServer.Entities | ||||||
|  | { | ||||||
|  |     [Table("Samples")] | ||||||
|  |     public class Sample : BaseSQLAdapter | ||||||
|  |     { | ||||||
|  |         public string Name { get; set; } = null!; | ||||||
|  |         public string Description { get; set; } = null!; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| using Core.Blueprint.SQLServer.Entities; |  | ||||||
| using System.ComponentModel.DataAnnotations.Schema; |  | ||||||
|  |  | ||||||
| namespace Core.Blueprint.DAL.SQLServer.Entities |  | ||||||
| { |  | ||||||
|     [Table("UserProjects")] |  | ||||||
|     public class UserProject : BaseSQLAdapter |  | ||||||
|     { |  | ||||||
|         public string ProjectCode { get; set; } = null!; |  | ||||||
|         public string ProjectDescription { get; set; } = null!; |  | ||||||
|         public string UserId { get; set; } = null!; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										82
									
								
								Core.Blueprint.DAL.SQLServer/Services/SqlSampleService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								Core.Blueprint.DAL.SQLServer/Services/SqlSampleService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | using Core.Blueprint.DAL.SQLServer; | ||||||
|  | using Core.Blueprint.DAL.SQLServer.Context; | ||||||
|  | using Core.Blueprint.DAL.SQLServer.Contracts; | ||||||
|  | using Core.Blueprint.DAL.SQLServer.Entities; | ||||||
|  | using Core.Blueprint.DAL.SQLServer.Entities.Request; | ||||||
|  | using Core.Blueprint.Redis; | ||||||
|  | using Core.Blueprint.Redis.Helpers; | ||||||
|  | using Mapster; | ||||||
|  | using Microsoft.Extensions.Options; | ||||||
|  |  | ||||||
|  | public class SqlSampleService : ISqlSampleService | ||||||
|  | { | ||||||
|  |     private readonly IEntityRepository<Sample, SqlServerContext> _sqlSampleRepository; | ||||||
|  |     private readonly CacheSettings cacheSettings; | ||||||
|  |     private readonly IRedisCacheProvider cacheProvider; | ||||||
|  |  | ||||||
|  |     public SqlSampleService(IEntityRepository<Sample, SqlServerContext> sqlSampleRepository, IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings) | ||||||
|  |     { | ||||||
|  |         _sqlSampleRepository = sqlSampleRepository; | ||||||
|  |         this.cacheSettings = cacheSettings.Value; | ||||||
|  |         this.cacheProvider = cacheProvider; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<IEnumerable<Sample>> GetAllSamples() | ||||||
|  |     { | ||||||
|  |         var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllSamples"); | ||||||
|  |         var cachedData = await cacheProvider.GetAsync<IEnumerable<Sample>>(cacheKey) ?? []; | ||||||
|  |  | ||||||
|  |         if (cachedData.Any()) return cachedData; | ||||||
|  |  | ||||||
|  |         var samples = await _sqlSampleRepository.GetAllAsync(); | ||||||
|  |  | ||||||
|  |         await cacheProvider.SetAsync(cacheKey, samples); | ||||||
|  |  | ||||||
|  |         return samples; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<Sample?> GetSampleById(int id) | ||||||
|  |     { | ||||||
|  |         var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetSampleById", id); | ||||||
|  |         var cachedData = await cacheProvider.GetAsync<Sample>(cacheKey); | ||||||
|  |  | ||||||
|  |         if (cachedData is not null) { return cachedData; } | ||||||
|  |  | ||||||
|  |         var sample = await _sqlSampleRepository.GetByIdAsync(id); | ||||||
|  |  | ||||||
|  |         await cacheProvider.SetAsync(cacheKey, sample); | ||||||
|  |  | ||||||
|  |         return sample; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<Sample> AddSample(SampleRequest newSample) | ||||||
|  |     { | ||||||
|  |         var sample = newSample.Adapt<Sample>(); | ||||||
|  |  | ||||||
|  |         await _sqlSampleRepository.AddAsync(sample); | ||||||
|  |         await _sqlSampleRepository.SaveAsync(); | ||||||
|  |         return sample; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<Sample?> UpdateSample(Sample sample) | ||||||
|  |     { | ||||||
|  |         var existingEntity = await _sqlSampleRepository.GetByIdAsync(sample.Id); | ||||||
|  |  | ||||||
|  |         if (existingEntity is null) return existingEntity; | ||||||
|  |  | ||||||
|  |         _sqlSampleRepository.Update(sample); | ||||||
|  |         await _sqlSampleRepository.SaveAsync(); | ||||||
|  |         return sample; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<Sample?> DeleteSample(int id) | ||||||
|  |     { | ||||||
|  |         var sample = await _sqlSampleRepository.GetByIdAsync(id); | ||||||
|  |         if (sample == null) | ||||||
|  |             return null; | ||||||
|  |  | ||||||
|  |         _sqlSampleRepository.Delete(sample); | ||||||
|  |         await _sqlSampleRepository.SaveAsync(); | ||||||
|  |         return sample; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,82 +0,0 @@ | |||||||
| using Core.Blueprint.DAL.SQLServer; |  | ||||||
| using Core.Blueprint.DAL.SQLServer.Context; |  | ||||||
| using Core.Blueprint.DAL.SQLServer.Contracts; |  | ||||||
| using Core.Blueprint.DAL.SQLServer.Entities; |  | ||||||
| using Core.Blueprint.DAL.SQLServer.Entities.Request; |  | ||||||
| using Core.Blueprint.Redis; |  | ||||||
| using Core.Blueprint.Redis.Helpers; |  | ||||||
| using Mapster; |  | ||||||
| using Microsoft.Extensions.Options; |  | ||||||
|  |  | ||||||
| public class UserProjectService : IUserProjectService |  | ||||||
| { |  | ||||||
|     private readonly IEntityRepository<UserProject, SqlServerContext> _userProjectRepository; |  | ||||||
|     private readonly CacheSettings cacheSettings; |  | ||||||
|     private readonly IRedisCacheProvider cacheProvider; |  | ||||||
|  |  | ||||||
|     public UserProjectService(IEntityRepository<UserProject, SqlServerContext> userProjectRepository, IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings) |  | ||||||
|     { |  | ||||||
|         _userProjectRepository = userProjectRepository; |  | ||||||
|         this.cacheSettings = cacheSettings.Value; |  | ||||||
|         this.cacheProvider = cacheProvider; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public async Task<IEnumerable<UserProject>> GetAllUserProjects() |  | ||||||
|     { |  | ||||||
|         var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllUserProjects"); |  | ||||||
|         var cachedData = await cacheProvider.GetAsync<IEnumerable<UserProject>>(cacheKey) ?? []; |  | ||||||
|  |  | ||||||
|         if (cachedData.Any()) return cachedData; |  | ||||||
|  |  | ||||||
|         var userProjects = await _userProjectRepository.GetAllAsync(); |  | ||||||
|  |  | ||||||
|         await cacheProvider.SetAsync(cacheKey, userProjects); |  | ||||||
|  |  | ||||||
|         return userProjects; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public async Task<UserProject?> GetUserProjectById(int id) |  | ||||||
|     { |  | ||||||
|         var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserProjectById", id); |  | ||||||
|         var cachedData = await cacheProvider.GetAsync<UserProject>(cacheKey); |  | ||||||
|  |  | ||||||
|         if (cachedData is not null) { return cachedData; } |  | ||||||
|  |  | ||||||
|         var userProject = await _userProjectRepository.GetByIdAsync(id); |  | ||||||
|  |  | ||||||
|         await cacheProvider.SetAsync(cacheKey, userProject); |  | ||||||
|  |  | ||||||
|         return userProject; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public async Task<UserProject> AddUserProject(UserProjectRequest newUserProject) |  | ||||||
|     { |  | ||||||
|         var userProject = newUserProject.Adapt<UserProject>(); |  | ||||||
|  |  | ||||||
|         await _userProjectRepository.AddAsync(userProject); |  | ||||||
|         await _userProjectRepository.SaveAsync(); |  | ||||||
|         return userProject; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public async Task<UserProject?> UpdateUserProject(UserProject userProject) |  | ||||||
|     { |  | ||||||
|         var existingEntity = await _userProjectRepository.GetByIdAsync(userProject.Id); |  | ||||||
|  |  | ||||||
|         if (existingEntity is null) return existingEntity; |  | ||||||
|  |  | ||||||
|         _userProjectRepository.Update(userProject); |  | ||||||
|         await _userProjectRepository.SaveAsync(); |  | ||||||
|         return userProject; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public async Task<UserProject?> DeleteUserProject(int id) |  | ||||||
|     { |  | ||||||
|         var userProject = await _userProjectRepository.GetByIdAsync(id); |  | ||||||
|         if (userProject == null) |  | ||||||
|             return null; |  | ||||||
|  |  | ||||||
|         _userProjectRepository.Delete(userProject); |  | ||||||
|         await _userProjectRepository.SaveAsync(); |  | ||||||
|         return userProject; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -11,12 +11,7 @@ | |||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="Azure.Identity" Version="1.13.1" /> |     <PackageReference Include="Blueprint.Storage" Version="0.0.1" /> | ||||||
|     <PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" /> |  | ||||||
|     <PackageReference Include="Core.Blueprint.Storage" Version="0.3.0-alpha0049" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Azure" Version="1.9.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" /> |  | ||||||
|     <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
| </Project> | </Project> | ||||||
|   | |||||||
| @@ -13,8 +13,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.SQLServe | |||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Storage", "Core.Blueprint.DAL.Storage\Core.Blueprint.DAL.Storage.csproj", "{B744C1BC-7EDA-47C5-BC04-91D0FB061985}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Storage", "Core.Blueprint.DAL.Storage\Core.Blueprint.DAL.Storage.csproj", "{B744C1BC-7EDA-47C5-BC04-91D0FB061985}" | ||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Hangfire", "Core.Blueprint.DAL.Hangfire\Core.Blueprint.DAL.Hangfire.csproj", "{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}" |  | ||||||
| EndProject |  | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Mongo", "Core.Blueprint.DAL.Mongo\Core.Blueprint.DAL.Mongo.csproj", "{14F77CBD-952F-40F1-8568-A084EF7D2224}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Mongo", "Core.Blueprint.DAL.Mongo\Core.Blueprint.DAL.Mongo.csproj", "{14F77CBD-952F-40F1-8568-A084EF7D2224}" | ||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Redis", "Core.Blueprint.DAL.Redis\Core.Blueprint.DAL.Redis.csproj", "{CD655B60-8C94-494A-87BA-F689CDD65F2B}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Redis", "Core.Blueprint.DAL.Redis\Core.Blueprint.DAL.Redis.csproj", "{CD655B60-8C94-494A-87BA-F689CDD65F2B}" | ||||||
| @@ -41,10 +39,6 @@ Global | |||||||
| 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Debug|Any CPU.Build.0 = Debug|Any CPU | 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
| 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Release|Any CPU.ActiveCfg = Release|Any CPU | 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
| 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Release|Any CPU.Build.0 = Release|Any CPU | 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
| 		{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |  | ||||||
| 		{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU |  | ||||||
| 		{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU |  | ||||||
| 		{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Release|Any CPU.Build.0 = Release|Any CPU |  | ||||||
| 		{14F77CBD-952F-40F1-8568-A084EF7D2224}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | 		{14F77CBD-952F-40F1-8568-A084EF7D2224}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
| 		{14F77CBD-952F-40F1-8568-A084EF7D2224}.Debug|Any CPU.Build.0 = Debug|Any CPU | 		{14F77CBD-952F-40F1-8568-A084EF7D2224}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
| 		{14F77CBD-952F-40F1-8568-A084EF7D2224}.Release|Any CPU.ActiveCfg = Release|Any CPU | 		{14F77CBD-952F-40F1-8568-A084EF7D2224}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
| @@ -69,7 +63,6 @@ Global | |||||||
| 		{D66611EE-2AE0-48B2-8D79-AF10A5E11C91} = {0DD43B65-17E6-4AA2-BE35-F9C7FCB5DD18} | 		{D66611EE-2AE0-48B2-8D79-AF10A5E11C91} = {0DD43B65-17E6-4AA2-BE35-F9C7FCB5DD18} | ||||||
| 		{546B418A-2DBD-499D-B7AA-57078231B950} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | 		{546B418A-2DBD-499D-B7AA-57078231B950} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | ||||||
| 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | 		{B744C1BC-7EDA-47C5-BC04-91D0FB061985} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | ||||||
| 		{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} |  | ||||||
| 		{14F77CBD-952F-40F1-8568-A084EF7D2224} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | 		{14F77CBD-952F-40F1-8568-A084EF7D2224} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | ||||||
| 		{CD655B60-8C94-494A-87BA-F689CDD65F2B} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | 		{CD655B60-8C94-494A-87BA-F689CDD65F2B} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | ||||||
| 		{B91E1D72-FB2E-4532-83E9-3E9EF2231740} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | 		{B91E1D72-FB2E-4532-83E9-3E9EF2231740} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user