diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index e7dd9ce..7529477 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -25,4 +25,4 @@ jobs: - name: Build run: dotnet build src/SharpConnector/SharpConnector.csproj --no-restore - name: Test - run: dotnet test src/SharpConnector.Test/SharpConnector.Test.csproj --no-build --verbosity normal + run: dotnet test src/SharpConnector.Tests/SharpConnector.Tests.csproj --no-build --verbosity normal diff --git a/README.md b/README.md index 78cdcb1..763cba0 100755 --- a/README.md +++ b/README.md @@ -20,11 +20,9 @@ SharpConnector provides access to **CRUD** operations to NoSQL databases with ** * **EnyimMemcached** * **RavenDB** -other connectors and operations are under development. - ### How to use it -To use SharpConnector simply configure the *connectionString* to the desired connector and the *instance* type. -Add the *ConnectorConfig* node configuration within the *appsettings.json* file, here is the example for Redis connector: +To get started with SharpConnector, configure your *connectionString* and specify the connector *instance* type. +Then, add the ConnectorConfig node within your appsettings.json file. Here’s an example configuration for a Redis connector: ```json { @@ -36,13 +34,19 @@ Add the *ConnectorConfig* node configuration within the *appsettings.json* file, } ``` -and instantiate a new client specifying the type of data (for example string): +Once configured, create a new SharpConnector client, specifying the payload type (e.g., string): ```csharp SharpConnectorClient client = new SharpConnectorClient() ``` -SharpConnector works with any object that is serializable. +Alternatively, you can integrate SharpConnector client using dependency injection. Here’s how to register the SharpConnector service with a string payload type: + +```csharp +// Register the SharpConnector services with string payload type. +builder.Services.AddSharpConnectorServices(); +``` +This setup provides flexibility in working with different payload types and makes SharpConnector easy to use within dependency injection configurations. ### Contributing Thank you for considering to help out with the source code! diff --git a/src/SharpConnector.Api/Controllers/ConnectorController.cs b/src/SharpConnector.Api/Controllers/ConnectorController.cs new file mode 100644 index 0000000..ede9d74 --- /dev/null +++ b/src/SharpConnector.Api/Controllers/ConnectorController.cs @@ -0,0 +1,113 @@ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using Microsoft.AspNetCore.Mvc; +using SharpConnector.Interfaces; + +namespace SharpConnector.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class ConnectorController : ControllerBase + { + private readonly ISharpConnectorClient _connectorClient; + + private readonly ILogger _logger; + + public ConnectorController(ILogger logger, ISharpConnectorClient connectorClient) + { + _logger = logger; + _connectorClient = connectorClient; + } + + [HttpGet("{key}", Name = "Get")] + public ActionResult Get(string key) + { + var result = _connectorClient.Get(key); + return result != null ? Ok(result) : NotFound(); + } + + [HttpGet("async/{key}")] + public async Task> GetAsync(string key) + { + var result = await _connectorClient.GetAsync(key); + return result != null ? Ok(result) : NotFound(); + } + + [HttpGet("all")] + public ActionResult> GetAll() + { + var results = _connectorClient.GetAll(); + return Ok(results); + } + + [HttpPost("insert")] + public ActionResult Insert(string key, [FromBody] string value) + { + var success = _connectorClient.Insert(key, value); + return success ? Ok(success) : BadRequest("Insert failed."); + } + + [HttpPost("insert/with-expiration")] + public ActionResult Insert(string key, [FromBody] string value, TimeSpan expiration) + { + var success = _connectorClient.Insert(key, value, expiration); + return success ? Ok(success) : BadRequest("Insert with expiration failed."); + } + + [HttpPost("insert-async")] + public async Task> InsertAsync(string key, [FromBody] string value) + { + var success = await _connectorClient.InsertAsync(key, value); + return success ? Ok(success) : BadRequest("Async insert failed."); + } + + [HttpPost("insert-async/with-expiration")] + public async Task> InsertAsync(string key, [FromBody] string value, TimeSpan expiration) + { + var success = await _connectorClient.InsertAsync(key, value, expiration); + return success ? Ok(success) : BadRequest("Async insert with expiration failed."); + } + + [HttpPost("insert-many")] + public ActionResult InsertMany([FromBody] Dictionary values) + { + var success = _connectorClient.InsertMany(values); + return success ? Ok(success) : BadRequest("Insert many failed."); + } + + [HttpPost("insert-many/with-expiration")] + public ActionResult InsertMany([FromBody] Dictionary values, TimeSpan expiration) + { + var success = _connectorClient.InsertMany(values, expiration); + return success ? Ok(success) : BadRequest("Insert many with expiration failed."); + } + + [HttpDelete("{key}")] + public ActionResult Delete(string key) + { + var success = _connectorClient.Delete(key); + return success ? Ok(success) : NotFound("Delete failed."); + } + + [HttpDelete("async/{key}")] + public async Task> DeleteAsync(string key) + { + var success = await _connectorClient.DeleteAsync(key); + return success ? Ok(success) : NotFound("Async delete failed."); + } + + [HttpPut("{key}")] + public ActionResult Update(string key, [FromBody] string value) + { + var success = _connectorClient.Update(key, value); + return success ? Ok(success) : NotFound("Update failed."); + } + + [HttpPut("async/{key}")] + public async Task> UpdateAsync(string key, [FromBody] string value) + { + var success = await _connectorClient.UpdateAsync(key, value); + return success ? Ok(success) : NotFound("Async update failed."); + } + } +} diff --git a/src/SharpConnector.Api/Program.cs b/src/SharpConnector.Api/Program.cs new file mode 100644 index 0000000..2c00ead --- /dev/null +++ b/src/SharpConnector.Api/Program.cs @@ -0,0 +1,32 @@ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using SharpConnector.Middleware; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +// Register the SharpConnector services with string payload type. +builder.Services.AddSharpConnectorServices(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/src/SharpConnector.Api/Properties/launchSettings.json b/src/SharpConnector.Api/Properties/launchSettings.json new file mode 100644 index 0000000..8c0c20d --- /dev/null +++ b/src/SharpConnector.Api/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:44453", + "sslPort": 44308 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5124", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7158;http://localhost:5124", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/SharpConnector.Api/SharpConnector.Api.csproj b/src/SharpConnector.Api/SharpConnector.Api.csproj new file mode 100644 index 0000000..829839b --- /dev/null +++ b/src/SharpConnector.Api/SharpConnector.Api.csproj @@ -0,0 +1,44 @@ + + + + net8.0 + enable + enable + false + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + + diff --git a/src/SharpConnector.Api/SharpConnector.Api.http b/src/SharpConnector.Api/SharpConnector.Api.http new file mode 100644 index 0000000..add1736 --- /dev/null +++ b/src/SharpConnector.Api/SharpConnector.Api.http @@ -0,0 +1,6 @@ +@SharpConnector.Api_HostAddress = http://localhost:5124 + +GET {{SharpConnector.Api_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/src/SharpConnector.Api/appsettings.json b/src/SharpConnector.Api/appsettings.json new file mode 100644 index 0000000..4166de0 --- /dev/null +++ b/src/SharpConnector.Api/appsettings.json @@ -0,0 +1,14 @@ +{ + "ConnectorConfig": { + "Instance": "RavenDb", + "DatabaseName": "test", + "ConnectionString": "http://live-test.ravendb.net" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/SharpConnector.Test/appsettings.litedb.json b/src/SharpConnector.Api/appsettings.litedb.json old mode 100755 new mode 100644 similarity index 95% rename from src/SharpConnector.Test/appsettings.litedb.json rename to src/SharpConnector.Api/appsettings.litedb.json index 9e34922..4cbd392 --- a/src/SharpConnector.Test/appsettings.litedb.json +++ b/src/SharpConnector.Api/appsettings.litedb.json @@ -1,7 +1,7 @@ -{ - "ConnectorConfig": { - "Instance": "LiteDb", - "CollectionName": "test", - "ConnectionString": "LiteDbTest.db" - } +{ + "ConnectorConfig": { + "Instance": "LiteDb", + "CollectionName": "test", + "ConnectionString": "LiteDbTest.db" + } } \ No newline at end of file diff --git a/src/SharpConnector.Test/appsettings.memcached.json b/src/SharpConnector.Api/appsettings.memcached.json old mode 100755 new mode 100644 similarity index 95% rename from src/SharpConnector.Test/appsettings.memcached.json rename to src/SharpConnector.Api/appsettings.memcached.json index ad0113b..4b3b6d5 --- a/src/SharpConnector.Test/appsettings.memcached.json +++ b/src/SharpConnector.Api/appsettings.memcached.json @@ -1,6 +1,6 @@ -{ - "ConnectorConfig": { - "Instance": "Memcached", - "ConnectionString": "127.0.0.1:11211" - } +{ + "ConnectorConfig": { + "Instance": "Memcached", + "ConnectionString": "127.0.0.1:11211" + } } \ No newline at end of file diff --git a/src/SharpConnector.Test/appsettings.mongodb.json b/src/SharpConnector.Api/appsettings.mongodb.json old mode 100755 new mode 100644 similarity index 96% rename from src/SharpConnector.Test/appsettings.mongodb.json rename to src/SharpConnector.Api/appsettings.mongodb.json index b97bddf..6c11b28 --- a/src/SharpConnector.Test/appsettings.mongodb.json +++ b/src/SharpConnector.Api/appsettings.mongodb.json @@ -1,8 +1,8 @@ -{ - "ConnectorConfig": { - "Instance": "MongoDb", - "DatabaseName": "test", - "CollectionName": "test", - "ConnectionString": "mongodb_connectionstring_here" - } +{ + "ConnectorConfig": { + "Instance": "MongoDb", + "DatabaseName": "test", + "CollectionName": "test", + "ConnectionString": "mongodb_connectionstring_here" + } } \ No newline at end of file diff --git a/src/SharpConnector.Test/appsettings.ravendb.json b/src/SharpConnector.Api/appsettings.ravendb.json old mode 100755 new mode 100644 similarity index 95% rename from src/SharpConnector.Test/appsettings.ravendb.json rename to src/SharpConnector.Api/appsettings.ravendb.json index f80be05..8c5b88b --- a/src/SharpConnector.Test/appsettings.ravendb.json +++ b/src/SharpConnector.Api/appsettings.ravendb.json @@ -1,7 +1,7 @@ -{ - "ConnectorConfig": { - "Instance": "RavenDb", - "DatabaseName": "test", - "ConnectionString": "http://live-test.ravendb.net" - } +{ + "ConnectorConfig": { + "Instance": "RavenDb", + "DatabaseName": "test", + "ConnectionString": "http://live-test.ravendb.net" + } } \ No newline at end of file diff --git a/src/SharpConnector.Test/appsettings.redis.json b/src/SharpConnector.Api/appsettings.redis.json old mode 100755 new mode 100644 similarity index 95% rename from src/SharpConnector.Test/appsettings.redis.json rename to src/SharpConnector.Api/appsettings.redis.json index 3950348..ed660a5 --- a/src/SharpConnector.Test/appsettings.redis.json +++ b/src/SharpConnector.Api/appsettings.redis.json @@ -1,7 +1,7 @@ -{ - "ConnectorConfig": { - "Instance": "Redis", - "DatabaseNumber": 0, - "ConnectionString": "redis_connectionstring_here" - } +{ + "ConnectorConfig": { + "Instance": "Redis", + "DatabaseNumber": 0, + "ConnectionString": "redis_connectionstring_here" + } } \ No newline at end of file diff --git a/src/SharpConnector.Test/LiteDbTests.cs b/src/SharpConnector.Test/LiteDbTests.cs deleted file mode 100755 index 5daf46b..0000000 --- a/src/SharpConnector.Test/LiteDbTests.cs +++ /dev/null @@ -1,99 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SharpConnector.Interfaces; -using System.Collections.Generic; -using System.Linq; - -namespace SharpConnector.Test -{ - [TestClass] - public class LiteDbTests - { - private readonly ISharpConnectorClient _sharpConnectorClient; - - public LiteDbTests() - { - var builder = new ConfigurationBuilder() - .SetBasePath(System.IO.Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.litedb.json", optional: true, reloadOnChange: true); - - _sharpConnectorClient = new SharpConnectorClient(builder); - } - - [TestMethod] - public void Insert() - { - const string key = "testKey"; - var result = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(result); - } - - [TestMethod] - public void InsertMany() - { - var dictionary = new Dictionary() - { - { "key", "payload" }, - { "key2", "payload2" }, - { "key3", "payload3" } - }; - var result = _sharpConnectorClient.InsertMany(dictionary); - Assert.IsTrue(result); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= dictionary.Count); - } - - [TestMethod] - public void Get() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - } - - [TestMethod] - public void GetAll() - { - const string key = "testKey"; - const string otherkey = "testKey2"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - insert = _sharpConnectorClient.Insert(otherkey, "payload"); - Assert.IsTrue(insert); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= 2); - } - - [TestMethod] - public void Update() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var update = _sharpConnectorClient.Update(key, "modPayload"); - Assert.IsTrue(update); - obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "modPayload"); - } - - [TestMethod] - public void Delete() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var delete = _sharpConnectorClient.Delete(key); - Assert.IsTrue(delete); - obj = _sharpConnectorClient.Get(key); - Assert.IsNull(obj); - } - } -} diff --git a/src/SharpConnector.Test/MemcachedTests.cs b/src/SharpConnector.Test/MemcachedTests.cs deleted file mode 100755 index 3deec67..0000000 --- a/src/SharpConnector.Test/MemcachedTests.cs +++ /dev/null @@ -1,85 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SharpConnector.Interfaces; -using System.Collections.Generic; -using System.Linq; - -namespace SharpConnector.Test -{ - [TestClass] - public class MemcachedTests - { - private readonly ISharpConnectorClient _sharpConnectorClient; - - public MemcachedTests() - { - var builder = new ConfigurationBuilder() - .SetBasePath(System.IO.Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.memcached.json", optional: true, reloadOnChange: true); - - _sharpConnectorClient = new SharpConnectorClient(builder); - } - - [TestMethod] - public void Insert() - { - const string key = "testKey"; - var result = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(result); - } - - [TestMethod] - public void InsertMany() - { - var dictionary = new Dictionary() - { - { "key", "payload" }, - { "key2", "payload2" }, - { "key3", "payload3" } - }; - var result = _sharpConnectorClient.InsertMany(dictionary); - Assert.IsTrue(result); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= dictionary.Count); - } - - [TestMethod] - public void Get() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - } - - [TestMethod] - public void Update() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var update = _sharpConnectorClient.Update(key, "modPayload"); - Assert.IsTrue(update); - obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "modPayload"); - } - - [TestMethod] - public void Delete() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var delete = _sharpConnectorClient.Delete(key); - Assert.IsTrue(delete); - obj = _sharpConnectorClient.Get(key); - Assert.IsNull(obj); - } - } -} diff --git a/src/SharpConnector.Test/MongoDbTests.cs b/src/SharpConnector.Test/MongoDbTests.cs deleted file mode 100755 index 1fbcf6a..0000000 --- a/src/SharpConnector.Test/MongoDbTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -// (c) 2020 Francesco Del Re -// This code is licensed under MIT license (see LICENSE.txt for details) -using Microsoft.Extensions.Configuration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SharpConnector.Interfaces; -using System.Collections.Generic; -using System.Linq; - -namespace SharpConnector.Test -{ - [TestClass] - public class MongoDbTests - { - private readonly ISharpConnectorClient _sharpConnectorClient; - - public MongoDbTests() - { - var builder = new ConfigurationBuilder() - .SetBasePath(System.IO.Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.mongodb.json", optional: true, reloadOnChange: true); - - _sharpConnectorClient = new SharpConnectorClient(builder); - } - - [TestMethod] - public void Insert() - { - const string key = "testKey"; - var result = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(result); - } - - [TestMethod] - public void InsertMany() - { - var dictionary = new Dictionary() - { - { "key", "payload" }, - { "key2", "payload2" }, - { "key3", "payload3" } - }; - var result = _sharpConnectorClient.InsertMany(dictionary); - Assert.IsTrue(result); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= dictionary.Count); - } - - [TestMethod] - public void Get() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - } - - [TestMethod] - public void GetAll() - { - const string key = "testKey"; - const string otherkey = "testKey2"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - insert = _sharpConnectorClient.Insert(otherkey, "payload"); - Assert.IsTrue(insert); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= 2); - } - - [TestMethod] - public void Update() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var update = _sharpConnectorClient.Update(key, "modPayload"); - Assert.IsTrue(update); - obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "modPayload"); - } - - [TestMethod] - public void Delete() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var delete = _sharpConnectorClient.Delete(key); - Assert.IsTrue(delete); - obj = _sharpConnectorClient.Get(key); - Assert.IsNull(obj); - } - } -} diff --git a/src/SharpConnector.Test/RavenDbTests.cs b/src/SharpConnector.Test/RavenDbTests.cs deleted file mode 100755 index f3b7409..0000000 --- a/src/SharpConnector.Test/RavenDbTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -// (c) 2021 Francesco Del Re -// This code is licensed under MIT license (see LICENSE.txt for details) -using Microsoft.Extensions.Configuration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SharpConnector.Interfaces; -using System.Collections.Generic; -using System.Linq; - -namespace SharpConnector.Test -{ - [TestClass] - public class RavenDbTests - { - private readonly ISharpConnectorClient _sharpConnectorClient; - - public RavenDbTests() - { - var builder = new ConfigurationBuilder() - .SetBasePath(System.IO.Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.ravendb.json", optional: true, reloadOnChange: true); - - _sharpConnectorClient = new SharpConnectorClient(builder); - } - - [TestMethod] - public void Insert() - { - const string key = "testKey"; - var result = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(result); - } - - [TestMethod] - public void InsertMany() - { - var dictionary = new Dictionary() - { - { "key", "payload" }, - { "key2", "payload2" }, - { "key3", "payload3" } - }; - var result = _sharpConnectorClient.InsertMany(dictionary); - Assert.IsTrue(result); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= dictionary.Count); - } - - [TestMethod] - public void Get() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - } - - [TestMethod] - public void GetAll() - { - const string key = "testKey"; - const string otherkey = "testKey2"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - insert = _sharpConnectorClient.Insert(otherkey, "payload"); - Assert.IsTrue(insert); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= 2); - } - - [TestMethod] - public void Update() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var update = _sharpConnectorClient.Update(key, "modPayload"); - Assert.IsTrue(update); - obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "modPayload"); - } - - [TestMethod] - public void Delete() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var delete = _sharpConnectorClient.Delete(key); - Assert.IsTrue(delete); - obj = _sharpConnectorClient.Get(key); - Assert.IsNull(obj); - } - } -} diff --git a/src/SharpConnector.Test/RedisTests.cs b/src/SharpConnector.Tests/ConnectorTests.cs old mode 100755 new mode 100644 similarity index 69% rename from src/SharpConnector.Test/RedisTests.cs rename to src/SharpConnector.Tests/ConnectorTests.cs index cbb89bc..246196a --- a/src/SharpConnector.Test/RedisTests.cs +++ b/src/SharpConnector.Tests/ConnectorTests.cs @@ -1,149 +1,148 @@ -// (c) 2020 Francesco Del Re -// This code is licensed under MIT license (see LICENSE.txt for details) -using Microsoft.Extensions.Configuration; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SharpConnector.Interfaces; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace SharpConnector.Test -{ - [TestClass] - public class RedisTests - { - private readonly ISharpConnectorClient _sharpConnectorClient; - - public RedisTests() - { - var builder = new ConfigurationBuilder() - .SetBasePath(System.IO.Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.redis.json", optional: true, reloadOnChange: true); - - _sharpConnectorClient = new SharpConnectorClient(builder); - } - - [TestMethod] - public void Insert() - { - const string key = "testKey"; - var result = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(result); - } - - [TestMethod] - public async Task InsertAsync() - { - const string key = "testKey"; - var result = await _sharpConnectorClient.InsertAsync(key, "payload"); - Assert.IsTrue(result); - } - - [TestMethod] - public void InsertMany() - { - var dictionary = new Dictionary() - { - { "key", "payload" }, - { "key2", "payload2" }, - { "key3", "payload3" } - }; - var result = _sharpConnectorClient.InsertMany(dictionary); - Assert.IsTrue(result); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= dictionary.Count); - } - - [TestMethod] - public void Get() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - } - - [TestMethod] - public async Task GetAsync() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = await _sharpConnectorClient.GetAsync(key); - Assert.AreEqual(obj, "payload"); - } - - [TestMethod] - public void GetAll() - { - const string key = "testKey"; - const string otherkey = "testKey2"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - insert = _sharpConnectorClient.Insert(otherkey, "payload"); - Assert.IsTrue(insert); - var list = _sharpConnectorClient.GetAll(); - Assert.IsNotNull(list); - Assert.IsTrue(list.ToList().Count >= 2); - } - - [TestMethod] - public void Update() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var update = _sharpConnectorClient.Update(key, "modPayload"); - Assert.IsTrue(update); - obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "modPayload"); - } - - [TestMethod] - public async Task UpdateAsync() - { - const string key = "testKey"; - var insert = await _sharpConnectorClient.InsertAsync(key, "payload"); - Assert.IsTrue(insert); - var obj = await _sharpConnectorClient.GetAsync(key); - Assert.AreEqual(obj, "payload"); - var update = await _sharpConnectorClient.UpdateAsync(key, "modPayload"); - Assert.IsTrue(update); - obj = await _sharpConnectorClient.GetAsync(key); - Assert.AreEqual(obj, "modPayload"); - } - - [TestMethod] - public void Delete() - { - const string key = "testKey"; - var insert = _sharpConnectorClient.Insert(key, "payload"); - Assert.IsTrue(insert); - var obj = _sharpConnectorClient.Get(key); - Assert.AreEqual(obj, "payload"); - var delete = _sharpConnectorClient.Delete(key); - Assert.IsTrue(delete); - obj = _sharpConnectorClient.Get(key); - Assert.IsNull(obj); - } - - [TestMethod] - public async Task DeleteAsync() - { - const string key = "testKey"; - var insert = await _sharpConnectorClient.InsertAsync(key, "payload"); - Assert.IsTrue(insert); - var obj = await _sharpConnectorClient.GetAsync(key); - Assert.AreEqual(obj, "payload"); - var delete = await _sharpConnectorClient.DeleteAsync(key); - Assert.IsTrue(delete); - obj = await _sharpConnectorClient.GetAsync(key); - Assert.IsNull(obj); - } - - } -} +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SharpConnector.Interfaces; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace SharpConnector.Tests +{ + [TestClass] + public class ConnectorTests + { + private readonly ISharpConnectorClient _sharpConnectorClient; + private readonly Mock> _mockClient; + + public ConnectorTests() + { + _mockClient = new Mock>(); + + _mockClient.Setup(client => client.Insert(It.IsAny(), It.IsAny())) + .Returns(true); + + _mockClient.Setup(client => client.InsertAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(true); + + _mockClient.Setup(client => client.Get(It.IsAny())) + .Returns((string key) => key == "testKey" ? "payload" : null); + + _mockClient.Setup(client => client.GetAsync(It.IsAny())) + .ReturnsAsync((string key) => key == "testKey" ? "payload" : null); + + _sharpConnectorClient = _mockClient.Object; + } + + [TestMethod] + public void Insert() + { + const string key = "testKey"; + var result = _sharpConnectorClient.Insert(key, "payload"); + Assert.IsTrue(result); + } + + [TestMethod] + public async Task InsertAsync() + { + const string key = "testKey"; + var result = await _sharpConnectorClient.InsertAsync(key, "payload"); + Assert.IsTrue(result); + } + + [TestMethod] + public void InsertMany() + { + var dictionary = new Dictionary() + { + { "key", "payload" }, + { "key2", "payload2" }, + { "key3", "payload3" } + }; + + _mockClient.Setup(client => client.InsertMany(dictionary)).Returns(true); + + var result = _sharpConnectorClient.InsertMany(dictionary); + Assert.IsTrue(result); + } + + [TestMethod] + public void Get() + { + const string key = "testKey"; + var insert = _sharpConnectorClient.Insert(key, "payload"); + Assert.IsTrue(insert); + var obj = _sharpConnectorClient.Get(key); + Assert.AreEqual(obj, "payload"); + } + + [TestMethod] + public async Task GetAsync() + { + const string key = "testKey"; + var insert = _sharpConnectorClient.Insert(key, "payload"); + Assert.IsTrue(insert); + var obj = await _sharpConnectorClient.GetAsync(key); + Assert.AreEqual(obj, "payload"); + } + + [TestMethod] + public void Update() + { + const string key = "testKey"; + var insert = _sharpConnectorClient.Insert(key, "payload"); + Assert.IsTrue(insert); + var obj = _sharpConnectorClient.Get(key); + Assert.AreEqual(obj, "payload"); + + // Set up mock for update method + _mockClient.Setup(client => client.Update(key, "modPayload")).Returns(true); + var update = _sharpConnectorClient.Update(key, "modPayload"); + Assert.IsTrue(update); + } + + [TestMethod] + public async Task UpdateAsync() + { + const string key = "testKey"; + var insert = await _sharpConnectorClient.InsertAsync(key, "payload"); + Assert.IsTrue(insert); + var obj = await _sharpConnectorClient.GetAsync(key); + Assert.AreEqual(obj, "payload"); + + // Mock async update behavior + _mockClient.Setup(client => client.UpdateAsync(key, "modPayload")).ReturnsAsync(true); + var update = await _sharpConnectorClient.UpdateAsync(key, "modPayload"); + Assert.IsTrue(update); + } + + [TestMethod] + public void Delete() + { + const string key = "testKey"; + var insert = _sharpConnectorClient.Insert(key, "payload"); + Assert.IsTrue(insert); + var obj = _sharpConnectorClient.Get(key); + Assert.AreEqual(obj, "payload"); + + // Mock delete behavior + _mockClient.Setup(client => client.Delete(key)).Returns(true); + var delete = _sharpConnectorClient.Delete(key); + Assert.IsTrue(delete); + } + + [TestMethod] + public async Task DeleteAsync() + { + const string key = "testKey"; + var insert = await _sharpConnectorClient.InsertAsync(key, "payload"); + Assert.IsTrue(insert); + var obj = await _sharpConnectorClient.GetAsync(key); + Assert.AreEqual(obj, "payload"); + + // Mock async delete behavior + _mockClient.Setup(client => client.DeleteAsync(key)).ReturnsAsync(true); + var delete = await _sharpConnectorClient.DeleteAsync(key); + Assert.IsTrue(delete); + } + } +} diff --git a/src/SharpConnector.Tests/ConverterTests.cs b/src/SharpConnector.Tests/ConverterTests.cs new file mode 100644 index 0000000..d3e6780 --- /dev/null +++ b/src/SharpConnector.Tests/ConverterTests.cs @@ -0,0 +1,73 @@ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SharpConnector.Entities; +using SharpConnector.Utilities; +using System.Collections.Generic; +using System.Linq; + +namespace SharpConnector.Tests +{ + [TestClass] + public class ConverterTests + { + [TestMethod] + public void ToPayloadObject_ConnectorEntity_ReturnsCorrectObject() + { + // Arrange + var connectorEntity = new ConnectorEntity("testKey", "testPayload"); + + // Act + var result = connectorEntity.ToPayloadObject(); + + // Assert + Assert.AreEqual("testPayload", result); + } + + [TestMethod] + public void ToConnectorEntityList_ValidDictionary_ReturnsCorrectList() + { + // Arrange + var dictionary = new Dictionary + { + { "key1", "value1" }, + { "key2", "value2" }, + { "", "value3" }, // This should be ignored + { "key3", null } // This should be ignored + }; + + // Act + var result = dictionary.ToConnectorEntityList(); + + // Assert + Assert.AreEqual(2, result.Count); + Assert.AreEqual("key1", result[0].Key); + Assert.AreEqual("value1", result[0].Payload); + Assert.AreEqual("key2", result[1].Key); + Assert.AreEqual("value2", result[1].Payload); + } + + [TestMethod] + public void ToLiteDbConnectorEntityList_ValidDictionary_ReturnsCorrectList() + { + // Arrange + var dictionary = new Dictionary + { + { "key1", "value1" }, + { "key2", "value2" }, + { "", "value3" }, // This should be ignored + { "key3", null } // This should be ignored + }; + + // Act + var result = dictionary.ToLiteDbConnectorEntityList(); + + // Assert + Assert.AreEqual(2, result.Count); + Assert.AreEqual("key1", result[0].Key); + Assert.AreEqual("value1", result[0].Payload); + Assert.AreEqual("key2", result[1].Key); + Assert.AreEqual("value2", result[1].Payload); + } + } +} diff --git a/src/SharpConnector.Tests/SerializationExtensionsTests.cs b/src/SharpConnector.Tests/SerializationExtensionsTests.cs new file mode 100644 index 0000000..c68a6ac --- /dev/null +++ b/src/SharpConnector.Tests/SerializationExtensionsTests.cs @@ -0,0 +1,50 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SharpConnector.Utilities; + +namespace SharpConnector.Tests +{ + [TestClass] + public class SerializationExtensionsTests + { + [TestMethod] + public void IsSerializable_ReturnsTrue_ForSerializableObject() + { + // Arrange + var testObject = new SerializableTestClass { Name = "Test", Value = 42 }; + + // Act + var result = testObject.IsSerializable(); + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public void IsSerializable_ReturnsTrue_ForNullObject() + { + // Arrange + object testObject = null; + + // Act + var result = testObject.IsSerializable(); + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public void IsSerializable_ReturnsTrue_ForPrimitiveTypes() + { + // Act & Assert + Assert.IsTrue(42.IsSerializable()); + Assert.IsTrue("test".IsSerializable()); + Assert.IsTrue(true.IsSerializable()); + } + + private class SerializableTestClass + { + public string Name { get; set; } + public int Value { get; set; } + } + } +} \ No newline at end of file diff --git a/src/SharpConnector.Test/SharpConnector.Test.csproj b/src/SharpConnector.Tests/SharpConnector.Tests.csproj old mode 100755 new mode 100644 similarity index 73% rename from src/SharpConnector.Test/SharpConnector.Test.csproj rename to src/SharpConnector.Tests/SharpConnector.Tests.csproj index 58b57c8..e3ef612 --- a/src/SharpConnector.Test/SharpConnector.Test.csproj +++ b/src/SharpConnector.Tests/SharpConnector.Tests.csproj @@ -1,59 +1,51 @@ - - - - net8.0 - - false - - General purpose multiple connector to NoSQL database - - MIT - - SharpConnector - - Francesco Del Re - - Francesco Del Re - - https://github.com/engineering87/SharpConnector - - 2.0.0 - - 2.0.0.0 - - 2.0.0.0 - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - Always - - - Always - - - Always - - - Always - - - Always - - - - + + + + net8.0 + + false + + General purpose multiple connector to NoSQL database + + MIT + + SharpConnector + + Francesco Del Re + + Francesco Del Re + + https://github.com/engineering87/SharpConnector + + 2.0.0 + + 2.0.0.0 + + 2.0.0.0 + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + Always + + + Always + + + + diff --git a/src/SharpConnector/Connectors/LiteDb/LiteDbWrapper.cs b/src/SharpConnector/Connectors/LiteDb/LiteDbWrapper.cs index d9a1cec..f32b854 100755 --- a/src/SharpConnector/Connectors/LiteDb/LiteDbWrapper.cs +++ b/src/SharpConnector/Connectors/LiteDb/LiteDbWrapper.cs @@ -29,7 +29,9 @@ public LiteDbWrapper(LiteDbConfig liteDbConfig) /// public LiteDbConnectorEntity Get(string key) { - return _liteDbAccess.Collection.Find(Query.EQ("Key", new BsonValue(key))).FirstOrDefault(); + return _liteDbAccess.Collection + .Find(Query.EQ("Key", new BsonValue(key))) + .FirstOrDefault(); } /// @@ -40,7 +42,9 @@ public LiteDbConnectorEntity Get(string key) public Task GetAsync(string key) { // LiteDb library does not implement asynchronous operations - var entity = _liteDbAccess.Collection.Find(Query.EQ("Key", new BsonValue(key))).FirstOrDefault(); + var entity = _liteDbAccess.Collection + .Find(Query.EQ("Key", new BsonValue(key))) + .FirstOrDefault(); return Task.FromResult(entity); } @@ -53,6 +57,17 @@ public IEnumerable GetAll() return _liteDbAccess.Collection.Find(x=> true).ToList(); } + /// + /// Get all the values asynchronously. + /// + /// + public Task> GetAllAsync() + { + var entities = GetAll(); + return Task.FromResult(entities); + } + + /// /// Set the Key to hold the value. /// @@ -72,9 +87,8 @@ public bool Insert(LiteDbConnectorEntity connectorEntity) public Task InsertAsync(LiteDbConnectorEntity connectorEntity) { // LiteDb library does not implement asynchronous operations - Delete(connectorEntity.Key); - var insert = Insert(connectorEntity); - return Task.FromResult(insert); + var result = Insert(connectorEntity); + return Task.FromResult(result); } /// @@ -88,6 +102,17 @@ public bool InsertMany(List connectorEntities) return true; } + /// + /// Asynchronously inserts multiple ConnectorEntities. + /// + /// The list of ConnectorEntities to store. + /// True if all operations succeeded, false otherwise. + public Task InsertManyAsync(List connectorEntities) + { + InsertMany(connectorEntities); + return Task.FromResult(true); + } + /// /// Removes the specified Key. /// @@ -117,8 +142,7 @@ public Task DeleteAsync(string key) /// public bool Update(LiteDbConnectorEntity connectorEntity) { - // TODO switch to single access with UpdateMany - _liteDbAccess.Collection.DeleteMany(Query.EQ("Key", new BsonValue(connectorEntity.Key))); + Delete(connectorEntity.Key); return Insert(connectorEntity); } @@ -130,8 +154,8 @@ public bool Update(LiteDbConnectorEntity connectorEntity) public Task UpdateAsync(LiteDbConnectorEntity connectorEntity) { // LiteDb library does not implement asynchronous operations yet - var update = Update(connectorEntity); - return Task.FromResult(update); + var result = Update(connectorEntity); + return Task.FromResult(result); } } } diff --git a/src/SharpConnector/Connectors/Memcached/MemcachedWrapper.cs b/src/SharpConnector/Connectors/Memcached/MemcachedWrapper.cs index 7a07a06..ee1e098 100755 --- a/src/SharpConnector/Connectors/Memcached/MemcachedWrapper.cs +++ b/src/SharpConnector/Connectors/Memcached/MemcachedWrapper.cs @@ -1,7 +1,11 @@ -using Newtonsoft.Json; +// (c) 2021 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using Newtonsoft.Json; using SharpConnector.Configuration; using SharpConnector.Entities; +using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace SharpConnector.Connectors.Memcached @@ -40,6 +44,15 @@ public async Task GetAsync(string key) return result?.Value; } + /// + /// Get all ConnectorEntities asynchronously. + /// + /// A list of ConnectorEntities. + public async Task> GetAllAsync() + { + throw new NotSupportedException("This operation is not supported."); + } + /// /// Set the Key to hold the value. /// @@ -73,18 +86,19 @@ public Task InsertAsync(ConnectorEntity connectorEntity) /// public bool InsertMany(List connectorEntities) { - var result = true; - foreach (var entity in connectorEntities) - { - var seconds = entity.Expiration?.Seconds ?? 0; - var currentResult = _memcachedAccess.MemcachedClient.Add(entity.Key, - JsonConvert.SerializeObject(entity), - seconds); + return connectorEntities.All(Insert); + } - if (currentResult == false) - result = false; - } - return result; + /// + /// Asynchronously inserts multiple ConnectorEntities. + /// + /// The list of ConnectorEntities to store. + /// True if all operations succeeded, false otherwise. + public async Task InsertManyAsync(List connectorEntities) + { + var tasks = connectorEntities.Select(InsertAsync); + var results = await Task.WhenAll(tasks); + return results.All(r => r); } /// diff --git a/src/SharpConnector/Connectors/MongoDb/MongoDbWrapper.cs b/src/SharpConnector/Connectors/MongoDb/MongoDbWrapper.cs index 35276c1..e03063f 100755 --- a/src/SharpConnector/Connectors/MongoDb/MongoDbWrapper.cs +++ b/src/SharpConnector/Connectors/MongoDb/MongoDbWrapper.cs @@ -29,7 +29,9 @@ public MongoDbWrapper(MongoDbConfig mongoDbConfig) public ConnectorEntity Get(string key) { var filter = Builders.Filter.Eq("Key", key); - return _mongoDbAccess.Collection.Find(filter).FirstOrDefault(); + return _mongoDbAccess.Collection + .Find(filter) + .FirstOrDefault(); } /// @@ -50,7 +52,21 @@ public async Task GetAsync(string key) /// public List GetAll() { - return _mongoDbAccess.Collection.Find(x => true).ToList(); + return _mongoDbAccess.Collection + .Find(x => true) + .ToList(); + } + + /// + /// Asynchronously get all the values. + /// + /// + public async Task> GetAllAsync() + { + return await _mongoDbAccess.Collection + .Find(x => true) + .ToListAsync() + .ConfigureAwait(false); } /// @@ -60,8 +76,10 @@ public List GetAll() /// public bool Insert(ConnectorEntity connectorEntity) { - Delete(connectorEntity.Key); - _mongoDbAccess.Collection.InsertOne(connectorEntity); + var filter = Builders.Filter.Eq("Key", connectorEntity.Key); + var options = new ReplaceOptions { IsUpsert = true }; + _mongoDbAccess.Collection + .ReplaceOne(filter, connectorEntity, options); return true; } @@ -70,11 +88,14 @@ public bool Insert(ConnectorEntity connectorEntity) /// /// The ConnectorEntity to store. /// - public Task InsertAsync(ConnectorEntity connectorEntity) + public async Task InsertAsync(ConnectorEntity connectorEntity) { - DeleteAsync(connectorEntity.Key); - var insert = _mongoDbAccess.Collection.InsertOneAsync(connectorEntity); - return Task.FromResult(insert.IsCompletedSuccessfully); + var filter = Builders.Filter.Eq("Key", connectorEntity.Key); + var options = new ReplaceOptions { IsUpsert = true }; + await _mongoDbAccess.Collection + .ReplaceOneAsync(filter, connectorEntity, options) + .ConfigureAwait(false); + return true; } /// @@ -84,7 +105,23 @@ public Task InsertAsync(ConnectorEntity connectorEntity) /// public bool InsertMany(List connectorEntities) { - _mongoDbAccess.Collection.InsertMany(connectorEntities); + var options = new InsertManyOptions { IsOrdered = false }; + _mongoDbAccess.Collection + .InsertMany(connectorEntities, options); + return true; + } + + /// + /// Asynchronously inserts multiple ConnectorEntities. + /// + /// The list of ConnectorEntities to store. + /// A boolean indicating if the operation completed successfully. + public async Task InsertManyAsync(List connectorEntities) + { + var options = new InsertManyOptions { IsOrdered = false }; + await _mongoDbAccess.Collection + .InsertManyAsync(connectorEntities, options) + .ConfigureAwait(false); return true; } @@ -96,19 +133,22 @@ public bool InsertMany(List connectorEntities) public bool Delete(string key) { var filter = Builders.Filter.Eq("Key", key); - return _mongoDbAccess.Collection.DeleteOne(filter).IsAcknowledged; + return _mongoDbAccess.Collection + .DeleteOne(filter).IsAcknowledged; } /// - /// Removes the specified Key. + /// Asynchronously removes the specified Key. /// - /// The key of the object. - /// - public Task DeleteAsync(string key) + /// The key of the object to delete. + /// A boolean indicating if the deletion was acknowledged. + public async Task DeleteAsync(string key) { var filter = Builders.Filter.Eq("Key", key); - var delete = _mongoDbAccess.Collection.DeleteOneAsync(filter); - return Task.FromResult(delete.IsCompletedSuccessfully); + var result = await _mongoDbAccess.Collection + .DeleteOneAsync(filter) + .ConfigureAwait(false); + return result.IsAcknowledged && result.DeletedCount > 0; } /// @@ -120,19 +160,23 @@ public bool Update(ConnectorEntity connectorEntity) { var filter = Builders.Filter.Eq("Key", connectorEntity.Key); var update = Builders.Update.Set("Payload", connectorEntity.Payload); - return _mongoDbAccess.Collection.UpdateOne(filter, update).IsAcknowledged; + return _mongoDbAccess.Collection + .UpdateOne(filter, update).IsAcknowledged; } /// /// Updates the specified Key. /// /// The ConnectorEntity to store. - /// - public Task UpdateAsync(ConnectorEntity connectorEntity) + /// A boolean indicating if the update was acknowledged. + public async Task UpdateAsync(ConnectorEntity connectorEntity) { var filter = Builders.Filter.Eq("Key", connectorEntity.Key); var update = Builders.Update.Set("Payload", connectorEntity.Payload); - return Task.FromResult(_mongoDbAccess.Collection.UpdateOneAsync(filter, update).IsCompletedSuccessfully); + var result = await _mongoDbAccess.Collection + .UpdateOneAsync(filter, update) + .ConfigureAwait(false); + return result.IsAcknowledged && result.ModifiedCount > 0; } } } diff --git a/src/SharpConnector/Connectors/RavenDb/RavenDbWrapper.cs b/src/SharpConnector/Connectors/RavenDb/RavenDbWrapper.cs index 04b1ffd..d1adf43 100755 --- a/src/SharpConnector/Connectors/RavenDb/RavenDbWrapper.cs +++ b/src/SharpConnector/Connectors/RavenDb/RavenDbWrapper.cs @@ -1,5 +1,6 @@ // (c) 2021 Francesco Del Re // This code is licensed under MIT license (see LICENSE.txt for details) +using Raven.Client.Documents; using SharpConnector.Configuration; using SharpConnector.Entities; using System.Collections.Generic; @@ -57,6 +58,22 @@ public List GetAll() } } + /// + /// Get all values asynchronously. + /// + /// A task representing the asynchronous operation, containing a list of ConnectorEntities. + public async Task> GetAllAsync() + { + using (var session = _ravenDbAccess.Store.OpenAsyncSession()) + { + var entities = await session + .Query() + .Customize(cr => cr.WaitForNonStaleResults()) + .ToListAsync(); + return entities; + } + } + /// /// Set the Key to hold the value. /// @@ -105,6 +122,24 @@ public bool InsertMany(List connectorEntities) return true; } + /// + /// Asynchronously insert multiple ConnectorEntities. + /// + /// The ConnectorEntities to store. + /// A task representing the asynchronous operation. + public async Task InsertManyAsync(List connectorEntities) + { + using (var session = _ravenDbAccess.Store.OpenAsyncSession()) + { + foreach (var entity in connectorEntities) + { + await session.StoreAsync(entity, entity.Key); + } + await session.SaveChangesAsync(); + } + return true; + } + /// /// Removes the specified Key. /// @@ -145,6 +180,7 @@ public bool Update(ConnectorEntity connectorEntity) using (var session = _ravenDbAccess.Store.OpenSession()) { var entity = session.Load(connectorEntity.Key); + if (entity == null) return false; entity.Payload = connectorEntity.Payload; entity.Expiration = connectorEntity.Expiration; session.SaveChanges(); @@ -162,6 +198,7 @@ public async Task UpdateAsync(ConnectorEntity connectorEntity) using (var session = _ravenDbAccess.Store.OpenAsyncSession()) { var entity = await session.LoadAsync(connectorEntity.Key); + if (entity == null) return false; entity.Payload = connectorEntity.Payload; entity.Expiration = connectorEntity.Expiration; await session.SaveChangesAsync(); diff --git a/src/SharpConnector/Connectors/Redis/RedisWrapper.cs b/src/SharpConnector/Connectors/Redis/RedisWrapper.cs index a04e814..f88558c 100755 --- a/src/SharpConnector/Connectors/Redis/RedisWrapper.cs +++ b/src/SharpConnector/Connectors/Redis/RedisWrapper.cs @@ -1,13 +1,12 @@ // (c) 2020 Francesco Del Re // This code is licensed under MIT license (see LICENSE.txt for details) - using System.Collections.Generic; -using System.Linq; using Newtonsoft.Json; using SharpConnector.Configuration; using SharpConnector.Entities; using StackExchange.Redis; using System.Threading.Tasks; +using System.Linq; namespace SharpConnector.Connectors.Redis { @@ -46,10 +45,15 @@ public ConnectorEntity Get(string key, int databaseNumber = 0) public async Task GetAsync(string key, int databaseNumber = 0) { var database = _redisAccess.GetConnection().GetDatabase(databaseNumber); - var value = await database.StringGetAsync(key); + var value = await database.StringGetAsync(key).ConfigureAwait(false); return value.HasValue ? JsonConvert.DeserializeObject(value) : default; } + /// + /// Get all values from Redis database. + /// + /// The Redis database. + /// /// /// Get all values from Redis database. /// @@ -61,24 +65,53 @@ public IEnumerable GetAll(int databaseNumber = 0) var connection = _redisAccess.GetConnection(); var database = connection.GetDatabase(databaseNumber); var endpoints = connection.GetEndPoints(true); + foreach (var endpoint in endpoints) { var server = connection.GetServer(endpoint); var keys = server.Keys(databaseNumber); - //result.AddRange(keys.Select( - // key => new ConnectorEntity(key, database.StringGet(key))) - //); - - foreach(var redisKey in keys) + foreach (var redisKey in keys) { var value = database.StringGet(redisKey); - result.Add(JsonConvert.DeserializeObject(value)); + if (!value.IsNull) + { + result.Add(JsonConvert.DeserializeObject(value)); + } } } return result; } + /// + /// Asynchronously get all values from Redis database. + /// + /// The Redis database. + /// A task that represents the asynchronous operation, containing a list of all ConnectorEntity instances in the specified database. + public async Task> GetAllAsync(int databaseNumber = 0) + { + var result = new List(); + var connection = _redisAccess.GetConnection(); + var database = connection.GetDatabase(databaseNumber); + var endpoints = connection.GetEndPoints(true); + + foreach (var endpoint in endpoints) + { + var server = connection.GetServer(endpoint); + var keys = server.Keys(databaseNumber); + + var tasks = keys.Select(async redisKey => + { + var value = await database.StringGetAsync(redisKey); + return !value.IsNull ? JsonConvert.DeserializeObject(value) : null; + }); + + var entities = await Task.WhenAll(tasks); + result.AddRange(entities.Where(e => e != null)); + } + return result; + } + /// /// Set the Key to hold the value. /// @@ -95,7 +128,7 @@ public bool Insert(ConnectorEntity connectorEntity, int databaseNumber = 0) } /// - /// Set the Key to hold the value. + /// Asynchronously sets the Key to hold the value. /// /// The ConnectorEntity to store. /// The Redis database. @@ -104,9 +137,25 @@ public async Task InsertAsync(ConnectorEntity connectorEntity, int databas { var database = _redisAccess.GetConnection().GetDatabase(databaseNumber); return await database.StringSetAsync( - connectorEntity.Key, + connectorEntity.Key, JsonConvert.SerializeObject(connectorEntity), - connectorEntity.Expiration); + connectorEntity.Expiration).ConfigureAwait(false); + } + + /// + /// Set the Key to hold the value. + /// + /// The ConnectorEntity to store. + /// The Redis database. + /// + public async Task InsertManyAsync(List connectorEntities, int databaseNumber = 0) + { + var database = _redisAccess.GetConnection().GetDatabase(databaseNumber); + var tasks = connectorEntities.Select(entity => + database.StringSetAsync(entity.Key, JsonConvert.SerializeObject(entity), entity.Expiration)); + + var results = await Task.WhenAll(tasks).ConfigureAwait(false); + return results.All(result => result); } /// @@ -161,23 +210,19 @@ public async Task DeleteAsync(string key, int databaseNumber = 0) /// /// Updates the specified Key. /// - /// The ConnectorEntity to store. + /// The ConnectorEntity to update. /// The Redis database. /// - public bool Update(ConnectorEntity connectorEntity, int databaseNumber = 0) - { - return Insert(connectorEntity, databaseNumber); - } + public bool Update(ConnectorEntity connectorEntity, int databaseNumber = 0) => + Insert(connectorEntity, databaseNumber); /// - /// Updates the specified Key. + /// Asynchronously updates the specified Key. /// - /// The ConnectorEntity to store. + /// The ConnectorEntity to update. /// The Redis database. /// - public async Task UpdateAsync(ConnectorEntity connectorEntity, int databaseNumber = 0) - { - return await InsertAsync(connectorEntity, databaseNumber); - } + public Task UpdateAsync(ConnectorEntity connectorEntity, int databaseNumber = 0) => + InsertAsync(connectorEntity, databaseNumber); } } diff --git a/src/SharpConnector/Entities/ConnectorEntity.cs b/src/SharpConnector/Entities/ConnectorEntity.cs index 0a086f6..ea517ea 100755 --- a/src/SharpConnector/Entities/ConnectorEntity.cs +++ b/src/SharpConnector/Entities/ConnectorEntity.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json; using System; using MongoDB.Bson.Serialization.Attributes; +using SharpConnector.Utilities; namespace SharpConnector.Entities { @@ -33,8 +34,7 @@ public ConnectorEntity(string key, object payload, TimeSpan? expiration) if (string.IsNullOrEmpty(key) || payload == null) throw new ArgumentException("Key or Payload cannot be null"); - var type = payload.GetType(); - if (type.IsSerializable) + if (payload.IsSerializable()) { Key = key; Payload = payload; @@ -56,8 +56,7 @@ public ConnectorEntity(string key, object payload) if (string.IsNullOrEmpty(key) || payload == null) throw new ArgumentException("Key or Payload cannot be null"); - var type = payload.GetType(); - if (type.IsSerializable) + if (payload.IsSerializable()) { Key = key; Payload = payload; @@ -76,7 +75,7 @@ public ConnectorEntity(string key, object payload) /// public override bool Equals(object obj) { - if (!(obj is ConnectorEntity p)) + if (obj is not ConnectorEntity p) return false; return Payload.GetHashCode() == p.GetHashCode(); diff --git a/src/SharpConnector/Interfaces/IConnectorConfig.cs b/src/SharpConnector/Interfaces/IConnectorConfig.cs index 9580ab4..6776934 100755 --- a/src/SharpConnector/Interfaces/IConnectorConfig.cs +++ b/src/SharpConnector/Interfaces/IConnectorConfig.cs @@ -1,15 +1,15 @@ -// (c) 2020 Francesco Del Re -// This code is licensed under MIT license (see LICENSE.txt for details) -namespace SharpConnector.Interfaces -{ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +namespace SharpConnector.Interfaces +{ /// /// Configuration interface. - /// - public interface IConnectorConfig - { - int DatabaseNumber { get; } - string ConnectionString { get; } - string DatabaseName { get; } - string CollectionName { get; } - } -} + /// + public interface IConnectorConfig + { + int DatabaseNumber { get; } + string ConnectionString { get; } + string DatabaseName { get; } + string CollectionName { get; } + } +} diff --git a/src/SharpConnector/Interfaces/IOperations.cs b/src/SharpConnector/Interfaces/IOperations.cs index b448dcb..dac5fcf 100755 --- a/src/SharpConnector/Interfaces/IOperations.cs +++ b/src/SharpConnector/Interfaces/IOperations.cs @@ -15,12 +15,14 @@ public interface IOperations T Get(string key); Task GetAsync(string key); IEnumerable GetAll(); + Task> GetAllAsync(); bool Insert(string key, T value); bool Insert(string key, T value, TimeSpan expiration); Task InsertAsync(string key, T value); Task InsertAsync(string key, T value, TimeSpan expiration); bool InsertMany(Dictionary values); bool InsertMany(Dictionary values, TimeSpan expiration); + Task InsertManyAsync(IEnumerable values); bool Delete(string key); Task DeleteAsync(string key); bool Update(string key, T value); diff --git a/src/SharpConnector/Interfaces/ISharpConnectorClient.cs b/src/SharpConnector/Interfaces/ISharpConnectorClient.cs index 3b2d410..4e584e1 100755 --- a/src/SharpConnector/Interfaces/ISharpConnectorClient.cs +++ b/src/SharpConnector/Interfaces/ISharpConnectorClient.cs @@ -1,29 +1,32 @@ -// (c) 2020 Francesco Del Re -// This code is licensed under MIT license (see LICENSE.txt for details) -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace SharpConnector.Interfaces -{ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using SharpConnector.Entities; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace SharpConnector.Interfaces +{ /// /// The SharpConnectorClient operations interface. /// - /// The payload type. - public interface ISharpConnectorClient - { - T Get(string key); - Task GetAsync(string key); - IEnumerable GetAll(); - bool Insert(string key, T value); - bool Insert(string key, T value, TimeSpan expiration); - Task InsertAsync(string key, T value); - Task InsertAsync(string key, T value, TimeSpan expiration); - bool InsertMany(Dictionary values); - bool InsertMany(Dictionary values, TimeSpan expiration); - bool Delete(string key); - Task DeleteAsync(string key); - bool Update(string key, T value); - Task UpdateAsync(string key, T value); - } + /// The payload type. + public interface ISharpConnectorClient + { + T Get(string key); + Task GetAsync(string key); + IEnumerable GetAll(); + Task> GetAllAsync(); + bool Insert(string key, T value); + bool Insert(string key, T value, TimeSpan expiration); + Task InsertAsync(string key, T value); + Task InsertAsync(string key, T value, TimeSpan expiration); + bool InsertMany(Dictionary values); + bool InsertMany(Dictionary values, TimeSpan expiration); + Task InsertManyAsync(IEnumerable values); + bool Delete(string key); + Task DeleteAsync(string key); + bool Update(string key, T value); + Task UpdateAsync(string key, T value); + } } \ No newline at end of file diff --git a/src/SharpConnector/Middleware/SharpConnectorServiceExtensions.cs b/src/SharpConnector/Middleware/SharpConnectorServiceExtensions.cs new file mode 100644 index 0000000..dc2b5a1 --- /dev/null +++ b/src/SharpConnector/Middleware/SharpConnectorServiceExtensions.cs @@ -0,0 +1,31 @@ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using SharpConnector.Interfaces; + +namespace SharpConnector.Middleware +{ + public static class SharpConnectorServiceExtensions + { + /// + /// Registers the SharpConnector services in the dependency injection container. + /// This allows for a generic SharpConnectorClient to be used with any specified type T. + /// + /// The type parameter that specifies the type the client will handle. + /// The service collection to which the SharpConnector services will be added. + /// The updated service collection with the SharpConnector services registered. + public static IServiceCollection AddSharpConnectorServices(this IServiceCollection services) + { + services.AddControllers(); + + services.AddSingleton>(sp => + { + var configuration = sp.GetRequiredService(); + return new SharpConnectorClient(configuration); + }); + + return services; + } + } +} diff --git a/src/SharpConnector/Operations/LiteDbOperations.cs b/src/SharpConnector/Operations/LiteDbOperations.cs index 3e13537..4237e58 100755 --- a/src/SharpConnector/Operations/LiteDbOperations.cs +++ b/src/SharpConnector/Operations/LiteDbOperations.cs @@ -7,6 +7,9 @@ using SharpConnector.Configuration; using SharpConnector.Entities; using SharpConnector.Utilities; +using SharpConnector.Connectors.Redis; +using System.Linq; +using SharpConnector.Connectors.Memcached; namespace SharpConnector.Operations { @@ -175,5 +178,21 @@ public override async Task UpdateAsync(string key, T value) var connectorEntity = new LiteDbConnectorEntity(key, value, null); return await _liteDbWrapper.UpdateAsync(connectorEntity); } + + public override async Task> GetAllAsync() + { + var connectorEntities = await _liteDbWrapper.GetAllAsync(); + return connectorEntities + .Cast() + .ToList(); + } + + public override async Task InsertManyAsync(IEnumerable values) + { + var connectorEntityList = values + .Cast() + .ToList(); + return await _liteDbWrapper.InsertManyAsync(connectorEntityList); + } } } diff --git a/src/SharpConnector/Operations/MemcachedOperations.cs b/src/SharpConnector/Operations/MemcachedOperations.cs index d7016ab..e3d8050 100755 --- a/src/SharpConnector/Operations/MemcachedOperations.cs +++ b/src/SharpConnector/Operations/MemcachedOperations.cs @@ -2,9 +2,11 @@ // This code is licensed under MIT license (see LICENSE.txt for details) using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using SharpConnector.Configuration; using SharpConnector.Connectors.Memcached; +using SharpConnector.Connectors.Redis; using SharpConnector.Entities; using SharpConnector.Utilities; @@ -167,5 +169,21 @@ public override async Task UpdateAsync(string key, T value) var connectorEntity = new ConnectorEntity(key, value, null); return await _memcachedWrapper.UpdateAsync(connectorEntity); } + + public override async Task> GetAllAsync() + { + var connectorEntities = await _memcachedWrapper.GetAllAsync(); + return connectorEntities + .Cast() + .ToList(); + } + + public override async Task InsertManyAsync(IEnumerable values) + { + var connectorEntityList = values + .Cast() + .ToList(); + return await _memcachedWrapper.InsertManyAsync(connectorEntityList); + } } } diff --git a/src/SharpConnector/Operations/MongoDbOperations.cs b/src/SharpConnector/Operations/MongoDbOperations.cs index df04674..7909326 100755 --- a/src/SharpConnector/Operations/MongoDbOperations.cs +++ b/src/SharpConnector/Operations/MongoDbOperations.cs @@ -2,9 +2,11 @@ // This code is licensed under MIT license (see LICENSE.txt for details) using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using SharpConnector.Configuration; using SharpConnector.Connectors.MongoDb; +using SharpConnector.Connectors.Redis; using SharpConnector.Entities; using SharpConnector.Utilities; @@ -175,5 +177,21 @@ public override async Task UpdateAsync(string key, T value) var connectorEntity = new ConnectorEntity(key, value, null); return await _mongoDbWrapper.UpdateAsync(connectorEntity); } + + public override async Task> GetAllAsync() + { + var connectorEntities = await _mongoDbWrapper.GetAllAsync(); + return connectorEntities + .Cast() + .ToList(); + } + + public override async Task InsertManyAsync(IEnumerable values) + { + var connectorEntityList = values + .Cast() + .ToList(); + return await _mongoDbWrapper.InsertManyAsync(connectorEntityList); + } } } diff --git a/src/SharpConnector/Operations/Operations.cs b/src/SharpConnector/Operations/Operations.cs index a59122d..2a41a7e 100755 --- a/src/SharpConnector/Operations/Operations.cs +++ b/src/SharpConnector/Operations/Operations.cs @@ -16,12 +16,14 @@ public abstract class Operations : IOperations public abstract T Get(string key); public abstract Task GetAsync(string key); public abstract IEnumerable GetAll(); + public abstract Task> GetAllAsync(); public abstract bool Insert(string key, T value); public abstract bool Insert(string key, T value, TimeSpan expiration); public abstract Task InsertAsync(string key, T value); public abstract Task InsertAsync(string key, T value, TimeSpan expiration); public abstract bool InsertMany(Dictionary values); public abstract bool InsertMany(Dictionary values, TimeSpan expiration); + public abstract Task InsertManyAsync(IEnumerable values); public abstract bool Delete(string key); public abstract Task DeleteAsync(string key); public abstract bool Update(string key, T value); diff --git a/src/SharpConnector/Operations/RavenDbOperations.cs b/src/SharpConnector/Operations/RavenDbOperations.cs index 9c471dc..e6e28b2 100755 --- a/src/SharpConnector/Operations/RavenDbOperations.cs +++ b/src/SharpConnector/Operations/RavenDbOperations.cs @@ -2,10 +2,12 @@ // This code is licensed under MIT license (see LICENSE.txt for details) using SharpConnector.Configuration; using SharpConnector.Connectors.RavenDb; +using SharpConnector.Connectors.Redis; using SharpConnector.Entities; using SharpConnector.Utilities; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace SharpConnector.Operations @@ -175,5 +177,21 @@ public override async Task UpdateAsync(string key, T value) var connectorEntity = new ConnectorEntity(key, value, null); return await _ravenDbWrapper.UpdateAsync(connectorEntity); } + + public override async Task> GetAllAsync() + { + var connectorEntities = await _ravenDbWrapper.GetAllAsync(); + return connectorEntities + .Cast() + .ToList(); + } + + public override async Task InsertManyAsync(IEnumerable values) + { + var connectorEntityList = values + .Cast() + .ToList(); + return await _ravenDbWrapper.InsertManyAsync(connectorEntityList); + } } } diff --git a/src/SharpConnector/Operations/RedisOperations.cs b/src/SharpConnector/Operations/RedisOperations.cs index cc3c68d..7e9160a 100755 --- a/src/SharpConnector/Operations/RedisOperations.cs +++ b/src/SharpConnector/Operations/RedisOperations.cs @@ -2,6 +2,7 @@ // This code is licensed under MIT license (see LICENSE.txt for details) using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using SharpConnector.Configuration; using SharpConnector.Connectors.Redis; @@ -175,5 +176,21 @@ public override async Task UpdateAsync(string key, T value) var connectorEntity = new ConnectorEntity(key, value, null); return await _redisWrapper.UpdateAsync(connectorEntity); } + + public override async Task> GetAllAsync() + { + var connectorEntities = await _redisWrapper.GetAllAsync(); + return connectorEntities + .Cast() + .ToList(); + } + + public override async Task InsertManyAsync(IEnumerable values) + { + var connectorEntityList = values + .Cast() + .ToList(); + return await _redisWrapper.InsertManyAsync(connectorEntityList); + } } } diff --git a/src/SharpConnector/SharpConnector.csproj b/src/SharpConnector/SharpConnector.csproj index 19ebe35..82328cd 100755 --- a/src/SharpConnector/SharpConnector.csproj +++ b/src/SharpConnector/SharpConnector.csproj @@ -13,22 +13,27 @@ 2.0.0.0 2.0.0.0 logo.png + README.md - + - - - + + + - - + + + + True + \ + True diff --git a/src/SharpConnector/SharpConnector.sln b/src/SharpConnector/SharpConnector.sln index f744048..3a09363 100755 --- a/src/SharpConnector/SharpConnector.sln +++ b/src/SharpConnector/SharpConnector.sln @@ -1,11 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30621.155 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35327.3 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpConnector", "SharpConnector.csproj", "{04B2A952-D494-45B5-8819-EB0C38975CCD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpConnector", "SharpConnector.csproj", "{04B2A952-D494-45B5-8819-EB0C38975CCD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpConnector.Test", "..\SharpConnector.Test\SharpConnector.Test.csproj", "{F5953500-0FA2-4520-8E52-AB7E67293F09}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpConnector.Tests", "..\SharpConnector.Tests\SharpConnector.Tests.csproj", "{F5953500-0FA2-4520-8E52-AB7E67293F09}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpConnector.Api", "..\SharpConnector.Api\SharpConnector.Api.csproj", "{72A48B94-89D2-4F16-AE8C-E32B763EFA99}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {F5953500-0FA2-4520-8E52-AB7E67293F09}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5953500-0FA2-4520-8E52-AB7E67293F09}.Release|Any CPU.ActiveCfg = Release|Any CPU {F5953500-0FA2-4520-8E52-AB7E67293F09}.Release|Any CPU.Build.0 = Release|Any CPU + {72A48B94-89D2-4F16-AE8C-E32B763EFA99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72A48B94-89D2-4F16-AE8C-E32B763EFA99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72A48B94-89D2-4F16-AE8C-E32B763EFA99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72A48B94-89D2-4F16-AE8C-E32B763EFA99}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/SharpConnector/SharpConnectorClient.cs b/src/SharpConnector/SharpConnectorClient.cs index 5f404cb..36ec695 100755 --- a/src/SharpConnector/SharpConnectorClient.cs +++ b/src/SharpConnector/SharpConnectorClient.cs @@ -13,6 +13,11 @@ public sealed class SharpConnectorClient : ISharpConnectorClient { private IOperations _operations; + public SharpConnectorClient(IConfiguration configuration) + { + InitOperations(configuration); + } + /// /// Create e new SharpConnectorClient instance. /// @@ -97,6 +102,11 @@ public IEnumerable GetAll() return _operations.GetAll(); } + public async Task> GetAllAsync() + { + return await _operations.GetAllAsync(); + } + /// /// Set key to hold the string value. If key already holds a value, it is overwritten, regardless of its type. /// @@ -205,5 +215,15 @@ public async Task UpdateAsync(string key, T value) { return await _operations.UpdateAsync(key, value); } + + /// + /// Asynchronously inserts multiple ConnectorEntity instances into the storage. + /// + /// A list of ConnectorEntity instances to be inserted. + /// A Task representing the asynchronous operation, containing a boolean value indicating the success or failure of the insert operation. + public async Task InsertManyAsync(IEnumerable values) + { + return await _operations.InsertManyAsync(values); + } } } diff --git a/src/SharpConnector/Utilities/Converter.cs b/src/SharpConnector/Utilities/Converter.cs index 7cd5b72..d20b7db 100644 --- a/src/SharpConnector/Utilities/Converter.cs +++ b/src/SharpConnector/Utilities/Converter.cs @@ -3,7 +3,6 @@ using SharpConnector.Entities; using System; using System.Collections.Generic; -using System.Threading.Tasks; namespace SharpConnector.Utilities { @@ -74,7 +73,7 @@ public static IEnumerable ToPayloadList(this IEnumerable ToConnectorEntityList(this Dictionary values, TimeSpan? expiration = null) { if (values == null) - return new List(); + return []; var connectorEntities = new List(); foreach (var entry in values) @@ -96,7 +95,7 @@ public static List ToConnectorEntityList(this Dictionary ToLiteDbConnectorEntityList(this Dictionary values, TimeSpan? expiration = null) { if (values == null) - return new List(); + return []; var connectorEntities = new List(); foreach (var entry in values) diff --git a/src/SharpConnector/Utilities/Serialization.cs b/src/SharpConnector/Utilities/Serialization.cs new file mode 100644 index 0000000..6e213b9 --- /dev/null +++ b/src/SharpConnector/Utilities/Serialization.cs @@ -0,0 +1,33 @@ +// (c) 2020 Francesco Del Re +// This code is licensed under MIT license (see LICENSE.txt for details) +using System; +using System.Text.Json; + +namespace SharpConnector.Utilities +{ + public static class Serialization + { + /// + /// Determines if the given object is serializable. + /// + /// The object to check. + /// True if the object can be serialized; otherwise, false. + public static bool IsSerializable(this object obj) + { + try + { + // Attempt to serialize the object + JsonSerializer.Serialize(obj); + return true; + } + catch (JsonException jsonEx) + { + return false; + } + catch (Exception ex) + { + return false; + } + } + } +}