From 516d18314b1daadaa0dea88c039f01c8b5869c90 Mon Sep 17 00:00:00 2001 From: David Lebee Date: Wed, 29 Jul 2020 20:08:24 -0400 Subject: [PATCH] some batch actions, and added some methods while being there :) --- .../IObjectStorageCollection.cs | 33 +++++ .../CrudTests.cs | 42 ++++++ .../MongoObjectStorageCollection.cs | 135 +++++++++++++++++- 3 files changed, 208 insertions(+), 2 deletions(-) diff --git a/PoweredSoft.ObjectStorage.Core/IObjectStorageCollection.cs b/PoweredSoft.ObjectStorage.Core/IObjectStorageCollection.cs index 10a2d13..cfa513c 100644 --- a/PoweredSoft.ObjectStorage.Core/IObjectStorageCollection.cs +++ b/PoweredSoft.ObjectStorage.Core/IObjectStorageCollection.cs @@ -20,5 +20,38 @@ namespace PoweredSoft.ObjectStorage.Core Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken)); IQueryable AsQueryable(); List GetObjectKeys(); + Task AnyAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)); + Task CountAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)); + Task LongCountAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)); + Task FirstOrDefaultAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)); + Task FirstAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)); + + Task UpdateManyAsync(Expression> predicate, + Expression> fieldExpression, TField value, + CancellationToken cancellationToken = default); + + Task UpdateManyAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + CancellationToken cancellationToken = default); + + Task UpdateManyAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + Expression> fieldExpression3, TField3 value3, + CancellationToken cancellationToken = default); + + Task UpdateOneAsync(Expression> predicate, + Expression> fieldExpression, TField value, + CancellationToken cancellationToken = default); + Task UpdateOneAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + CancellationToken cancellationToken = default); + Task UpdateOneAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + Expression> fieldExpression3, TField3 value3, + CancellationToken cancellationToken = default); } } diff --git a/PoweredSoft.ObjectStorage.MongoDB.Tests/CrudTests.cs b/PoweredSoft.ObjectStorage.MongoDB.Tests/CrudTests.cs index 57bdaf8..8ced37a 100644 --- a/PoweredSoft.ObjectStorage.MongoDB.Tests/CrudTests.cs +++ b/PoweredSoft.ObjectStorage.MongoDB.Tests/CrudTests.cs @@ -9,6 +9,35 @@ namespace PoweredSoft.ObjectStorage.MongoDB.Tests { public class CrudTests { + [Fact] + public async Task UpdateMany() + { + var osc = MongoDatabaseFactory.GetObjectStorageContext(); + var collection = osc.GetCollection(); + var a = await collection.AddAsync(new Contact + { + LastName = "A", + FirstName = "A" + }); + + var b = await collection.AddAsync(new Contact + { + LastName = "B", + FirstName = "B" + }); + + await collection.UpdateManyAsync(t => t.LastName == "A" || t.LastName == "B", t => t.LastName, "C"); + var howManyCs = await collection.GetAllAsync(t => t.LastName == "C"); + var howManyCs2 = await collection.LongCountAsync(t => t.LastName == "C"); + Assert.Equal(2, howManyCs.Count); + Assert.Equal(2, howManyCs2); + + + // clean up. + await collection.DeleteAsync(a); + await collection.DeleteAsync(b); + } + [Fact] public async Task CreateUpdateThenDelete() { @@ -26,6 +55,12 @@ namespace PoweredSoft.ObjectStorage.MongoDB.Tests var updatedContact = await collection.UpdateAsync(contact); Assert.Equal("Norris", updatedContact.LastName); + // update name back to not norris + await collection.UpdateOneAsync(t => t.Id == contact.Id, t => t.LastName, "Not Norris"); + + var updatedContact2 = await collection.FirstAsync(t => t.Id == contact.Id); + Assert.Equal("Not Norris", updatedContact2.LastName); + // delete the test. await collection.DeleteAsync(updatedContact); @@ -49,6 +84,13 @@ namespace PoweredSoft.ObjectStorage.MongoDB.Tests var fetchedUsingGetAsync = await collection.GetAsync(contact.Id); Assert.NotNull(fetchedUsingGetAsync); + Assert.True(await collection.AnyAsync(t => t.Id == contact.Id), "Any async does not work"); + Assert.NotNull(await collection.FirstOrDefaultAsync(t => t.Id == contact.Id)); + + // does not crash. + await collection.FirstAsync(t => t.Id == contact.Id); + + // now delete it. await collection.DeleteAsync(fetchedUsingGetAsync); } diff --git a/PoweredSoft.ObjectStorage.MongoDB/MongoObjectStorageCollection.cs b/PoweredSoft.ObjectStorage.MongoDB/MongoObjectStorageCollection.cs index ff6a4b4..0929147 100644 --- a/PoweredSoft.ObjectStorage.MongoDB/MongoObjectStorageCollection.cs +++ b/PoweredSoft.ObjectStorage.MongoDB/MongoObjectStorageCollection.cs @@ -6,7 +6,8 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; using MongoDB.Bson.Serialization.Attributes; -using MongoDB.Driver; +using MongoDB.Driver; +using MongoDB.Driver.Linq; using PoweredSoft.DynamicLinq.Helpers; using PoweredSoft.ObjectStorage.Core; @@ -32,6 +33,11 @@ namespace PoweredSoft.ObjectStorage.MongoDB return entity; } + public Task AnyAsync(Expression> predicate, CancellationToken cancellationToken = default(CancellationToken)) + { + return MongoQueryable.AnyAsync(Collection.AsQueryable(), predicate, cancellationToken); + } + public IQueryable AsQueryable() { return Collection.AsQueryable(); @@ -95,6 +101,131 @@ namespace PoweredSoft.ObjectStorage.MongoDB { GetBsonIdProperty() }; - } + } + + public Task FirstOrDefaultAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + return this.Collection.AsQueryable().FirstOrDefaultAsync(predicate, cancellationToken); + } + + public Task FirstAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + return this.Collection.AsQueryable().FirstAsync(predicate, cancellationToken); + } + + public async Task UpdateManyAsync(Expression> predicate, Expression> fieldExpression, TField value, CancellationToken cancellationToken = default) + { + var updateDefinition = Builders.Update.Set(fieldExpression, value); + await Collection.UpdateManyAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateManyAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + + CancellationToken cancellationToken = default) + { + var updateDefinition = Builders.Update + .Set(fieldExpression, value) + .Set(fieldExpression2, value2) + ; + + await Collection.UpdateManyAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateManyAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + Expression> fieldExpression3, TField3 value3, + CancellationToken cancellationToken = default) + { + var updateDefinition = Builders.Update + .Set(fieldExpression, value) + .Set(fieldExpression2, value2) + .Set(fieldExpression3, value3) + ; + + await Collection.UpdateManyAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateOneAsync(Expression> predicate, Expression> fieldExpression, TField value, CancellationToken cancellationToken = default) + { + var updateDefinition = Builders.Update.Set(fieldExpression, value); + await Collection.UpdateOneAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateOneAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + CancellationToken cancellationToken = default) + { + var updateDefinition = Builders.Update + .Set(fieldExpression, value) + .Set(fieldExpression2, value2); + + await Collection.UpdateOneAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateOneAsync(Expression> predicate, + Expression> fieldExpression, TField value, + Expression> fieldExpression2, TField2 value2, + Expression> fieldExpression3, TField3 value3, + CancellationToken cancellationToken = default) + { + var updateDefinition = Builders.Update + .Set(fieldExpression, value) + .Set(fieldExpression2, value2) + .Set(fieldExpression3, value3) + ; + + await Collection.UpdateOneAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateOneAsync(Expression> predicate, UpdateDefinition updateDefinition, CancellationToken cancellationToken = default) + { + await Collection.UpdateOneAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task UpdateManyAsync(Expression> predicate, UpdateDefinition updateDefinition, CancellationToken cancellationToken = default) + { + await Collection.UpdateManyAsync(predicate, updateDefinition, new UpdateOptions() + { + IsUpsert = false + }, cancellationToken); + } + + public async Task CountAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + var longResult = await Collection.CountDocumentsAsync(predicate, null, cancellationToken); + if (longResult > int.MaxValue) + throw new Exception("Exceeds integer maximum value"); + return (int)longResult; + } + + public Task LongCountAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + return Collection.CountDocumentsAsync(predicate, null, cancellationToken); + } } }