diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/BaseIndexTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/BaseIndexTests.cs index 566aa75..ba9ce13 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/BaseIndexTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/BaseIndexTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading; using CoreUnitTests.Infrastructure; using MongoDB.Bson; -using MongoDB.Bson.Serialization; using MongoDB.Driver; using MongoDbGenericRepository.DataAccess.Index; using Moq; @@ -41,5 +40,4 @@ public class BaseIndexTests : GenericTestContext return (asyncCursor, indexManager); } - } diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateAscendingIndexAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateAscendingIndexAsyncTests.cs index e3040e8..01f5ebc 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateAscendingIndexAsyncTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateAscendingIndexAsyncTests.cs @@ -19,7 +19,7 @@ public class CreateAscendingIndexAsyncTests : BaseIndexTests private readonly Expression> fieldExpression = t => t.SomeContent2; [Fact] - public async Task WhenFieldExpression_ThenCreatesIndex() + public async Task WithFieldExpression_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -42,7 +42,7 @@ public class CreateAscendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptions_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptions_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -68,7 +68,7 @@ public class CreateAscendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndPartitionKey_ThenCreatesIndex() + public async Task WithFieldExpressionAndPartitionKey_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -95,7 +95,7 @@ public class CreateAscendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -121,7 +121,7 @@ public class CreateAscendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateCombinedTextIndexAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateCombinedTextIndexAsyncTests.cs index 5f1ed30..d801586 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateCombinedTextIndexAsyncTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateCombinedTextIndexAsyncTests.cs @@ -29,7 +29,7 @@ public class CreateCombinedTextIndexAsyncTests : BaseIndexTests => this.testOutputHelper = testOutputHelper; [Fact] - public async Task WhenFieldExpression_ThenCreatesIndex() + public async Task WithFieldExpression_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -52,7 +52,7 @@ public class CreateCombinedTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptions_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptions_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -78,7 +78,7 @@ public class CreateCombinedTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndPartitionKey_ThenCreatesIndex() + public async Task WithFieldExpressionAndPartitionKey_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -105,7 +105,7 @@ public class CreateCombinedTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -131,7 +131,7 @@ public class CreateCombinedTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateDescendingIndexAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateDescendingIndexAsyncTests.cs index d0bb876..8ad433a 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateDescendingIndexAsyncTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateDescendingIndexAsyncTests.cs @@ -19,7 +19,7 @@ public class CreateDescendingIndexAsyncTests : BaseIndexTests private readonly Expression> fieldExpression = t => t.SomeContent2; [Fact] - public async Task WhenFieldExpression_ThenCreatesIndex() + public async Task WithFieldExpression_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -42,7 +42,7 @@ public class CreateDescendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptions_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptions_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -68,7 +68,7 @@ public class CreateDescendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndPartitionKey_ThenCreatesIndex() + public async Task WithFieldExpressionAndPartitionKey_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -95,7 +95,7 @@ public class CreateDescendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -121,7 +121,7 @@ public class CreateDescendingIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateHashedIndexAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateHashedIndexAsyncTests.cs index f1172c7..74c576d 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateHashedIndexAsyncTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateHashedIndexAsyncTests.cs @@ -24,7 +24,7 @@ public class CreateHashedIndexAsyncTests : BaseIndexTests => this.testOutputHelper = testOutputHelper; [Fact] - public async Task WhenFieldExpression_ThenCreatesIndex() + public async Task WithFieldExpression_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -47,7 +47,7 @@ public class CreateHashedIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptions_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptions_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -73,7 +73,7 @@ public class CreateHashedIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndPartitionKey_ThenCreatesIndex() + public async Task WithFieldExpressionAndPartitionKey_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -100,7 +100,7 @@ public class CreateHashedIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -126,7 +126,7 @@ public class CreateHashedIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateTextIndexAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateTextIndexAsyncTests.cs index f54b2ff..3c482dd 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateTextIndexAsyncTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/CreateTextIndexAsyncTests.cs @@ -19,7 +19,7 @@ public class CreateTextIndexAsyncTests : BaseIndexTests private readonly Expression> fieldExpression = t => t.SomeContent2; [Fact] - public async Task WhenFieldExpression_ThenCreatesIndex() + public async Task WithFieldExpression_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -42,7 +42,7 @@ public class CreateTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptions_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptions_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -68,7 +68,7 @@ public class CreateTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndPartitionKey_ThenCreatesIndex() + public async Task WithFieldExpressionAndPartitionKey_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -95,7 +95,7 @@ public class CreateTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -121,7 +121,7 @@ public class CreateTextIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_ThenCreatesIndex() + public async Task WithFieldExpressionAndOptionsAndPartitionKeyAndCancellationToken_CreatesIndex() { // Arrange var expectedIndexName = Fixture.Create(); diff --git a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/DropIndexAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/DropIndexAsyncTests.cs index 6485411..b8b30ac 100644 --- a/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/DropIndexAsyncTests.cs +++ b/CoreUnitTests/DataAccessTests/MongoDbIndexHandlerTests/DropIndexAsyncTests.cs @@ -13,7 +13,7 @@ namespace CoreUnitTests.DataAccessTests.MongoDbIndexHandlerTests; public class DropIndexAsyncTests : BaseIndexTests { [Fact] - public async Task WhenIndexName_ThenDropsIndex() + public async Task WithIndexName_DropsIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -30,7 +30,7 @@ public class DropIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenIndexNameAndPartitionKey_ThenDropsIndex() + public async Task WithIndexNameAndPartitionKey_DropsIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -50,7 +50,7 @@ public class DropIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenIndexNameAndCancellationToken_ThenDropsIndex() + public async Task WithIndexNameAndCancellationToken_DropsIndex() { // Arrange var expectedIndexName = Fixture.Create(); @@ -69,7 +69,7 @@ public class DropIndexAsyncTests : BaseIndexTests } [Fact] - public async Task WhenIndexNameAndPartitionKeyAndCancellationToken_ThenDropsIndex() + public async Task WithIndexNameAndPartitionKeyAndCancellationToken_DropsIndex() { // Arrange var expectedIndexName = Fixture.Create(); diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/BaseReaderTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/BaseReaderTests.cs new file mode 100644 index 0000000..e4057fa --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/BaseReaderTests.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.Threading; +using CoreUnitTests.Infrastructure; +using MongoDB.Driver; +using MongoDbGenericRepository.DataAccess.Read; +using Moq; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class BaseReaderTests : GenericTestContext +{ + protected Mock> SetupSyncCursor(List documents) + { + var asyncCursor = MockOf>(); + + var moveNextSequence = asyncCursor + .SetupSequence(x => x.MoveNext(It.IsAny())); + + var currentSequence = asyncCursor + .SetupSequence(x => x.Current); + + foreach (var projection in documents) + { + moveNextSequence.Returns(true); + currentSequence.Returns(new[] {projection}); + } + + moveNextSequence.Returns(false); + return asyncCursor; + } + + protected Mock> SetupAsyncCursor(List documents) + { + var asyncCursor = MockOf>(); + + var moveNextSequence = asyncCursor + .SetupSequence(x => x.MoveNextAsync(It.IsAny())); + + var currentSequence = asyncCursor + .SetupSequence(x => x.Current); + + foreach (var projection in documents) + { + moveNextSequence.ReturnsAsync(true); + currentSequence.Returns(new[] {projection}); + } + + moveNextSequence.ReturnsAsync(false); + return asyncCursor; + } + + protected static void SetupFindAsync(Mock> collection, Mock> asyncCursor) => + collection + .Setup( + x => x.FindAsync( + It.IsAny>(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(asyncCursor.Object); + + protected static void SetupFindSync(Mock> collection, Mock> asyncCursor) => + collection + .Setup( + x => x.FindSync( + It.IsAny>(), + It.IsAny>(), + It.IsAny())) + .Returns(asyncCursor.Object); +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetByIdAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetByIdAsyncTests.cs new file mode 100644 index 0000000..d9af227 --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetByIdAsyncTests.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class GetByIdAsyncTests : BaseReaderTests +{ + [Fact] + public async Task WithId_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetByIdAsync(documents[0].Id); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithIdAndCancellationToken_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetByIdAsync(documents[0].Id, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithIdAndPartitionKey_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetByIdAsync(documents[0].Id, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithIdAndPartitionKeyAndCancellationToken_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetByIdAsync(documents[0].Id, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + private (Mock, Mock>) SetupAsyncGet( + List documents, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupAsyncCursor(documents); + + SetupFindAsync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetByIdTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetByIdTests.cs new file mode 100644 index 0000000..7d3da07 --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetByIdTests.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class GetByIdTests : BaseReaderTests +{ + [Fact] + public void WithId_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = Sut.GetById(documents[0].Id); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithIdAndCancellationToken_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = Sut.GetById(documents[0].Id, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithIdAndPartitionKey_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetById(documents[0].Id, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithIdAndPartitionKeyAndCancellationToken_GetsMatchingDocument() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetById(documents[0].Id, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + private (Mock, Mock>) SetupAsyncGet( + List documents, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupSyncCursor(documents); + + SetupFindSync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetOneAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetOneAsyncTests.cs new file mode 100644 index 0000000..51818de --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetOneAsyncTests.cs @@ -0,0 +1,283 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class GetOneAsyncTests : BaseReaderTests +{ + [Fact] + public async Task WithFilter_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupAsyncGet(documents, collection); + + + // Act + var result = await Sut.GetOneAsync(filter); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithFilterAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var token = new CancellationToken(true); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetOneAsync(filter, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithFilterAndPartitionKey_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetOneAsync(filter, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithFilterAndPartitionKeyAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetOneAsync(filter, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithCondition_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetOneAsync(condition); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithConditionAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetOneAsync(condition, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithConditionAndPartitionKey_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetOneAsync(condition, partitionKey: partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithConditionAndPartitionKeyAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetOneAsync(condition, partitionKey: partitionKey, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithConditionAndFindOptions_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var options = Fixture + .Build() + .Without(x => x.Comment) + .Without(x => x.Hint) + .Create(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetOneAsync(condition, options); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithConditionAndFindOptionsAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var options = Fixture + .Build() + .Without(x => x.Comment) + .Without(x => x.Hint) + .Create(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncGet(documents, collection); + + // Act + var result = await Sut.GetOneAsync(condition, options, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public async Task WithConditionAndFindOptionsAndPartitionKeyAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var options = Fixture + .Build() + .Without(x => x.Comment) + .Without(x => x.Hint) + .Create(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var token = new CancellationToken(true); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncGet(documents, collection, partitionKey); + + // Act + var result = await Sut.GetOneAsync(condition, options, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + private (Mock, Mock>) SetupAsyncGet( + List documents, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupAsyncCursor(documents); + + SetupFindAsync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetOneTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetOneTests.cs new file mode 100644 index 0000000..84944e6 --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/GetOneTests.cs @@ -0,0 +1,282 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class GetOneTests : BaseReaderTests +{ + [Fact] + public void WithFilter_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupSyncGet(documents, collection); + + + // Act + var result = Sut.GetOne(filter); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithFilterAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var token = new CancellationToken(true); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupSyncGet(documents, collection); + + // Act + var result = Sut.GetOne(filter, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithFilterAndPartitionKey_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupSyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetOne(filter, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithFilterAndPartitionKeyAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + Expression> filter = x => x.Id == documents[0].Id; + var (context, cursor) = SetupSyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetOne(filter, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithCondition_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var (context, cursor) = SetupSyncGet(documents, collection); + + // Act + var result = Sut.GetOne(condition); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithConditionAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var token = new CancellationToken(true); + var (context, cursor) = SetupSyncGet(documents, collection); + + // Act + var result = Sut.GetOne(condition, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithConditionAndPartitionKey_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupSyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetOne(condition, partitionKey: partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithConditionAndPartitionKeyAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + var (context, cursor) = SetupSyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetOne(condition, partitionKey: partitionKey, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithConditionAndFindOptions_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var options = Fixture + .Build() + .Without(x => x.Comment) + .Without(x => x.Hint) + .Create(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var (context, cursor) = SetupSyncGet(documents, collection); + + // Act + var result = Sut.GetOne(condition, options); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithConditionAndFindOptionsAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var options = Fixture + .Build() + .Without(x => x.Comment) + .Without(x => x.Hint) + .Create(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var token = new CancellationToken(true); + var (context, cursor) = SetupSyncGet(documents, collection); + + // Act + var result = Sut.GetOne(condition, options, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + [Fact] + public void WithConditionAndFindOptionsAndPartitionKeyAndCancellationToken_GetsMatchingDocuments() + { + // Arrange + var collection = MockOf>(); + var documents = Fixture.CreateMany().ToList(); + var options = Fixture + .Build() + .Without(x => x.Comment) + .Without(x => x.Hint) + .Create(); + var condition = Builders.Filter.Eq("Id", documents[0].Id); + var token = new CancellationToken(true); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupSyncGet(documents, collection, partitionKey); + + // Act + var result = Sut.GetOne(condition, options, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(documents[0]); + } + + private (Mock, Mock>) SetupSyncGet( + List documents, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupSyncCursor(documents); + + SetupFindSync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectManyAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectManyAsyncTests.cs new file mode 100644 index 0000000..a4633bd --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectManyAsyncTests.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class ProjectManyAsyncTests : BaseReaderTests +{ + private readonly Expression> filter = t => string.IsNullOrWhiteSpace(t.SomeContent2); + + private readonly Expression> + projectionExpression = t => new TestProjection {TestDocumentId = t.Id, NestedData = t.Nested.SomeDate}; + + [Fact] + public async Task WithFilterAndProjection_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var (context, cursor) = SetupAsyncProjection(projections, collection); + + // Act + var result = await Sut.ProjectManyAsync(filter, projectionExpression); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + [Fact] + public async Task WithFilterAndProjectionAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var token = new CancellationToken(false); + var (context, cursor) = SetupAsyncProjection(projections, collection); + + // Act + var result = await Sut.ProjectManyAsync(filter, projectionExpression, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + [Fact] + public async Task WithFilterAndProjectionAndPartitionKey_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncProjection(projections, collection, partitionKey); + + // Act + var result = await Sut.ProjectManyAsync(filter, projectionExpression, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + [Fact] + public async Task WithFilterAndProjectionAndPartitionKeyAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(false); + var (context, cursor) = SetupAsyncProjection(projections, collection, partitionKey); + + // Act + var result = await Sut.ProjectManyAsync(filter, projectionExpression, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + private (Mock, Mock>) SetupAsyncProjection( + List projections, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupAsyncCursor(projections); + + collection + .Setup( + x => x.FindAsync( + It.IsAny>(), + It.IsAny>(), + It.IsAny())) + .ReturnsAsync(asyncCursor.Object); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectManyTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectManyTests.cs new file mode 100644 index 0000000..c5f0aea --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectManyTests.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class ProjectManyTests : BaseReaderTests +{ + private readonly Expression> filter = t => string.IsNullOrWhiteSpace(t.SomeContent2); + + private readonly Expression> + projectionExpression = t => new TestProjection {TestDocumentId = t.Id, NestedData = t.Nested.SomeDate}; + + [Fact] + public void WithFilterAndProjection_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var (context, cursor) = SetupAsyncProjection(projections, collection); + + // Act + var result = Sut.ProjectMany(filter, projectionExpression); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + [Fact] + public void WithFilterAndProjectionAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var token = new CancellationToken(false); + var (context, cursor) = SetupAsyncProjection(projections, collection); + + // Act + var result = Sut.ProjectMany(filter, projectionExpression, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + [Fact] + public void WithFilterAndProjectionAndPartitionKey_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncProjection(projections, collection, partitionKey); + + // Act + var result = Sut.ProjectMany(filter, projectionExpression, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.AtLeast(1)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + [Fact] + public void WithFilterAndProjectionAndPartitionKeyAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(false); + var (context, cursor) = SetupAsyncProjection(projections, collection, partitionKey); + + // Act + var result = Sut.ProjectMany(filter, projectionExpression, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.AtLeast(projections.Count)); + result.Should().NotBeNull(); + result.Should().OnlyContain(x => projections.Contains(x)); + } + + private (Mock, Mock>) SetupAsyncProjection( + List projections, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupSyncCursor(projections); + + SetupFindSync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectOneAsyncTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectOneAsyncTests.cs new file mode 100644 index 0000000..7c21b07 --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectOneAsyncTests.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class ProjectOneAsyncTests : BaseReaderTests +{ + private readonly Expression> filter = t => string.IsNullOrWhiteSpace(t.SomeContent2); + + private readonly Expression> + projectionExpression = t => new TestProjection {TestDocumentId = t.Id, NestedData = t.Nested.SomeDate}; + + [Fact] + public async Task WithFilterAndProjection_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var (context, cursor) = SetupAsyncProjection(projections, collection); + + // Act + var result = await Sut.ProjectOneAsync(filter, projectionExpression); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + [Fact] + public async Task WithFilterAndProjectionAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncProjection(projections, collection); + + // Act + var result = await Sut.ProjectOneAsync(filter, projectionExpression, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + [Fact] + public async Task WithFilterAndProjectionAndPartitionKey_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupAsyncProjection(projections, collection, partitionKey); + + // Act + var result = await Sut.ProjectOneAsync(filter, projectionExpression, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + [Fact] + public async Task WithFilterAndProjectionAndPartitionKeyAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + var (context, cursor) = SetupAsyncProjection(projections, collection, partitionKey); + + // Act + var result = await Sut.ProjectOneAsync(filter, projectionExpression, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNextAsync(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + private (Mock, Mock>) SetupAsyncProjection( + List projections, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupAsyncCursor(projections); + + SetupFindAsync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectOneTests.cs b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectOneTests.cs new file mode 100644 index 0000000..eabc833 --- /dev/null +++ b/CoreUnitTests/DataAccessTests/MongoDbReaderTests/ProjectOneTests.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using AutoFixture; +using CoreUnitTests.Infrastructure.Model; +using FluentAssertions; +using MongoDB.Driver; +using MongoDbGenericRepository; +using Moq; +using Xunit; + +namespace CoreUnitTests.DataAccessTests.MongoDbReaderTests; + +public class ProjectOneTests : BaseReaderTests +{ + private readonly Expression> filter = t => string.IsNullOrWhiteSpace(t.SomeContent2); + + private readonly Expression> + projectionExpression = t => new TestProjection {TestDocumentId = t.Id, NestedData = t.Nested.SomeDate}; + + [Fact] + public void WithFilterAndProjection_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var (context, cursor) = SetupProjection(projections, collection); + + // Act + var result = Sut.ProjectOne(filter, projectionExpression); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + [Fact] + public void WithFilterAndProjectionAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var token = new CancellationToken(true); + var (context, cursor) = SetupProjection(projections, collection); + + // Act + var result = Sut.ProjectOne(filter, projectionExpression, cancellationToken: token); + + // Assert + context.Verify(x => x.GetCollection(null), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + [Fact] + public void WithFilterAndProjectionAndPartitionKey_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var (context, cursor) = SetupProjection(projections, collection, partitionKey); + + // Act + var result = Sut.ProjectOne(filter, projectionExpression, partitionKey); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(CancellationToken.None), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + [Fact] + public void WithFilterAndProjectionAndPartitionKeyAndCancellationToken_Projects() + { + // Arrange + var collection = MockOf>(); + var projections = Fixture.CreateMany().ToList(); + var partitionKey = Fixture.Create(); + var token = new CancellationToken(true); + var (context, cursor) = SetupProjection(projections, collection, partitionKey); + + // Act + var result = Sut.ProjectOne(filter, projectionExpression, partitionKey, token); + + // Assert + context.Verify(x => x.GetCollection(partitionKey), Times.Once); + cursor.Verify(x => x.Current, Times.Once); + cursor.Verify(x => x.MoveNext(token), Times.Once); + result.Should().NotBeNull(); + result.Should().Be(projections[0]); + } + + private (Mock, Mock>) SetupProjection( + List projections, + Mock> collection, + string partitionKey = null) + { + var asyncCursor = SetupSyncCursor(projections); + + SetupFindSync(collection, asyncCursor); + + var context = MockOf(); + + context + .Setup(x => x.GetCollection(partitionKey)) + .Returns(collection.Object); + + return (context, asyncCursor); + } +} diff --git a/CoreUnitTests/Infrastructure/Model/TestProjection.cs b/CoreUnitTests/Infrastructure/Model/TestProjection.cs new file mode 100644 index 0000000..7d278a1 --- /dev/null +++ b/CoreUnitTests/Infrastructure/Model/TestProjection.cs @@ -0,0 +1,10 @@ +using System; + +namespace CoreUnitTests.Infrastructure.Model; + +public class TestProjection +{ + public Guid TestDocumentId { get; set; } + + public DateTime NestedData { get; set; } +} diff --git a/MongoDbGenericRepository/Abstractions/IMongoDbContext.cs b/MongoDbGenericRepository/Abstractions/IMongoDbContext.cs index bca34b4..e3c70b5 100644 --- a/MongoDbGenericRepository/Abstractions/IMongoDbContext.cs +++ b/MongoDbGenericRepository/Abstractions/IMongoDbContext.cs @@ -25,7 +25,7 @@ namespace MongoDbGenericRepository IMongoCollection GetCollection(string partitionKey = null); /// - /// Drops a collection having a partitionkey, use very carefully. + /// Drops a collection having a partitionKey, use very carefully. /// /// void DropCollection(string partitionKey = null); diff --git a/MongoDbGenericRepository/DataAccess/Read/IMongoDbReader.cs b/MongoDbGenericRepository/DataAccess/Read/IMongoDbReader.cs index 8665bd8..7230aa3 100644 --- a/MongoDbGenericRepository/DataAccess/Read/IMongoDbReader.cs +++ b/MongoDbGenericRepository/DataAccess/Read/IMongoDbReader.cs @@ -26,8 +26,8 @@ namespace MongoDbGenericRepository.DataAccess.Read /// An optional partition key. /// An optional cancellation Token. Task ProjectOneAsync( - Expression> filter, - Expression> projection, + Expression> filter, + Expression> projection, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument @@ -43,7 +43,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A LINQ expression filter. /// The projection expression. /// An optional partition key. - TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) + TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable where TProjection : class; @@ -59,8 +59,8 @@ namespace MongoDbGenericRepository.DataAccess.Read /// An optional partition key. /// An optional cancellation Token. Task> ProjectManyAsync( - Expression> filter, - Expression> projection, + Expression> filter, + Expression> projection, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument @@ -76,13 +76,13 @@ namespace MongoDbGenericRepository.DataAccess.Read /// The document filter. /// The projection expression. /// An optional partition key. - List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable where TProjection : class; /// - /// Groups a collection of documents given a grouping criteria, + /// Groups a collection of documents given a grouping criteria, /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. /// /// The type representing a Document. @@ -95,13 +95,13 @@ namespace MongoDbGenericRepository.DataAccess.Read List GroupBy( Expression> groupingCriteria, Expression, TProjection>> groupProjection, - string partitionKey = null) + string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable where TProjection : class, new(); /// - /// Groups filtered a collection of documents given a grouping criteria, + /// Groups filtered a collection of documents given a grouping criteria, /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. /// /// The type representing a Document. @@ -116,13 +116,13 @@ namespace MongoDbGenericRepository.DataAccess.Read Expression> filter, Expression> selector, Expression, TProjection>> projection, - string partitionKey = null) + string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable where TProjection : class, new(); /// - /// Groups filtered a collection of documents given a grouping criteria, + /// Groups filtered a collection of documents given a grouping criteria, /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. /// /// The type representing a Document. @@ -207,7 +207,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. - TDocument GetById(TKey id, string partitionKey = null) + TDocument GetById(TKey id, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -246,7 +246,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A mongodb filter definition. /// A mongodb filter option. /// An optional partition key. - TDocument GetOne(FilterDefinition condition, FindOptions findOption = null, string partitionKey = null) + TDocument GetOne(FilterDefinition condition, FindOptions findOption = null, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -257,7 +257,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. - TDocument GetOne(Expression> filter, string partitionKey = null) + TDocument GetOne(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -307,7 +307,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A mongodb counting option. /// An optional partition key. bool Any(FilterDefinition condition, CountOptions countOption = null, - string partitionKey = null) + string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -318,7 +318,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. - bool Any(Expression> filter, string partitionKey = null) + bool Any(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -357,7 +357,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A mongodb filter option. /// An optional partition key. List GetAll(FilterDefinition condition, FindOptions findOption = null, - string partitionKey = null) + string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -368,7 +368,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. - List GetAll(Expression> filter, string partitionKey = null) + List GetAll(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -407,7 +407,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A mongodb counting option. /// An optional partitionKey long Count(FilterDefinition condition, CountOptions countOption = null, - string partitionKey = null) + string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -418,7 +418,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partitionKey - long Count(Expression> filter, string partitionKey = null) + long Count(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -443,7 +443,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A LINQ expression filter. /// A property selector to order by descending. /// An optional partitionKey. - TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -468,7 +468,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A LINQ expression filter. /// A property selector to order by ascending. /// An optional partitionKey. - TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) + TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -495,7 +495,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A LINQ expression filter. /// A property selector to order by ascending. /// An optional partitionKey. - TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; @@ -522,7 +522,7 @@ namespace MongoDbGenericRepository.DataAccess.Read /// A LINQ expression filter. /// A property selector to order by ascending. /// An optional partition key. - TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable; diff --git a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.GroupBy.cs b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.GroupBy.cs new file mode 100644 index 0000000..35185b3 --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.GroupBy.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDbGenericRepository.Models; + +namespace MongoDbGenericRepository.DataAccess.Read +{ + public partial class MongoDbReader + { + /// + public virtual List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null, CancellationToken cancellationToken = default) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + return HandlePartitioned(partitionKey) + .Aggregate() + .Group(groupingCriteria, groupProjection) + .ToList(cancellationToken:cancellationToken); + } + + /// + public virtual List GroupBy( + Expression> filter, + Expression> selector, + Expression, TProjection>> projection, + string partitionKey = null, + CancellationToken cancellationToken = default) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + var collection = HandlePartitioned(partitionKey); + return collection.Aggregate() + .Match(Builders.Filter.Where(filter)) + .Group(selector, projection) + .ToList(cancellationToken); + } + + /// + public virtual async Task> GroupByAsync( + Expression> filter, + Expression> selector, + Expression, TProjection>> projection, + string partitionKey = null, + CancellationToken cancellationToken = default) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + var collection = HandlePartitioned(partitionKey); + return await collection.Aggregate() + .Match(Builders.Filter.Where(filter)) + .Group(selector, projection) + .ToListAsync(cancellationToken); + } + + /// + public virtual async Task> GetSortedPaginatedAsync( + Expression> filter, + Expression> sortSelector, + bool ascending = true, + int skipNumber = 0, + int takeNumber = 50, + string partitionKey = null, + CancellationToken cancellationToken = default) + where TDocument : IDocument + where TKey : IEquatable + { + var sorting = ascending + ? Builders.Sort.Ascending(sortSelector) + : Builders.Sort.Descending(sortSelector); + + return await HandlePartitioned(partitionKey) + .Find(filter) + .Sort(sorting) + .Skip(skipNumber) + .Limit(takeNumber) + .ToListAsync(cancellationToken); + } + + /// + public virtual async Task> GetSortedPaginatedAsync( + Expression> filter, + SortDefinition sortDefinition, + int skipNumber = 0, + int takeNumber = 50, + string partitionKey = null, + CancellationToken cancellationToken = default) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey) + .Find(filter) + .Sort(sortDefinition) + .Skip(skipNumber) + .Limit(takeNumber) + .ToListAsync(cancellationToken); + } + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs index 7252cc4..05ab62d 100644 --- a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs +++ b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs @@ -1,39 +1,32 @@ -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using MongoDbGenericRepository.DataAccess.Base; -using MongoDbGenericRepository.Models; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Base; +using MongoDbGenericRepository.Models; namespace MongoDbGenericRepository.DataAccess.Read { /// - /// A class to read MongoDb document. + /// A class to read MongoDb document. /// - public partial class MongoDbReader : DataAccessBase + public partial class MongoDbReader : DataAccessBase, IMongoDbReader { /// - /// The construct of the MongoDbReader class. + /// The construct of the MongoDbReader class. /// - /// A instance. + /// A instance. public MongoDbReader(IMongoDbContext mongoDbContext) : base(mongoDbContext) { } #region Read TKey - /// - /// Asynchronously returns one document given its id. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The Id of the document you want to get. - /// An optional partition key. - /// An optional cancellation Token. + /// public virtual async Task GetByIdAsync(TKey id, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable @@ -42,90 +35,62 @@ namespace MongoDbGenericRepository.DataAccess.Read return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(cancellationToken); } - /// - /// Returns one document given its id. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public virtual TDocument GetById(TKey id, string partitionKey = null) + /// + public virtual TDocument GetById(TKey id, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", id); - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(cancellationToken); } - /// - /// Asynchronously returns one document given filter definition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb filter option. - /// An optional partition key. - /// An optional cancellation Token. - public virtual Task GetOneAsync(FilterDefinition condition, FindOptions findOption = null, + /// + public virtual Task GetOneAsync( + FilterDefinition condition, + FindOptions findOption = null, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(condition, findOption).FirstOrDefaultAsync(cancellationToken); + return HandlePartitioned(partitionKey).Find(condition, findOption).FirstOrDefaultAsync(cancellationToken); } - /// - /// Returns one document given filter definition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb filter option. - /// An optional partition key. - public virtual TDocument GetOne(FilterDefinition condition, FindOptions findOption = null, string partitionKey = null) + /// + public virtual TDocument GetOne( + FilterDefinition condition, + FindOptions findOption = null, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(condition, findOption).FirstOrDefault(); + return HandlePartitioned(partitionKey).Find(condition, findOption).FirstOrDefault(cancellationToken); } - /// - /// Asynchronously returns one document given an expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task GetOneAsync(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task GetOneAsync( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(cancellationToken); } - /// - /// Returns one document given an expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public virtual TDocument GetOne(Expression> filter, string partitionKey = null) + /// + public virtual TDocument GetOne( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(cancellationToken); } - /// - /// Returns a collection cursor. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. + /// public virtual IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable @@ -133,16 +98,11 @@ namespace MongoDbGenericRepository.DataAccess.Read return HandlePartitioned(partitionKey).Find(filter); } - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb counting option. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task AnyAsync(FilterDefinition condition, CountOptions countOption = null, string partitionKey = null, + /// + public virtual async Task AnyAsync( + FilterDefinition condition, + CountOptions countOption = null, + string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable @@ -151,396 +111,297 @@ namespace MongoDbGenericRepository.DataAccess.Read return count > 0; } - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb counting option. - /// An optional partition key. - public virtual bool Any(FilterDefinition condition, CountOptions countOption = null, - string partitionKey = null) + /// + public virtual bool Any( + FilterDefinition condition, + CountOptions countOption = null, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - var count = HandlePartitioned(partitionKey).CountDocuments(condition, countOption); + var count = HandlePartitioned(partitionKey).CountDocuments(condition, countOption, cancellationToken); return count > 0; } - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task AnyAsync(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task AnyAsync( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter, cancellationToken: cancellationToken); - return (count > 0); + return count > 0; } - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public virtual bool Any(Expression> filter, string partitionKey = null) + /// + public virtual bool Any( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - var count = HandlePartitioned(partitionKey).CountDocuments(filter); - return (count > 0); + var count = HandlePartitioned(partitionKey).CountDocuments(filter, cancellationToken: cancellationToken); + return count > 0; } - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb filter option. - /// An optional partition key. - /// An optional cancellation Token. - public virtual Task> GetAllAsync(FilterDefinition condition, - FindOptions findOption = null, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual Task> GetAllAsync( + FilterDefinition condition, + FindOptions findOption = null, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(condition, findOption).ToListAsync(cancellationToken); } - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb filter option. - /// An optional partition key. - public virtual List GetAll(FilterDefinition condition, FindOptions findOption = null, - string partitionKey = null) + /// + public virtual List GetAll( + FilterDefinition condition, + FindOptions findOption = null, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(condition, findOption).ToList(); + return HandlePartitioned(partitionKey).Find(condition, findOption).ToList(cancellationToken); } - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task> GetAllAsync(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task> GetAllAsync( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(cancellationToken); } - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public virtual List GetAll(Expression> filter, string partitionKey = null) + /// + public virtual List GetAll( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(filter).ToList(); + return HandlePartitioned(partitionKey).Find(filter).ToList(cancellationToken); } - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb counting option. - /// An optional partitionKey - /// An optional cancellation Token. - public virtual Task CountAsync(FilterDefinition condition, CountOptions countOption = null, - string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual Task CountAsync( + FilterDefinition condition, + CountOptions countOption = null, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return HandlePartitioned(partitionKey).CountDocumentsAsync(condition, countOption, cancellationToken); } - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A mongodb filter definition. - /// A mongodb counting option. - /// An optional partitionKey - public virtual long Count(FilterDefinition condition, CountOptions countOption = null, - string partitionKey = null) + /// + public virtual long Count( + FilterDefinition condition, + CountOptions countOption = null, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).CountDocuments(condition, countOption); + return HandlePartitioned(partitionKey).CountDocuments(condition, countOption, cancellationToken); } - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partitionKey - /// An optional cancellation Token. - public virtual async Task CountAsync(Expression> filter, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task CountAsync( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter, cancellationToken: cancellationToken); } - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public virtual long Count(Expression> filter, string partitionKey = null) + /// + public virtual long Count( + Expression> filter, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + return HandlePartitioned(partitionKey).Find(filter).CountDocuments(cancellationToken); } #endregion #region Min / Max - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - /// An optional cancellation Token. - public virtual async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task GetByMaxAsync( + Expression> filter, + Expression> maxValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefaultAsync(cancellationToken); + .SortByDescending(maxValueSelector) + .Limit(1) + .FirstOrDefaultAsync(cancellationToken); } - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - public virtual TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + /// + public virtual TDocument GetByMax( + Expression> filter, + Expression> maxValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefault(); + .SortByDescending(maxValueSelector) + .Limit(1) + .FirstOrDefault(cancellationToken); } - /// - /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - /// An optional cancellation Token. - public virtual async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task GetByMinAsync( + Expression> filter, + Expression> minValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefaultAsync(cancellationToken); + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefaultAsync(cancellationToken); } - /// - /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public virtual TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) + /// + public virtual TDocument GetByMin( + Expression> filter, + Expression> minValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefault(); + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefault(cancellationToken); } - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the field for which you want the maximum value. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - /// An optional cancellation Token. - public virtual async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task GetMaxValueAsync( + Expression> filter, + Expression> maxValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefaultAsync(cancellationToken); + .Project(maxValueSelector) + .FirstOrDefaultAsync(cancellationToken); } - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public virtual TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + /// + public virtual TValue GetMaxValue( + Expression> filter, + Expression> maxValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefault(); + .Project(maxValueSelector) + .FirstOrDefault(cancellationToken); } - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task GetMinValueAsync( + Expression> filter, + Expression> minValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(cancellationToken); + return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector) + .FirstOrDefaultAsync(cancellationToken); } - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + /// + public virtual TValue GetMinValue( + Expression> filter, + Expression> minValueSelector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { - return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); + return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector) + .FirstOrDefault(cancellationToken); } - #endregion Min / Max #region Sum TKey - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - /// An optional cancellation Token. - public virtual async Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null, - CancellationToken cancellationToken = default) + /// + public virtual async Task SumByAsync( + Expression> filter, + Expression> selector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await GetQuery(filter, partitionKey).SumAsync(selector, cancellationToken); } - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - public virtual int SumBy(Expression> filter, - Expression> selector, - string partitionKey = null) + /// + public virtual int SumBy( + Expression> filter, + Expression> selector, + string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetQuery(filter, partitionKey).Sum(selector); } - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - /// An optional cancellation Token. - public virtual async Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null, CancellationToken cancellationToken = default) + /// + public virtual async Task SumByAsync( + Expression> filter, + Expression> selector, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable { return await GetQuery(filter, partitionKey).SumAsync(selector, cancellationToken); } - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - public virtual decimal SumBy(Expression> filter, - Expression> selector, - string partitionKey = null) + /// + public virtual decimal SumBy( + Expression> filter, + Expression> selector, + string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { @@ -549,155 +410,4 @@ namespace MongoDbGenericRepository.DataAccess.Read #endregion Sum TKey } - - public partial class MongoDbReader - { - /// - /// Groups a collection of documents given a grouping criteria, - /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - public virtual List GroupBy( - Expression> groupingCriteria, - Expression, TProjection>> groupProjection, - string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class, new() - { - return HandlePartitioned(partitionKey) - .Aggregate() - .Group(groupingCriteria, groupProjection) - .ToList(); - - } - - /// - /// Groups filtered a collection of documents given a grouping criteria, - /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// A LINQ expression filter. - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - public virtual List GroupBy( - Expression> filter, - Expression> selector, - Expression, TProjection>> projection, - string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class, new() - { - var collection = HandlePartitioned(partitionKey); - return collection.Aggregate() - .Match(Builders.Filter.Where(filter)) - .Group(selector, projection) - .ToList(); - } - - /// - /// Groups filtered a collection of documents given a grouping criteria, - /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// A LINQ expression filter. - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - /// An optional cancellation Token. - public virtual async Task> GroupByAsync( - Expression> filter, - Expression> selector, - Expression, TProjection>> projection, - string partitionKey = null, - CancellationToken cancellationToken = default) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class, new() - { - var collection = HandlePartitioned(partitionKey); - return await collection.Aggregate() - .Match(Builders.Filter.Where(filter)) - .Group(selector, projection) - .ToListAsync(cancellationToken); - } - - /// - /// Asynchronously returns a paginated list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The property selector. - /// Order of the sorting. - /// The number of documents you want to skip. Default value is 0. - /// The number of documents you want to take. Default value is 50. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task> GetSortedPaginatedAsync( - Expression> filter, - Expression> sortSelector, - bool ascending = true, - int skipNumber = 0, - int takeNumber = 50, - string partitionKey = null, - CancellationToken cancellationToken = default) - where TDocument : IDocument - where TKey : IEquatable - { - var sorting = ascending - ? Builders.Sort.Ascending(sortSelector) - : Builders.Sort.Descending(sortSelector); - - return await HandlePartitioned(partitionKey) - .Find(filter) - .Sort(sorting) - .Skip(skipNumber) - .Limit(takeNumber) - .ToListAsync(cancellationToken); - } - - /// - /// Asynchronously returns a paginated list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The sort definition. - /// The number of documents you want to skip. Default value is 0. - /// The number of documents you want to take. Default value is 50. - /// An optional partition key. - /// An optional cancellation Token. - public virtual async Task> GetSortedPaginatedAsync( - Expression> filter, - SortDefinition sortDefinition, - int skipNumber = 0, - int takeNumber = 50, - string partitionKey = null, - CancellationToken cancellationToken = default) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey) - .Find(filter) - .Sort(sortDefinition) - .Skip(skipNumber) - .Limit(takeNumber) - .ToListAsync(cancellationToken); - } - } -} +} \ No newline at end of file diff --git a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs index 61639ee..ebf0c98 100644 --- a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs +++ b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs @@ -1,73 +1,35 @@ -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using MongoDbGenericRepository.Models; -using System; +using System; using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDbGenericRepository.Models; namespace MongoDbGenericRepository.DataAccess.Read { - public partial class MongoDbReader : IMongoDbReader + public partial class MongoDbReader { - /// - /// Asynchronously returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - /// An optional cancellation Token. + /// public virtual async Task ProjectOneAsync( - Expression> filter, - Expression> projection, + Expression> filter, + Expression> projection, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable where TProjection : class { - return await HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .FirstOrDefaultAsync(cancellationToken); + return await HandlePartitioned(partitionKey) + .Find(filter) + .Project(projection) + .FirstOrDefaultAsync(cancellationToken); } - /// - /// Returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class - { - return HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .FirstOrDefault(); - } - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - /// An optional cancellation Token. + /// public virtual async Task> ProjectManyAsync( - Expression> filter, - Expression> projection, + Expression> filter, + Expression> projection, string partitionKey = null, CancellationToken cancellationToken = default) where TDocument : IDocument @@ -75,27 +37,38 @@ namespace MongoDbGenericRepository.DataAccess.Read where TProjection : class { return await HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .ToListAsync(cancellationToken); + .Project(projection) + .ToListAsync(cancellationToken); } - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// The document filter. - /// The projection expression. - /// An optional partition key. - public virtual List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + /// + public virtual TProjection ProjectOne( + Expression> filter, + Expression> projection, + string partitionKey = null, + CancellationToken cancellationToken = default) where TDocument : IDocument where TKey : IEquatable where TProjection : class { return HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .ToList(); + .Project(projection) + .FirstOrDefault(cancellationToken); + } + + /// + public virtual List ProjectMany( + Expression> filter, + Expression> projection, + string partitionKey = null, + CancellationToken cancellationToken = default) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return HandlePartitioned(partitionKey).Find(filter) + .Project(projection) + .ToList(cancellationToken); } } -} +} \ No newline at end of file