diff --git a/CoreIntegrationTests/CRUDObjectIdTests.cs b/CoreIntegrationTests/CRUDObjectIdTests.cs index 335043f..8a03de0 100644 --- a/CoreIntegrationTests/CRUDObjectIdTests.cs +++ b/CoreIntegrationTests/CRUDObjectIdTests.cs @@ -1,6 +1,6 @@ using CoreIntegrationTests.Infrastructure; using MongoDB.Bson; -using System; + namespace CoreIntegrationTests { public class CoreObjectIdTestDocument : TestDoc diff --git a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs index c70056c..a1f3944 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs @@ -235,7 +235,7 @@ namespace CoreIntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.True(1 == count, GetTestName()); } @@ -1078,7 +1078,7 @@ namespace CoreIntegrationTests.Infrastructure #region Math [Fact] - public async Task SumByAsync() + public async Task SumByDecimalAsync() { // Arrange var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; @@ -1100,6 +1100,29 @@ namespace CoreIntegrationTests.Infrastructure Assert.Equal(expectedSum, result); } + [Fact] + public void SumByDecimal() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => + { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.Nested.SomeAmount = 5m; + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedSum = documents.Sum(e => e.Nested.SomeAmount); + + // Act + var result = SUT.SumBy(e => e.SomeContent == criteria, e => e.Nested.SomeAmount, PartitionKey); + + // Assert + Assert.Equal(expectedSum, result); + } + #endregion Math #region Test Utils diff --git a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index 9d99665..e4b0843 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -236,7 +236,7 @@ namespace CoreIntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.True (1 == count, GetTestName()); } @@ -1071,7 +1071,7 @@ namespace CoreIntegrationTests.Infrastructure #region Math [Fact] - public async Task SumByAsync() + public async Task SumByDecimalAsync() { // Arrange var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; @@ -1093,6 +1093,29 @@ namespace CoreIntegrationTests.Infrastructure Assert.Equal(expectedSum, result); } + [Fact] + public void SumByDecimal() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => + { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.Nested.SomeAmount = 5m; + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedSum = documents.Sum(e => e.Nested.SomeAmount); + + // Act + var result = SUT.SumBy(e => e.SomeContent == criteria, e => e.Nested.SomeAmount, PartitionKey); + + // Assert + Assert.Equal(expectedSum, result); + } + #endregion Math #region Test Utils diff --git a/IntegrationTests/App.config b/IntegrationTests/App.config index fb9836a..beb386a 100644 --- a/IntegrationTests/App.config +++ b/IntegrationTests/App.config @@ -11,7 +11,7 @@ - + diff --git a/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs b/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs index ebd66e2..ea3dfd6 100644 --- a/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs +++ b/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs @@ -202,7 +202,7 @@ namespace IntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.AreEqual(1, count, GetTestName()); } diff --git a/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index 3d0cf8c..e6b87d9 100644 --- a/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -204,7 +204,7 @@ namespace IntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.AreEqual(1, count, GetTestName()); } diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj index c5b56bc..9a6c6b3 100644 --- a/IntegrationTests/IntegrationTests.csproj +++ b/IntegrationTests/IntegrationTests.csproj @@ -30,33 +30,32 @@ 4 - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\DnsClient.dll + + ..\packages\DnsClient.1.2.0\lib\net45\DnsClient.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDB.Bson.dll + + ..\packages\MongoDB.Bson.2.8.0\lib\net452\MongoDB.Bson.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDB.Driver.dll + + ..\packages\MongoDB.Driver.2.8.0\lib\net452\MongoDB.Driver.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDB.Driver.Core.dll - - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDbGenericRepository.dll + + ..\packages\MongoDB.Driver.Core.2.8.0\lib\net452\MongoDB.Driver.Core.dll ..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\System.Buffers.dll + + ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True @@ -86,5 +85,11 @@ + + + {efc776c4-2af3-440c-be80-3fbe335817a5} + MongoDbGenericRepository + + \ No newline at end of file diff --git a/IntegrationTests/packages.config b/IntegrationTests/packages.config index 94c72ae..1d92b40 100644 --- a/IntegrationTests/packages.config +++ b/IntegrationTests/packages.config @@ -1,12 +1,11 @@  - - - - - + + + + - - + + \ No newline at end of file diff --git a/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs new file mode 100644 index 0000000..a2b42c1 --- /dev/null +++ b/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDbGenericRepository.Models; + +namespace MongoDbGenericRepository +{ + public interface IKeyTypedReadOnlyMongoRepository : IBaseReadOnlyRepository + where TKey : IEquatable + { + #region Read + + /// + /// Asynchronously returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns a collection cursor. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + #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. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + /// + TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// 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. + Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// 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. + TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument; + + #endregion + + #region Maths + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + int SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + decimal SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + #endregion Maths + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs index a79d3e9..a5e295e 100644 --- a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs @@ -1,458 +1,11 @@ -using MongoDB.Driver; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Linq.Expressions; -using MongoDbGenericRepository.Models; +using System; namespace MongoDbGenericRepository { /// /// The IReadOnlyMongoRepository exposes the readonly functionality of the BaseMongoRepository. /// - public interface IReadOnlyMongoRepository + public interface IReadOnlyMongoRepository : IBaseReadOnlyRepository, IKeyTypedReadOnlyMongoRepository { - /// - /// The connection string. - /// - string ConnectionString { get; set; } - /// - /// The database name. - /// - string DatabaseName { get; set; } - - #region Read - - /// - /// Asynchronously returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - Task GetByIdAsync(Guid id, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - TDocument GetById(Guid id, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns a collection cursor. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - #endregion - - #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. - Task GetByIdAsync(TKey id, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - TDocument GetById(TKey id, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - Task GetOneAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - TDocument GetOne(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - IFindFluent GetCursor(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - - /// - /// 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. - Task AnyAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - bool Any(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - Task> GetAllAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - List GetAll(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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 - Task CountAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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 - long Count(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - #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. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - /// - TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// 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. - Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// 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. - TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument; - - /// - /// 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. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument; - - /// - /// 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. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - TValue GetMaxValue(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// 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. - Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument; - - /// - /// 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. - Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// 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. - TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument; - - /// - /// 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. - TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - #endregion - - #region Sum - - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument; - - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - #endregion Sum } - } diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs index f8c9c75..db9dd3d 100644 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/BaseMongoDbRepository.cs @@ -20,9 +20,8 @@ namespace MongoDbGenericRepository /// /// The connection string of the MongoDb server. /// The name of the database against which you want to perform operations. - protected BaseMongoRepository(string connectionString, string databaseName) : base(connectionString, databaseName) + protected BaseMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) { - MongoDbContext = new MongoDbContext(connectionString, databaseName); } /// @@ -31,7 +30,6 @@ namespace MongoDbGenericRepository /// A mongodb context implementing protected BaseMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) { - MongoDbContext = mongoDbContext; } /// @@ -40,7 +38,6 @@ namespace MongoDbGenericRepository /// A mongodb context implementing protected BaseMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) { - MongoDbContext = new MongoDbContext(mongoDatabase); } #region Create diff --git a/MongoDbGenericRepository/BaseRepository.cs b/MongoDbGenericRepository/BaseRepository.cs new file mode 100644 index 0000000..823c1f8 --- /dev/null +++ b/MongoDbGenericRepository/BaseRepository.cs @@ -0,0 +1,843 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseReadOnlyRepository + { + /// + /// The connection string. + /// + string ConnectionString { get; } + + /// + /// The database name. + /// + string DatabaseName { get; } + + #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. + Task GetByIdAsync(TKey id, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + TDocument GetById(TKey id, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + Task GetOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + TDocument GetOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + IFindFluent GetCursor(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + + /// + /// 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. + Task AnyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + bool Any(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + Task> GetAllAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + List GetAll(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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 + Task CountAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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 + long Count(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + #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. + Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TValue GetMaxValue(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// 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. + TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + #endregion + + #region Sum + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + int SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + decimal SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + #endregion Sum + } + + public class BaseReadOnlyRepository : IBaseReadOnlyRepository + { + /// + /// The connection string. + /// + public string ConnectionString { get; } + + /// + /// The database name. + /// + public string DatabaseName { get; } + + /// + /// The MongoDbContext + /// + protected IMongoDbContext MongoDbContext = null; + + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected BaseReadOnlyRepository(string connectionString, string databaseName = null) + { + if (databaseName == null) + { + var mongoUrl = new MongoUrl(connectionString); + databaseName = databaseName ?? mongoUrl.DatabaseName; + } + ConnectionString = connectionString; + DatabaseName = databaseName; + MongoDbContext = new MongoDbContext(connectionString, databaseName); + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected BaseReadOnlyRepository(IMongoDbContext mongoDbContext) + { + MongoDbContext = mongoDbContext; + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected BaseReadOnlyRepository(IMongoDatabase mongoDatabase) + { + MongoDbContext = new MongoDbContext(mongoDatabase); + } + + + #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. + public async Task GetByIdAsync(TKey id, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", id); + return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); + } + + /// + /// 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 TDocument GetById(TKey id, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", id); + return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + } + + /// + /// 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. + public async Task GetOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); + } + + /// + /// 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 TDocument GetOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + } + + /// + /// 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 IFindFluent GetCursor(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + 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 LINQ expression filter. + /// An optional partition key. + public async Task AnyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); + 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 bool Any(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var count = HandlePartitioned(partitionKey).CountDocuments(filter); + 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 LINQ expression filter. + /// An optional partition key. + public async Task> GetAllAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); + } + + /// + /// 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 List GetAll(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return HandlePartitioned(partitionKey).Find(filter).ToList(); + } + + /// + /// 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 + public async Task CountAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); + } + + /// + /// 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 long Count(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + } + + /// + /// 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 async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(maxValueSelector) + .Limit(1) + .FirstOrDefaultAsync(); + } + + /// + /// 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 TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(maxValueSelector) + .Limit(1) + .FirstOrDefault(); + } + + /// + /// 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 async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefaultAsync(); + } + + /// + /// 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 TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefault(); + } + + /// + /// 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. + private IFindFluent GetMinMongoQuery(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(ConvertExpression(minValueSelector)) + .Limit(1); + } + + /// + /// 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 descending. + /// An optional partition key. + private IFindFluent GetMaxMongoQuery(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(ConvertExpression(maxValueSelector)) + .Limit(1); + } + + /// + /// 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. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey) + .Project(maxValueSelector) + .FirstOrDefaultAsync(); + } + + /// + /// 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 TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + + return GetMaxMongoQuery(filter, maxValueSelector, partitionKey) + .Project(maxValueSelector) + .FirstOrDefault(); + } + + /// + /// 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 async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); + } + + /// + /// 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) + where TDocument : IDocument + where TKey : IEquatable + { + return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); + } + + #endregion + + #region Sum TKey + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetQuery(filter, partitionKey).SumAsync(selector); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing 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) + 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. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetQuery(filter, partitionKey).SumAsync(selector); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing 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) + where TDocument : IDocument + where TKey : IEquatable + { + return GetQuery(filter, partitionKey).Sum(selector); + } + + #endregion Sums TKey + + #region Utility Methods + + protected IMongoQueryable GetQuery(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).AsQueryable().Where(filter); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The document. + /// + protected virtual IMongoCollection HandlePartitioned(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + if (document is IPartitionedDocument) + { + return GetCollection(((IPartitionedDocument)document).PartitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for the type TDocument with a partition key. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + protected virtual IMongoCollection GetCollection(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbContext.GetCollection(partitionKey); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + protected virtual IMongoCollection HandlePartitioned(string partitionKey) + where TDocument : IDocument + where TKey : IEquatable + { + if (!string.IsNullOrEmpty(partitionKey)) + { + return GetCollection(partitionKey); + } + return GetCollection(); + } + + /// + /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object + /// + /// The document type. + /// The type of the value. + /// The expression to convert + protected static Expression> ConvertExpression(Expression> expression) + { + var param = expression.Parameters[0]; + Expression body = expression.Body; + var convert = Expression.Convert(body, typeof(object)); + return Expression.Lambda>(convert, param); + } + + #endregion + } +} diff --git a/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs b/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs new file mode 100644 index 0000000..88d6f25 --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs @@ -0,0 +1,151 @@ +using MongoDB.Driver; +using MongoDbGenericRepository.Models; +using MongoDbGenericRepository.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + /// + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. + /// + /// + public abstract class KeyTypedBaseMongoDbRepository : KeyTypedReadOnlyMongoRepository, IKeyTypedReadOnlyMongoRepository where TKey : IEquatable + { + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected KeyTypedBaseMongoDbRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedBaseMongoDbRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedBaseMongoDbRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + { + } + + #region Create + + /// + /// Asynchronously adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The document you want to add. + public virtual async Task AddOneAsync(TDocument document) where TDocument : IDocument + { + FormatDocument(document); + await HandlePartitioned(document).InsertOneAsync(document); + } + + /// + /// Adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The document you want to add. + public virtual void AddOne(TDocument document) where TDocument : IDocument + { + FormatDocument(document); + HandlePartitioned(document).InsertOne(document); + } + + /// + /// Asynchronously adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The documents you want to add. + public virtual async Task AddManyAsync(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return; + } + foreach (var document in documents) + { + FormatDocument(document); + } + // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 + if (documents.Any(e => e is IPartitionedDocument)) + { + foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) + { + await HandlePartitioned(group.FirstOrDefault()).InsertManyAsync(group.ToList()); + } + } + else + { + await GetCollection().InsertManyAsync(documents.ToList()); + } + } + + /// + /// Adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The documents you want to add. + public virtual void AddMany(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return; + } + foreach (var document in documents) + { + FormatDocument(document); + } + // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 + if (documents.Any(e => e is IPartitionedDocument)) + { + foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) + { + HandlePartitioned(group.FirstOrDefault()).InsertMany(group.ToList()); + } + } + else + { + GetCollection().InsertMany(documents.ToList()); + } + } + + #endregion Create + + /// + /// Sets the value of the document Id if it is not set already. + /// + /// The document type. + /// The document. + protected void FormatDocument(TDocument document) where TDocument : IDocument + { + if (document == null) + { + throw new ArgumentNullException(nameof(document)); + } + var defaultTKey = default(TKey); + if (document.Id == null + || (defaultTKey != null + && defaultTKey.Equals(document.Id))) + { + document.Id = IdGenerator.GetId(); + } + } + } +} diff --git a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs new file mode 100644 index 0000000..3f3d37f --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs @@ -0,0 +1,390 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + /// + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. + /// + public abstract class KeyTypedReadOnlyMongoRepository : BaseReadOnlyRepository, IKeyTypedReadOnlyMongoRepository where TKey : IEquatable + { + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected KeyTypedReadOnlyMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + { + } + + #region Read + + /// + /// Asynchronously returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + public async Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument + { + return await base.GetByIdAsync(id, partitionKey); + } + + /// + /// Returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + public TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument + { + return base.GetById(id, partitionKey); + } + + /// + /// Asynchronously returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await base.GetOneAsync(filter, partitionKey); + } + + /// + /// Returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return base.GetOne(filter, partitionKey); + } + + /// + /// Returns a collection cursor. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return base.GetCursor(filter, partitionKey); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await base.AnyAsync(filter, partitionKey); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return base.Any(filter, partitionKey); + } + + /// + /// Asynchronously returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await base.GetAllAsync(filter, partitionKey); + } + + /// + /// Returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return base.GetAll(filter, partitionKey); + } + + /// + /// Asynchronously counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partitionKey + public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await base.CountAsync(filter, partitionKey); + } + + /// + /// Counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partitionKey + public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return base.Count(filter, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await base.GetByMaxAsync(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + /// + public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return base.GetByMax(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await base.GetByMinAsync(filter, minValueSelector, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return base.GetByMin(filter, minValueSelector, partitionKey); + } + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// 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 async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await base.GetMaxValueAsync(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// 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 TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return base.GetMaxValue(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// 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 async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await base.GetMinValueAsync(filter, minValueSelector, partitionKey); + } + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// 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) + where TDocument : IDocument + { + return base.GetMinValue(filter, minValueSelector, partitionKey); + } + + #endregion + + #region Maths + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + { + return await base.SumByAsync(filter, selector, partitionKey); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + { + return await base.SumByAsync(filter, selector, partitionKey); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing 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) + where TDocument : IDocument + { + return base.SumBy(filter, selector, partitionKey); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing 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) + where TDocument : IDocument + { + return base.SumBy(filter, selector, partitionKey); + } + + #endregion Maths + + #region Utility Methods + + /// + /// Gets a collections for the type TDocument with the matching partition key (if any). + /// + /// The document type. + /// An optional partition key. + /// An + protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument + { + return MongoDbContext.GetCollection(partitionKey); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The document. + /// + protected virtual IMongoCollection HandlePartitioned(TDocument document) + where TDocument : IDocument + { + if (document is IPartitionedDocument) + { + return GetCollection(((IPartitionedDocument)document).PartitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + protected virtual IMongoCollection HandlePartitioned(string partitionKey) + where TDocument : IDocument + { + if (!string.IsNullOrEmpty(partitionKey)) + { + return GetCollection(partitionKey); + } + return GetCollection(); + } + + #endregion + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/MongoDbContext.cs b/MongoDbGenericRepository/MongoDbContext.cs index 175c4c4..c5921b9 100644 --- a/MongoDbGenericRepository/MongoDbContext.cs +++ b/MongoDbGenericRepository/MongoDbContext.cs @@ -63,8 +63,8 @@ namespace MongoDbGenericRepository Client = new MongoClient(connectionString); Database = Client.GetDatabase(databaseName); } - - /// + + /// /// The constructor of the MongoDbContext, it needs a connection string and a database name. /// /// The MongoClient. @@ -111,7 +111,7 @@ namespace MongoDbGenericRepository /// Given the document type and the partition key, returns the name of the collection it belongs to. /// /// The type representing a Document. - /// The value of the partition key. + /// The value of the partition key. /// The name of the collection. private string GetCollectionName(string partitionKey) { diff --git a/MongoDbGenericRepository/MongoDbGenericRepository.csproj b/MongoDbGenericRepository/MongoDbGenericRepository.csproj index bed1e2f..55a2c7d 100644 --- a/MongoDbGenericRepository/MongoDbGenericRepository.csproj +++ b/MongoDbGenericRepository/MongoDbGenericRepository.csproj @@ -1,7 +1,7 @@ - + - net45;netstandard1.5;netstandard2.0 + net45;netstandard2.0;netstandard1.5; MongoDbGenericRepository 1.2.0 Alexandre Spieser diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs deleted file mode 100644 index b75fe11..0000000 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs +++ /dev/null @@ -1,52 +0,0 @@ -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using MongoDbGenericRepository.Models; -using System; -using System.Linq; -using System.Linq.Expressions; -using System.Threading.Tasks; - -namespace MongoDbGenericRepository -{ - /// - /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. - /// Its constructor must be given a connection string and a database name. - /// - public abstract partial class ReadOnlyMongoRepository - { - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - public virtual async Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument - { - return await SumByAsync(filter, selector, partitionKey); - } - - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - public virtual async Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection(partitionKey) - .AsQueryable() - .Where(filter) - .SumAsync(selector); - } - - } -} \ No newline at end of file diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs index 7638cdb..fe995a9 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs @@ -1,745 +1,37 @@ using MongoDB.Driver; using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Linq.Expressions; -using MongoDbGenericRepository.Models; -using System.Linq; namespace MongoDbGenericRepository { /// - /// The ReadOnlyMongoRepository implements the readonly functionality of the IReadOnlyMongoRepository. + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. /// - public abstract partial class ReadOnlyMongoRepository : IReadOnlyMongoRepository + public abstract class ReadOnlyMongoRepository : KeyTypedReadOnlyMongoRepository, IReadOnlyMongoRepository { - /// - /// The connection string. - /// - public string ConnectionString { get; set; } - - /// - /// The database name. - /// - public string DatabaseName { get; set; } - - /// - /// The MongoDbContext - /// - protected IMongoDbContext MongoDbContext = null; - /// /// The constructor taking a connection string and a database name. /// /// The connection string of the MongoDb server. /// The name of the database against which you want to perform operations. - protected ReadOnlyMongoRepository(string connectionString, string databaseName) + protected ReadOnlyMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) { - MongoDbContext = new MongoDbContext(connectionString, databaseName); } /// /// The contructor taking a . /// /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) + protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) { - MongoDbContext = mongoDbContext; } /// /// The contructor taking a . /// /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) + protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) { - MongoDbContext = new MongoDbContext(mongoDatabase); } - - #region Read - - /// - /// Asynchronously returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public async Task GetByIdAsync(Guid id, string partitionKey = null) where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", id); - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// Returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public TDocument GetById(Guid id, string partitionKey = null) where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", id); - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// Asynchronously returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// Returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// Returns a collection cursor. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter); - } - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - return (count > 0); - } - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - var count = HandlePartitioned(partitionKey).CountDocuments(filter); - return (count > 0); - } - - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); - } - - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter).ToList(); - } - - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - } - - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetByMaxAsync(filter, maxValueSelector, partitionKey); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - /// - public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return GetByMax(filter, maxValueSelector, partitionKey); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetByMinAsync(filter, minValueSelector, partitionKey); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument - { - return GetByMin(filter, orderByAscending, partitionKey); - } - - #endregion - - #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. - public async Task GetByIdAsync(TKey id, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", id); - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// 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 TDocument GetById(TKey id, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", id); - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// 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. - public async Task GetOneAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// 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 TDocument GetOne(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// 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 IFindFluent GetCursor(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - 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 LINQ expression filter. - /// An optional partition key. - public async Task AnyAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - 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 bool Any(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var count = HandlePartitioned(partitionKey).CountDocuments(filter); - 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 LINQ expression filter. - /// An optional partition key. - public async Task> GetAllAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); - } - - /// - /// 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 List GetAll(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter).ToList(); - } - - /// - /// 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 - public async Task CountAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - } - - /// - /// 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 long Count(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); - } - - /// - /// 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 async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); - } - - /// - /// 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 TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefault(); - } - - /// - /// 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 async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); - } - - /// - /// 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 TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefault(); - } - - /// - /// 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. - private IFindFluent GetMinMongoQuery(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(ConvertExpression(minValueSelector)) - .Limit(1); - } - - /// - /// 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 descending. - /// An optional partition key. - private IFindFluent GetMaxMongoQuery(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(ConvertExpression(maxValueSelector)) - .Limit(1); - } - - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// 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 async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetMaxValueAsync(filter, maxValueSelector, partitionKey); - } - - /// - /// 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. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefaultAsync(); - } - - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// 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 TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return GetMaxValue(filter, maxValueSelector, partitionKey); - } - - /// - /// 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 TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - - return GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefault(); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// 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 async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetMinValueAsync(filter, minValueSelector, partitionKey); - } - - /// - /// 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 async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// 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) - where TDocument : IDocument - { - return GetMinValue(filter, minValueSelector, partitionKey); - } - - /// - /// 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) - where TDocument : IDocument - where TKey : IEquatable - { - return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); - } - - #endregion - - #region Utility Methods - - /// - /// Gets a collections for the type TDocument with the matching partition key (if any). - /// - /// The document type. - /// An optional partition key. - /// An - protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument - { - return MongoDbContext.GetCollection(partitionKey); - } - - /// - /// Gets a collections for the type TDocument - /// - /// The document type. - /// The document. - /// - protected virtual IMongoCollection HandlePartitioned(TDocument document) where TDocument : IDocument - { - if (document is IPartitionedDocument) - { - return GetCollection(((IPartitionedDocument)document).PartitionKey); - } - return GetCollection(); - } - - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The type of the primary key. - /// The document. - /// - protected virtual IMongoCollection HandlePartitioned(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - if (document is IPartitionedDocument) - { - return GetCollection(((IPartitionedDocument)document).PartitionKey); - } - return GetCollection(); - } - - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The collection partition key. - /// - protected virtual IMongoCollection HandlePartitioned(string partitionKey) where TDocument : IDocument - { - if (!string.IsNullOrEmpty(partitionKey)) - { - return GetCollection(partitionKey); - } - return GetCollection(); - } - - /// - /// Gets a collections for the type TDocument with a partition key. - /// - /// The document type. - /// The type of the primary key. - /// The collection partition key. - /// - protected virtual IMongoCollection GetCollection(string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return MongoDbContext.GetCollection(partitionKey); - } - - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The type of the primary key. - /// The collection partition key. - /// - protected virtual IMongoCollection HandlePartitioned(string partitionKey) - where TDocument : IDocument - where TKey : IEquatable - { - if (!string.IsNullOrEmpty(partitionKey)) - { - return GetCollection(partitionKey); - } - return GetCollection(); - } - - /// - /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object - /// - /// The document type. - /// The type of the value. - /// The expression to convert - protected static Expression> ConvertExpression(Expression> expression) - { - var param = expression.Parameters[0]; - Expression body = expression.Body; - var convert = Expression.Convert(body, typeof(object)); - return Expression.Lambda>(convert, param); - } - - #endregion - } -} +} \ No newline at end of file